Conector Azure Cosmos DB Spark: controle de taxa de transferência

APLICA-SE A: NoSQL

O conector Spark permite que você se comunique com o Azure Cosmos DB usando o Apache Spark. Este artigo descreve como o recurso de controle de taxa de transferência funciona. Confira nossos exemplos do Spark no GitHub para começar a usar o controle de taxa de transferência.

Este artigo documenta o uso de grupos de controle de taxa de transferência global no conector Spark do Azure Cosmos DB, mas a funcionalidade também está disponível no Java SDK. No SDK, você pode usar grupos de controle de taxa de transferência global e local para limitar o consumo de unidade de solicitação (RU) no contexto de uma única instância de conexão de cliente. Por exemplo, você pode aplicar essa abordagem a diferentes operações em um único microsserviço ou talvez a um único programa de carregamento de dados. Para obter mais informações, consulte como usar o controle de taxa de transferência no Java SDK.

Aviso

O controle de taxa de transferência não é suportado no modo de gateway. Atualmente, para contas do Azure Cosmos DB sem servidor, tentar usar targetThroughputThreshold para definir uma porcentagem resulta em falha. Você só pode fornecer um valor absoluto para a taxa de transferência/RU de destino usando spark.cosmos.throughputControl.targetThroughput.

Por que o controle de taxa de transferência é importante?

O controle de taxa de transferência ajuda a isolar as necessidades de desempenho de aplicativos executados em um contêiner. O controle de taxa de transferência limita a quantidade de RUs que um cliente Spark específico pode consumir.

Vários cenários avançados se beneficiam do controle de taxa de transferência do lado do cliente:

  • Diferentes operações e tarefas têm prioridades diferentes: pode haver a necessidade de evitar que as transações normais sejam limitadas devido à ingestão de dados ou atividades de cópia. Algumas operações ou tarefas não são sensíveis à latência e são mais tolerantes a serem limitadas do que outras.
  • Fornecer equidade/isolamento para diferentes usuários ou locatários: um aplicativo geralmente tem muitos usuários. Alguns usuários podem enviar muitas solicitações, o que consome toda a taxa de transferência disponível e faz com que outros sejam limitados.
  • Balanceamento de carga da taxa de transferência entre diferentes clientes do Azure Cosmos DB: em alguns casos de uso, é importante garantir que todos os clientes recebam uma parcela justa (igual) da taxa de transferência.

O controle de taxa de transferência permite a capacidade de limitar a taxa de RU de nível mais granular, conforme necessário.

Como funciona o controle de taxa de transferência?

Para configurar o controle de taxa de transferência para o conector Spark, primeiro crie um contêiner que defina metadados de controle de taxa de transferência. A chave de partição está groupId e ttl está ativada. Aqui, você cria esse contêiner usando o Spark SQL e o chama:ThroughputControl

    %sql
    CREATE TABLE IF NOT EXISTS cosmosCatalog.`database-v4`.ThroughputControl 
    USING cosmos.oltp
    OPTIONS(spark.cosmos.database = 'database-v4')
    TBLPROPERTIES(partitionKeyPath = '/groupId', autoScaleMaxThroughput = '4000', indexingPolicy = 'AllProperties', defaultTtlInSeconds = '-1');

O exemplo anterior cria um contêiner com dimensionamento automático. Se preferir o provisionamento padrão, você pode substituir autoScaleMaxThroughput por manualThroughput.

Importante

A chave de partição deve ser definida como e ttl deve ser habilitada para /groupId que o recurso de controle de taxa de transferência funcione.

Na configuração do Spark de um aplicativo específico, você pode especificar parâmetros para a carga de trabalho. O exemplo a seguir define o controle de taxa de transferência como enabled. O exemplo define um parâmetro de grupo name de controle de taxa de transferência e um targetThroughputThreshold parâmetro. Você também define os database parâmetros e container nos quais o grupo de controle de taxa de transferência é mantido:

    "spark.cosmos.throughputControl.enabled" -> "true",
    "spark.cosmos.throughputControl.name" -> "SourceContainerThroughputControl",
    "spark.cosmos.throughputControl.targetThroughputThreshold" -> "0.95", 
    "spark.cosmos.throughputControl.globalControl.database" -> "database-v4", 
    "spark.cosmos.throughputControl.globalControl.container" -> "ThroughputControl"

