Partilhar via


Fragmentação para escalabilidade horizontal no Azure DocumentDB

O Azure DocumentDB suporta sharding para distribuir dados e tráfego horizontalmente. Os documentos dentro de uma coleção são divididos em blocos chamados fragmentos lógicos.

O sharding é definido individualmente para cada coleção usando uma chave de partição designada da estrutura dos documentos da coleção. Os dados são então agrupados em blocos, sendo que cada bloco corresponde a uma partição lógica. Os documentos para cada valor único da propriedade da chave do fragmento residem no mesmo fragmento lógico.

Para cada documento inserido numa coleção fragmentada, o valor da propriedade da chave do shard é transformado em um valor hash para calcular o fragmento lógico designado. A responsabilidade de colocar o shard lógico e distribuir todos os shards lógicos dentro do cluster é abstraída do utilizador e totalmente gerida pelo serviço.

Fragmentos lógicos

Todos os documentos que contêm o mesmo valor para a chave do fragmento pertencem ao mesmo fragmento lógico.

Por exemplo, vamos considerar uma coleção chamada Employees com a estrutura do documento abaixo.

Esta tabela mostra um mapeamento dos valores das chaves do fragmento para partições lógicas.

ID do documento Valor da Chave do Fragmento Fragmento Lógico
"12345" "Steve Smith" Fragmento 1
"23456" "Jane Doe" Fragmento 2
"34567" "Steve Smith" Fragmento 1
"45678" "Michael Smith" Fragmento 3
"56789" "Jane Doe" Fragmento 2
  • Não há limites para o número de fragmentos lógicos de uma coleção. Uma coleção pode ter tantas partições lógicas quantos documentos com um valor único para a chave de partição em cada documento.

  • Também não há limites para o tamanho de um único fragmento lógico.

  • Além disso, o serviço não limita as transações ao âmbito de um shard lógico. O Azure DocumentDB suporta transações de leitura e escrita aplicáveis entre múltiplos shards lógicos e múltiplos shards físicos no cluster.

Fragmentos físicos

Os fragmentos físicos são as máquinas e discos subjacentes responsáveis por persistir os dados e cumprir transações na base de dados. Ao contrário dos fragmentos lógicos, o serviço gere fragmentos físicos em segundo plano.

O número de fragmentos físicos é definido quando um cluster é criado e pode ser aumentado se o tamanho da base de dados crescer ao longo do tempo. Clusters de shard único têm um shard físico (nó) que é inteiramente responsável pelo armazenamento e pelas transações de banco de dados do cluster. Os clusters multishard distribuem os dados e o volume de transações entre os shards físicos do cluster.

Mapear fragmentos lógicos para fragmentos físicos

Quando novos shards lógicos são adicionados, o cluster atualiza de forma fluida o mapeamento dos shards lógicos para físicos. De forma semelhante, a atribuição do espaço de endereçamento a cada shard físico é alterada à medida que novos shards físicos são adicionados ao cluster, após o que os shards lógicos são reequilibrados em todo o cluster.

O intervalo de hash usado para mapear fragmentos lógicos e físicos está distribuido uniformemente entre os fragmentos físicos do cluster. Cada fragmento físico possui um balde de tamanho uniforme da gama de hash. Para cada documento escrito, o valor da propriedade da chave do shard é transformado em hash, e o valor desse hash determina como o documento é associado ao shard físico subjacente. Internamente, vários fragmentos lógicos são mapeados em um único fragmento físico. Além disso, os fragmentos lógicos nunca são divididos entre fragmentos físicos e todos os documentos de um fragmento lógico correspondem apenas a um fragmento físico.

Baseando-se no exemplo anterior usando um cluster com dois fragmentos físicos, esta tabela mostra um exemplo de mapeamento de documentos para fragmentos físicos.

ID do documento Valor da Chave do Fragmento Fragmento Lógico Fragmento Físico
"12345" "Steve Smith" Fragmento 1 Fragmento Físico 1
"23456" "Jane Doe" Fragmento 2 Fragmento Físico 2
"34567" "Steve Smith" Fragmento 1 Fragmento Físico 1
"45678" "Michael Smith" Fragmento 3 Fragmento Físico 1
"56789" "Jane Doe" Fragmento 2 Fragmento Físico 2

Capacidade dos fragmentos físicos

O nível de cluster selecionado quando o cluster é provisionado determina a capacidade de CPU e memória de um shard físico. De forma semelhante, o SKU de armazenamento determina a capacidade de armazenamento e IOPS de um shard físico. Níveis de cluster maiores fornecem mais poder de computação e memória maior, enquanto discos de armazenamento maiores fornecem mais armazenamento e IOPS. Cargas de trabalho pesadas em leitura beneficiam de um nível de cluster maior, enquanto cargas de trabalho pesadas em escrita beneficiam de um SKU de armazenamento maior. A camada do cluster pode ser escalada para cima e para baixo após a criação do cluster, consoante as necessidades em constante mudança da aplicação.

Num cluster multifragmentos, a capacidade de cada fragmento físico é a mesma. Escalar o cluster tier ou o SKU de armazenamento não altera a colocação dos shards lógicos nos shards físicos. Após uma operação de escalonamento, o número de fragmentos físicos mantém-se o mesmo, evitando assim a necessidade de reequilibrar os dados no cluster.

A capacidade de computação, memória, armazenamento e IOPS do shard físico determinam os recursos disponíveis para os shards lógicos. Chaves de shard que não têm uma distribuição uniforme dos volumes de armazenamento e pedidos podem causar um armazenamento e consumo de throughput desiguais dentro do cluster. As partições quentes podem fazer com que os shards físicos sejam utilizados de forma desigual, resultando em taxa de transferência e desempenho imprevisíveis. Assim, os clusters fragmentados requerem um planeamento cuidadoso desde o início para garantir que o desempenho se mantém consistente à medida que os requisitos da aplicação mudam ao longo do tempo.

Conjuntos de réplicas

Cada fragmento físico é composto por um conjunto de réplicas, também conhecido como conjunto de réplicas. Cada réplica hospeda uma instância do mecanismo de banco de dados. Um conjunto de réplicas torna o armazenamento de dados dentro do fragmento físico durável, altamente disponível e consistente. Cada réplica que compõe o fragmento físico herda a capacidade de armazenamento e computação do fragmento físico. O Azure DocumentDB gere automaticamente conjuntos de réplicas.

Boas práticas para a partição de dados

  • O sharding no Azure DocumentDB não é necessário a menos que o armazenamento e os volumes de transações da coleção possam exceder a capacidade de um único shard físico. Por exemplo, o serviço fornece 32 TB de discos por shard. Se uma coleção requer mais de 32 TB, deve ser fragmentada.

  • Não é necessário particionar todas as coleções de um cluster com vários fragmentos físicos. Coleções fragmentadas e não fragmentadas podem coexistir no mesmo agrupamento. O serviço distribui de forma ótima as coleções dentro do cluster para utilizar de forma uniforme os recursos de computação e armazenamento do cluster.

  • Para aplicações com muita leitura, a chave shard deve ser selecionada com base nos padrões de consulta mais frequentes. O filtro de consulta mais utilizado para uma coleção deve ser escolhido como chave de fragmento para otimizar a maior percentagem possível de transações na base de dados, localizando a pesquisa em um único fragmento físico.

  • Para aplicações com elevada carga de escrita que priorizam o desempenho de escrita sobre a leitura, deve ser escolhida uma chave de fragmentação para distribuir os dados de forma uniforme entre os fragmentos físicos. Chaves de fragmentação com a maior cardinalidade proporcionam a melhor oportunidade de distribuir de forma o mais uniforme possível.

  • Para um desempenho ótimo, o tamanho de armazenamento de um shard lógico deve ser inferior a 4 TB.

  • Para um desempenho ótimo, os shards lógicos devem estar distribuídos uniformemente no armazenamento e na carga de solicitações entre os shards físicos do cluster.

Como fragmentar uma coleção

Considere o seguinte documento dentro da base de dados 'cosmicworks' e da coleção 'employee'

{
    "firstName": "Steve",
    "lastName": "Smith",
    "companyName": "Microsoft",
    "division": "Azure",
    "subDivision": "Data & AI",
    "timeInOrgInYears": 7
}

O exemplo seguinte fragmenta a coleção de colaboradores da base de dados cosmicworks com base na propriedade firstName.

use cosmicworks;
sh.shardCollection("cosmicworks.employee", {"firstName": "hashed"})

A coleção também pode ser fragmentada usando um comando admin:

use cosmicworks;
db.adminCommand({
  "shardCollection": "cosmicworks.employee",
  "key": {"firstName": "hashed"}
})

Embora não seja ideal alterar a chave de partição depois de a coleção ter aumentado significativamente o volume de armazenamento, o comando reshardCollection pode ser usado para modificar a chave de partição.

use cosmicworks;
sh.reshardCollection("cosmicworks.employee", {"lastName": "hashed"})

A coleção também pode ser resfragmentada usando um comando de administrador:

use cosmicworks;
db.adminCommand({
  "reshardCollection": "cosmicworks.employee",
  "key": {"lastName": "hashed"}
})

Como boa prática, deve ser criado um índice sobre a propriedade da chave do fragmento.

use cosmicworks;
db.runCommand({
  createIndexes: "employee",
  indexes: [{"key":{"firstName":1}, "name":"firstName_1", "enableLargeIndexKeys": true}],
  blocking: true
})

Próximos passos