No exemplo anterior, o targetThroughputThreshold parâmetro é definido como 0,95. O limite de taxa ocorre (e as solicitações são repetidas) quando os clientes consomem mais de 95% (+/- 5-10%) da taxa de transferência alocada para o contêiner. Essa configuração é armazenada como um documento no contêiner de taxa de transferência, que se parece com este exemplo:

    {
        "id": "ZGF0YWJhc2UtdjQvY3VzdG9tZXIvU291cmNlQ29udGFpbmVyVGhyb3VnaHB1dENvbnRyb2w.info",
        "groupId": "database-v4/customer/SourceContainerThroughputControl.config",
        "targetThroughput": "",
        "targetThroughputThreshold": "0.95",
        "isDefault": true,
        "_rid": "EHcYAPolTiABAAAAAAAAAA==",
        "_self": "dbs/EHcYAA==/colls/EHcYAPolTiA=/docs/EHcYAPolTiABAAAAAAAAAA==/",
        "_etag": "\"2101ea83-0000-1100-0000-627503dd0000\"",
        "_attachments": "attachments/",
        "_ts": 1651835869
    }

O controle de taxa de transferência não faz o pré-cálculo de RU de cada operação. Em vez disso, ele rastreia os usos de RU após a operação com base no cabeçalho de resposta. Como tal, o controle de taxa de transferência é baseado em uma aproximação e não garante que a quantidade de taxa de transferência esteja disponível para o grupo em um determinado momento.

Por esse motivo, se a RU configurada for tão baixa que uma única operação possa usar tudo, o controle de taxa de transferência não poderá evitar que a RU exceda o limite configurado. O controle de taxa de transferência funciona melhor quando o limite configurado é maior do que qualquer operação única que um cliente no grupo de controle específico pode executar.

Quando você lê via consulta ou feed de alteração, você deve configurar o tamanho da página em spark.cosmos.read.maxItemCount (padrão 1000) para ser uma quantidade modesta. Desta forma, o controle de taxa de transferência do cliente pode ser recalculado com maior frequência e refletido com mais precisão em qualquer momento específico. Quando você usa o controle de taxa de transferência para um trabalho de gravação em massa, o número de documentos executados em uma única solicitação é ajustado automaticamente com base na taxa de limitação para permitir que o controle de taxa de transferência comece o mais cedo possível.

Aviso

O targetThroughputThreshold parâmetro é imutável. Se você alterar o valor do limite de taxa de transferência de destino, um novo grupo de controle de taxa de transferência será criado. (Se você usar a versão 4.10.0 ou posterior, ela pode ter o mesmo nome.) Você precisa reiniciar todos os trabalhos do Spark que estão usando o grupo se quiser garantir que todos eles consumam o novo limite imediatamente. Caso contrário, eles pegam o novo limite após a próxima reinicialização.

Para cada cliente Spark que usa o grupo de controle de taxa de transferência, um registro é criado no ThroughputControl contêiner, com alguns ttl segundos. Como resultado, os documentos desaparecem rapidamente se um cliente Spark não estiver mais em execução ativa. Eis um exemplo:

    {
        "id": "Zhjdieidjojdook3osk3okso3ksp3ospojsp92939j3299p3oj93pjp93jsps939pkp9ks39kp9339skp",
        "groupId": "database-v4/customer/SourceContainerThroughputControl.config",
        "_etag": "\"1782728-w98999w-ww9998w9-99990000\"",
        "ttl": 10,
        "initializeTime": "2022-06-26T02:24:40.054Z",
        "loadFactor": 0.97636377638898,
        "allocatedThroughput": 484.89444487847,
        "_rid": "EHcYAPolTiABAAAAAAAAAA==",
        "_self": "dbs/EHcYAA==/colls/EHcYAPolTiA=/docs/EHcYAPolTiABAAAAAAAAAA==/",
        "_etag": "\"2101ea83-0000-1100-0000-627503dd0000\"",
        "_attachments": "attachments/",
        "_ts": 1651835869
    }

Em cada registro de cliente, o loadFactor atributo representa a carga no cliente específico, em relação a outros clientes no grupo de controle de taxa de transferência. O allocatedThroughput atributo mostra quantas RUs estão atualmente alocadas a este cliente. O conector Spark ajusta a taxa de transferência alocada para cada cliente com base em sua carga. Dessa forma, cada cliente recebe uma parte da taxa de transferência disponível que é proporcional à sua carga. Todos os clientes juntos não consomem mais do que o total alocado para o grupo de controle de taxa de transferência ao qual pertencem.