Padrão de fragmentaçãoSharding pattern

Divida um armazenamento de dados em um conjunto de partições horizontais ou fragmentos.Divide a data store into a set of horizontal partitions or shards. Isso pode melhorar a escalabilidade ao armazenar e acessar grandes volumes de dados.This can improve scalability when storing and accessing large volumes of data.

Contexto e problemaContext and problem

Um repositório de dados hospedado por um único servidor pode estar sujeito às seguintes limitações:A data store hosted by a single server might be subject to the following limitations:

  • Espaço de armazenamento.Storage space. Um repositório de dados para um aplicativo de nuvem em grande escala deve conter um grande volume de dados que podem aumentar significativamente ao longo do tempo.A data store for a large-scale cloud application is expected to contain a huge volume of data that could increase significantly over time. Um servidor geralmente fornece apenas uma quantidade finita de armazenamento em disco, mas você pode substituir discos existentes por maiores ou adicionar mais discos a uma máquina com o crescimento dos volumes de dados.A server typically provides only a finite amount of disk storage, but you can replace existing disks with larger ones, or add further disks to a machine as data volumes grow. No entanto, o sistema uma hora atingirá um limite em que não é possível aumentar facilmente a capacidade de armazenamento em um determinado servidor.However, the system will eventually reach a limit where it isn't possible to easily increase the storage capacity on a given server.

  • Recursos de computação.Computing resources. Um aplicativo de nuvem é necessário para dar suporte a um grande número de usuários simultâneos, cada um dos quais executa consultas que recuperam informações do repositório de dados.A cloud application is required to support a large number of concurrent users, each of which run queries that retrieve information from the data store. Um único servidor que hospeda o armazenamento de dados pode não ser capaz de fornecer o poder de computação necessário para suportar essa carga, resultando em tempos de resposta estendidos para os usuários e falhas frequentes à medida que os aplicativos tentam armazenar e recuperar o tempo de data. Pode ser possível adicionar processadores de memória ou upgrade, mas o sistema atingirá um limite quando não for possível aumentar ainda mais os recursos de computação.A single server hosting the data store might not be able to provide the necessary computing power to support this load, resulting in extended response times for users and frequent failures as applications attempting to store and retrieve data time out. It might be possible to add memory or upgrade processors, but the system will reach a limit when it isn't possible to increase the compute resources any further.

  • Largura de banda da rede.Network bandwidth. Por fim, o desempenho de um repositório de dados em execução em um único servidor é controlado pela velocidade em que o servidor pode receber solicitações e enviar respostas.Ultimately, the performance of a data store running on a single server is governed by the rate the server can receive requests and send replies. É possível que o volume de tráfego de rede possa exceder a capacidade da rede usada para se conectar ao servidor, resultando em solicitações com falha.It's possible that the volume of network traffic might exceed the capacity of the network used to connect to the server, resulting in failed requests.

  • Geografia.Geography. Talvez seja necessário armazenar os dados gerados por usuários específicos na mesma região que esses usuários por motivos legais, de conformidade ou de desempenho ou para reduzir a latência de acesso aos dados.It might be necessary to store data generated by specific users in the same region as those users for legal, compliance, or performance reasons, or to reduce latency of data access. Se os usuários estão distribuídos em diferentes países ou regiões, pode não ser possível armazenar todos os dados do aplicativo em um único repositório de dados.If the users are dispersed across different countries or regions, it might not be possible to store the entire data for the application in a single data store.

O dimensionamento vertical por adição de mais capacidade em disco, capacidade de processamento, memória e conexões de rede pode adiar os efeitos de algumas dessas limitações, mas é provável que seja apenas uma solução temporária.Scaling vertically by adding more disk capacity, processing power, memory, and network connections can postpone the effects of some of these limitations, but it's likely to only be a temporary solution. Um aplicativo de nuvem comercial capaz de dar suporte a grandes números de usuários e grandes volumes de dados deve ser capaz de ser dimensionado quase indefinidamente, então o dimensionamento vertical não é necessariamente a melhor solução.A commercial cloud application capable of supporting large numbers of users and high volumes of data must be able to scale almost indefinitely, so vertical scaling isn't necessarily the best solution.

SoluçãoSolution

Divida o repositório de dados em partições horizontais ou fragmentos.Divide the data store into horizontal partitions or shards. Cada fragmento tem o mesmo esquema, mas mantém seu próprio subconjunto distinto dos dados.Each shard has the same schema, but holds its own distinct subset of the data. Um fragmento é um repositório de dados em si (ele pode conter os dados de várias entidades de tipos diferentes), em execução em um servidor que atua como nó de armazenamento.A shard is a data store in its own right (it can contain the data for many entities of different types), running on a server acting as a storage node.

Esse padrão tem os seguintes benefícios:This pattern has the following benefits:

  • Você pode dimensionar o sistema horizontalmente acrescentando mais fragmentos executados em nós de armazenamento adicionais.You can scale the system out by adding further shards running on additional storage nodes.

  • Um sistema pode usar hardware disponível no mercado em vez de computadores especializados e caros para cada nó de armazenamento.A system can use off-the-shelf hardware rather than specialized and expensive computers for each storage node.

  • Você pode reduzir a contenção e melhorar o desempenho equilibrando a carga de trabalho entre fragmentos.You can reduce contention and improve performance by balancing the workload across shards.

  • Na nuvem, fragmentos podem estar localizados fisicamente próximos aos usuários que acessarão os dados.In the cloud, shards can be located physically close to the users that'll access the data.

Ao dividir um repositório de dados em fragmentos, decida quais dados devem ser colocados em cada fragmento.When dividing a data store up into shards, decide which data should be placed in each shard. Geralmente, um fragmento contém itens que se encontram em um intervalo específico determinado por um ou mais atributos dos dados.A shard typically contains items that fall within a specified range determined by one or more attributes of the data. Esses atributos formam a chave de fragmentação (também conhecida como a chave de partição).These attributes form the shard key (sometimes referred to as the partition key). A chave de fragmentação deve ser estática.The shard key should be static. Ela não deve ser baseada em dados que possam ser alterados.It shouldn't be based on data that might change.

A fragmentação física organiza os dados.Sharding physically organizes the data. Quando um aplicativo armazena e recupera dados, a lógica de fragmentação direciona o aplicativo para o fragmento apropriado.When an application stores and retrieves data, the sharding logic directs the application to the appropriate shard. Essa lógica de fragmentação pode ser implementada como parte do código de acesso a dados no aplicativo ou pode ser implementada pelo sistema de armazenamento de dados se ele oferece suporte à fragmentação de forma transparente.This sharding logic can be implemented as part of the data access code in the application, or it could be implemented by the data storage system if it transparently supports sharding.

A abstração do local físico dos dados na lógica de fragmentação fornece um alto nível de controle sobre quais fragmentos contêm os dados.Abstracting the physical location of the data in the sharding logic provides a high level of control over which shards contain which data. Ela também permite que dados migrem entre fragmentos sem refazer a lógica de negócios de um aplicativo se os dados nos fragmentos precisarem ser redistribuídos posteriormente (por exemplo, se os fragmentos se tornarem desbalanceados).It also enables data to migrate between shards without reworking the business logic of an application if the data in the shards need to be redistributed later (for example, if the shards become unbalanced). A desvantagem é a sobrecarga de acesso a dados adicionais necessária para determinar a localização de cada item dos dados conforme eles são recuperados.The tradeoff is the additional data access overhead required in determining the location of each data item as it's retrieved.

Para garantir o desempenho e a escalabilidade ideais, é importante dividir os dados de maneira adequada para os tipos de consultas que o aplicativo executa.To ensure optimal performance and scalability, it's important to split the data in a way that's appropriate for the types of queries that the application performs. Em muitos casos, é improvável que o esquema de fragmentação corresponda exatamente aos requisitos de cada consulta.In many cases, it's unlikely that the sharding scheme will exactly match the requirements of every query. Por exemplo, em um sistema multilocatário, um aplicativo pode precisar recuperar dados de locatário usando a ID de locatário, mas ele também pode precisar consultar esses dados com base em algum outro atributo, como nome ou local do locatário.For example, in a multi-tenant system an application might need to retrieve tenant data using the tenant ID, but it might also need to look up this data based on some other attribute such as the tenant’s name or location. Para lidar com essas situações, implemente uma estratégia de fragmentação com uma chave de fragmentação que ofereça suporte às consultas realizadas com mais frequência.To handle these situations, implement a sharding strategy with a shard key that supports the most commonly performed queries.

Se as consultas regularmente recuperam dados usando uma combinação de valores de atributo, você provavelmente pode definir uma chave de fragmentação composta vinculando atributos.If queries regularly retrieve data using a combination of attribute values, you can likely define a composite shard key by linking attributes together. Como alternativa, use um padrão como Tabela de Índice para oferecer pesquisa rápida de dados com base em atributos que não são cobertos pela chave de fragmentação.Alternatively, use a pattern such as Index Table to provide fast lookup to data based on attributes that aren't covered by the shard key.

Estratégias de fragmentaçãoSharding strategies

Três estratégias são usadas frequentemente ao selecionar a chave de fragmentação e decidir como distribuir dados entre fragmentos.Three strategies are commonly used when selecting the shard key and deciding how to distribute data across shards. Observe que não é necessário que haja uma correspondência entre fragmentos e os servidores que os hospedam—um único servidor pode hospedar vários fragmentos.Note that there doesn't have to be a one-to-one correspondence between shards and the servers that host them—a single server can host multiple shards. As estratégias são:The strategies are:

A estratégia de pesquisa.The Lookup strategy. Nesta estratégia, a lógica de fragmentação implementa um mapa que encaminha uma solicitação de dados para o fragmento que contém os dados usando a chave de fragmentação.In this strategy the sharding logic implements a map that routes a request for data to the shard that contains that data using the shard key. Em um aplicativo multilocatário, todos os dados de um locatário podem ser armazenados juntos em um fragmento usando a ID do locatário como chave de fragmentação.In a multi-tenant application all the data for a tenant might be stored together in a shard using the tenant ID as the shard key. Vários locatários podem compartilhar o mesmo fragmento, mas os dados de um único locatário não serão distribuídos a vários fragmentos.Multiple tenants might share the same shard, but the data for a single tenant won't be spread across multiple shards. A figura ilustra a fragmentação dos dados de locatário com base nas IDs de locatário.The figure illustrates sharding tenant data based on tenant IDs.

Figura 1 - Fragmentação dos dados de locatário com base nos IDs de locatário

O mapeamento entre a chave de fragmentação e o armazenamento físico pode ser baseado em fragmentos físicos nos quais cada chave de fragmentação é mapeada a uma partição física.The mapping between the shard key and the physical storage can be based on physical shards where each shard key maps to a physical partition. Como alternativa, uma técnica mais flexível para rebalancear fragmentos é o particionamento virtual, no qual as chaves de fragmentação são mapeadas ao mesmo número de fragmentos virtuais, que por sua vez são mapeados a menos partições físicas.Alternatively, a more flexible technique for rebalancing shards is virtual partitioning, where shard keys map to the same number of virtual shards, which in turn map to fewer physical partitions. Nessa abordagem, um aplicativo localiza os dados usando uma chave de fragmentação que se refere a um fragmento virtual e o sistema mapeia de maneira transparentemente fragmentos virtuais a partições físicas.In this approach, an application locates data using a shard key that refers to a virtual shard, and the system transparently maps virtual shards to physical partitions. O mapeamento entre um fragmento virtual e uma partição física pode mudar sem a necessidade de modificar o código do aplicativo para usar um conjunto diferente de chaves de fragmentação.The mapping between a virtual shard and a physical partition can change without requiring the application code be modified to use a different set of shard keys.

A estratégia de intervalo.The Range strategy. Essa estratégia agrupa itens relacionados no mesmo fragmento e os classifica por chave de fragmentação—as chaves de fragmentação são sequenciais.This strategy groups related items together in the same shard, and orders them by shard key—the shard keys are sequential. É útil para aplicativos que frequentemente recuperam conjuntos de itens usando consultas de intervalo (consultas que retornam um conjunto de itens de dados para uma chave de fragmentação que fica dentro de um determinado intervalo).It's useful for applications that frequently retrieve sets of items using range queries (queries that return a set of data items for a shard key that falls within a given range). Por exemplo, se um aplicativo precisar localizar regularmente todos os pedidos feitos em um determinado mês, esses dados podem ser recuperados mais rapidamente se todos os pedidos de um mês estiverem armazenados ordenados por data e hora no mesmo fragmento.For example, if an application regularly needs to find all orders placed in a given month, this data can be retrieved more quickly if all orders for a month are stored in date and time order in the same shard. Se cada pedido foi armazenado em um fragmento diferente, eles precisam ser buscados individualmente executando um grande número de consultas pontuais (consultas que retornam um único item de dados).If each order was stored in a different shard, they'd have to be fetched individually by performing a large number of point queries (queries that return a single data item). A figura seguinte ilustra como armazenar conjuntos sequenciais (intervalos) de dados no fragmento.The next figure illustrates storing sequential sets (ranges) of data in shard.

Figura 2 - Armazenar conjuntos sequenciais (intervalos) de dados em fragmentos

Neste exemplo, a chave de fragmentação é uma chave composta que contém o mês do pedido como o elemento mais significativo, seguido por dia e hora do pedido.In this example, the shard key is a composite key containing the order month as the most significant element, followed by the order day and the time. Os dados de pedidos são classificados naturalmente quando novos pedidos são criados e adicionados a um fragmento.The data for orders is naturally sorted when new orders are created and added to a shard. Alguns repositórios de dados aceitam chaves de fragmentação de duas partes contendo um elemento de chave de partição que identifica o fragmento e uma chave de linha que identifica exclusivamente um item no fragmento.Some data stores support two-part shard keys containing a partition key element that identifies the shard and a row key that uniquely identifies an item in the shard. Normalmente, os dados são mantidos na ordem da chave de linha no fragmento.Data is usually held in row key order in the shard. Itens que estão sujeitos a consultas de intervalo e precisam ser agrupados podem usar uma chave de fragmentação que tenha o mesmo valor para a chave de partição, mas um valor exclusivo para a chave de linha.Items that are subject to range queries and need to be grouped together can use a shard key that has the same value for the partition key but a unique value for the row key.

A estratégia de Hash.The Hash strategy. A finalidade dessa estratégia é reduzir a chance de pontos problemáticos (fragmentos que recebem uma quantidade desproporcional de carga).The purpose of this strategy is to reduce the chance of hotspots (shards that receive a disproportionate amount of load). Ela distribui os dados entre os fragmentos de forma que alcance um equilíbrio entre o tamanho de cada fragmento e a carga média que cada fragmento encontrará.It distributes the data across the shards in a way that achieves a balance between the size of each shard and the average load that each shard will encounter. A lógica de fragmentação calcula o fragmento para armazenar um item com base em um hash de um ou mais atributos dos dados.The sharding logic computes the shard to store an item in based on a hash of one or more attributes of the data. A função de hash de escolhida deve distribuir os dados uniformemente entre os fragmentos, possivelmente introduzindo algum elemento aleatório na computação.The chosen hashing function should distribute data evenly across the shards, possibly by introducing some random element into the computation. A próxima figura ilustra a fragmentação dos dados de locatário com base em um hash de IDs de locatário.The next figure illustrates sharding tenant data based on a hash of tenant IDs.

Figura 3 - Fragmentação dos dados de locatário com base em um hash de IDs de locatário

Para entender a vantagem da estratégia de Hash sobre outras estratégias de fragmentação, considere como um aplicativo multilocatário que registra novos locatários pode atribuir sequencialmente os locatários a fragmentos no repositório de dados.To understand the advantage of the Hash strategy over other sharding strategies, consider how a multi-tenant application that enrolls new tenants sequentially might assign the tenants to shards in the data store. Ao usar a estratégia de Intervalo, os dados para locatários de 1 a n serão todos armazenados no fragmento A, os dados para locatários de n+1 a m serão todos armazenados no fragmento B e assim por diante.When using the Range strategy, the data for tenants 1 to n will all be stored in shard A, the data for tenants n+1 to m will all be stored in shard B, and so on. Se os locatários registrados mais recentemente também forem os mais ativos, a maior parte das atividades de dados ocorrerá em um pequeno número de fragmentos, o que pode resultar em pontos problemáticos.If the most recently registered tenants are also the most active, most data activity will occur in a small number of shards, which could cause hotspots. Por outro lado, a estratégia de Hash aloca locatários a fragmentos com base em um hash das IDs de locatário.In contrast, the Hash strategy allocates tenants to shards based on a hash of their tenant ID. Isso significa que locatários sequenciais têm mais probabilidade de serem alocados para fragmentos diferentes, que distribuirão a carga entre eles.This means that sequential tenants are most likely to be allocated to different shards, which will distribute the load across them. A figura anterior mostra a isso para os locatários 55 e 56.The previous figure shows this for tenants 55 and 56.

As três estratégias de fragmentação têm as seguintes vantagens e considerações:The three sharding strategies have the following advantages and considerations:

  • Procure .Lookup. Oferece mais controle sobre a forma em que os fragmentos são configurados e usados.This offers more control over the way that shards are configured and used. O uso de fragmentos virtuais reduz o impacto ao rebalancear dados porque novas partições físicas podem ser adicionadas para uniformizar a carga de trabalho.Using virtual shards reduces the impact when rebalancing data because new physical partitions can be added to even out the workload. O mapeamento entre um fragmento virtual e as partições físicas que implementam o fragmento pode ser modificado sem afetar o código do aplicativo que usa uma chave de fragmentação para armazenar e recuperar dados.The mapping between a virtual shard and the physical partitions that implement the shard can be modified without affecting application code that uses a shard key to store and retrieve data. A pesquisa de locais de fragmento pode impor uma sobrecarga adicional.Looking up shard locations can impose an additional overhead.

  • Alcance.Range. É fácil de implementar e funciona bem com consultas de intervalo porque geralmente podem buscar vários itens de dados em um único fragmento em uma única operação.This is easy to implement and works well with range queries because they can often fetch multiple data items from a single shard in a single operation. Essa estratégia oferece gerenciamento de dados mais fácil.This strategy offers easier data management. Por exemplo, se os usuários na mesma região estiverem no mesmo fragmento, podem ser agendadas atualizações em cada fuso horário com base no padrão de carga local e demanda.For example, if users in the same region are in the same shard, updates can be scheduled in each time zone based on the local load and demand pattern. No entanto, essa estratégia não fornece o equilíbrio ideal entre fragmentos.However, this strategy doesn't provide optimal balancing between shards. O rebalanceamento de fragmentos é difícil e pode não resolver o problema de carga irregular se a maior parte da atividade for para chaves de fragmentação adjacentes.Rebalancing shards is difficult and might not resolve the problem of uneven load if the majority of activity is for adjacent shard keys.

  • Hash.Hash. Essa estratégia oferece mais chances de uma distribuição de dados e carga mais uniforme.This strategy offers a better chance of more even data and load distribution. O roteamento de solicitação pode ser realizado diretamente usando a função de hash.Request routing can be accomplished directly by using the hash function. Não é necessário manter um mapa.There's no need to maintain a map. Observe que calcular o hash pode impor uma sobrecarga adicional.Note that computing the hash might impose an additional overhead. Além disso, o rebalanceamento de fragmentos é difícil.Also, rebalancing shards is difficult.

Os sistemas mais comuns de fragmentação implementam uma das abordagens descritas acima, mas você também deve considerar os requisitos de negócios de seus aplicativos e seus padrões de uso de dados.Most common sharding systems implement one of the approaches described above, but you should also consider the business requirements of your applications and their patterns of data usage. Por exemplo, em um aplicativo multilocatário:For example, in a multi-tenant application:

  • Você pode fragmentar dados com base na carga de trabalho.You can shard data based on workload. Você pode separar os dados para locatários altamente voláteis em fragmentos separados.You could segregate the data for highly volatile tenants in separate shards. A velocidade do acesso aos dados para outros locatários pode ser melhorada como resultado.The speed of data access for other tenants might be improved as a result.

  • Você pode fragmentar dados com base na localização dos locatários.You can shard data based on the location of tenants. Você pode tornar os dados de locatários em uma região geográfica específica offline para manutenção e backup fora do horário de pico nessa região, enquanto os dados de locatários em outras regiões permanecem online e acessíveis durante os respectivos horários comerciais.You can take the data for tenants in a specific geographic region offline for backup and maintenance during off-peak hours in that region, while the data for tenants in other regions remains online and accessible during their business hours.

  • Locatários de grande valor podem ter atribuídos seus próprios fragmentos privados, de alto desempenho e com pouca carga, enquanto locatários de valor inferior podem compartilhar fragmentos ocupados e mais compactados.High-value tenants could be assigned their own private, high performing, lightly loaded shards, whereas lower-value tenants might be expected to share more densely-packed, busy shards.

  • Os dados para locatários que precisam de um alto grau de isolamento de dados e privacidade podem ser armazenados em um servidor completamente separado.The data for tenants that need a high degree of data isolation and privacy can be stored on a completely separate server.

Operações de movimentação de dados e dimensionamentoScaling and data movement operations

Cada uma das estratégias de fragmentação implica diferentes recursos e níveis de complexidade para gerenciar a redução, a expansão, a movimentação de dados e o estado de manutenção.Each of the sharding strategies implies different capabilities and levels of complexity for managing scale in, scale out, data movement, and maintaining state.

A estratégia de pesquisa permite que operações de movimentação de dados e dimensionamento sejam executadas no nível do usuário, online ou offline.The Lookup strategy permits scaling and data movement operations to be carried out at the user level, either online or offline. A técnica resume-se em suspender algumas ou todas as atividades do usuário (talvez durante períodos de pico), mover os dados para a nova partição virtual ou fragmento físico, alterar os mapeamentos, invalidar ou atualizar quaisquer caches que mantenham esses dados e, em seguida, permitir que a atividade do usuário continue.The technique is to suspend some or all user activity (perhaps during off-peak periods), move the data to the new virtual partition or physical shard, change the mappings, invalidate or refresh any caches that hold this data, and then allow user activity to resume. Muitas vezes esse tipo de operação pode ser gerenciado de forma central.Often this type of operation can be centrally managed. A estratégia de Pesquisa requer que o estado favoreça o armazenamento em cache e seja fácil de replicar.The Lookup strategy requires state to be highly cacheable and replica friendly.

A estratégia de Intervalo impõe algumas limitações a operações de movimentação de dados e dimensionamento, que normalmente devem ser executadas quando uma parte ou todo o repositório de dados está offline porque os dados devem ser divididos e mesclados entre os fragmentos.The Range strategy imposes some limitations on scaling and data movement operations, which must typically be carried out when a part or all of the data store is offline because the data must be split and merged across the shards. A movimentação dos dados para reequilibrar fragmentos não poderá resolver o problema de carga irregular se a maior parte da atividade for para chaves de fragmentação adjacentes ou identificadores de dados que estejam dentro do mesmo intervalo.Moving the data to rebalance shards might not resolve the problem of uneven load if the majority of activity is for adjacent shard keys or data identifiers that are within the same range. A estratégia de Intervalo também pode exigir que algum estado seja mantido para mapear os intervalos às partições físicas.The Range strategy might also require some state to be maintained in order to map ranges to the physical partitions.

A estratégia de Hash torna as operações de movimentação de dados e dimensionamento mais complexas porque as chaves de partição são hashes das chaves de fragmentação ou dos identificadores de dados.The Hash strategy makes scaling and data movement operations more complex because the partition keys are hashes of the shard keys or data identifiers. O novo local de cada fragmento deve ser determinado a partir da função de hash ou a função modificada para fornecer os mapeamentos corretos.The new location of each shard must be determined from the hash function, or the function modified to provide the correct mappings. No entanto, a estratégia de Hash não exige manutenção do estado.However, the Hash strategy doesn't require maintenance of state.

Problemas e consideraçõesIssues and considerations

Considere os seguintes pontos ao decidir como implementar esse padrão:Consider the following points when deciding how to implement this pattern:

  • A fragmentação é complementar a outras formas de particionamento, como particionamento vertical e particionamento funcional.Sharding is complementary to other forms of partitioning, such as vertical partitioning and functional partitioning. Por exemplo, um único fragmento pode conter entidades que foram particionadas verticalmente e uma partição funcional pode ser implementada como vários fragmentos.For example, a single shard can contain entities that have been partitioned vertically, and a functional partition can be implemented as multiple shards. Para saber mais sobre o particionamento, confira a Diretrizes de particionamento de dados.For more information about partitioning, see the Data Partitioning Guidance.

  • Mantenha os fragmentos equilibrados para que todos tratem de um volume semelhante de E/S.Keep shards balanced so they all handle a similar volume of I/O. À medida que os dados são inseridos e excluídos, é necessário reequilibrar periodicamente os fragmentos para garantir uma distribuição uniforme e reduzir a chance de pontos problemáticos.As data is inserted and deleted, it's necessary to periodically rebalance the shards to guarantee an even distribution and to reduce the chance of hotspots. O rebalanceamento pode ser uma operação dispendiosa.Rebalancing can be an expensive operation. Para reduzir a necessidade de rebalanceamento, planeje o crescimento garantindo que cada fragmento contenha espaço suficiente para lidar com o volume esperado de alterações.To reduce the necessity of rebalancing, plan for growth by ensuring that each shard contains sufficient free space to handle the expected volume of changes. Você também deve desenvolver estratégias e scripts que possa usar para reequilibrar rapidamente fragmentos se isso for necessário.You should also develop strategies and scripts you can use to quickly rebalance shards if this becomes necessary.

  • Use dados estáveis para a chave de fragmentação.Use stable data for the shard key. Se a chave de fragmentação for alterada, o item de dados correspondente talvez precise ser movido entre fragmentos, aumentando a quantidade de trabalho realizado pelas operações de atualização.If the shard key changes, the corresponding data item might have to move between shards, increasing the amount of work performed by update operations. Por esse motivo, evite basear a chave de fragmentação em informações potencialmente voláteis.For this reason, avoid basing the shard key on potentially volatile information. Em vez disso, procure os atributos que sejam invariáveis ou que naturalmente formem uma chave.Instead, look for attributes that are invariant or that naturally form a key.

  • Certifique-se de que as chaves de fragmentação sejam exclusivas.Ensure that shard keys are unique. Por exemplo, evite usar campos de incremento automático como chave de fragmentação.For example, avoid using autoincrementing fields as the shard key. Em alguns sistemas, campos incrementados automaticamente não podem ser coordenados entre fragmentos, possivelmente resultando em itens em fragmentos diferentes com a mesma chave de fragmentação.Is some systems, autoincremented fields can't be coordinated across shards, possibly resulting in items in different shards having the same shard key.

    Valores incrementados automaticamente em outros campos que não chaves de fragmentação também podem causar problemas.Autoincremented values in other fields that are not shard keys can also cause problems. Por exemplo, se você usar campos incrementados automaticamente para gerar IDs exclusivas, dois itens diferentes localizados em fragmentos diferentes podem ter atribuída uma mesma ID.For example, if you use autoincremented fields to generate unique IDs, then two different items located in different shards might be assigned the same ID.

  • Pode não ser possível criar uma chave de fragmentação que atenda aos requisitos de cada possível consulta dos dados.It might not be possible to design a shard key that matches the requirements of every possible query against the data. Fragmente os dados para dar suporte às consultas mais frequentemente executadas e, se necessário, crie tabelas de índice secundárias para dar suporte a consultas que recuperem dados usando os critérios baseados em atributos que não façam parte da chave de fragmentação.Shard the data to support the most frequently performed queries, and if necessary create secondary index tables to support queries that retrieve data using criteria based on attributes that aren't part of the shard key. Para saber mais, confira o Padrão de Tabela de Índice.For more information, see the Index Table pattern.

  • Consultas que acessam apenas um único fragmento são mais eficientes do que aquelas que recuperam dados de vários fragmentos, portanto, evite implementar um sistema de fragmentação que resulte em aplicativos que executam grandes números de consultas que unem dados mantidos em fragmentos diferentes.Queries that access only a single shard are more efficient than those that retrieve data from multiple shards, so avoid implementing a sharding system that results in applications performing large numbers of queries that join data held in different shards. Lembre-se de que um único fragmento pode conter os dados de vários tipos de entidades.Remember that a single shard can contain the data for multiple types of entities. Considere a desnormalização de seus dados para manter as entidades relacionadas que normalmente são consultadas em conjunto (por exemplo, os detalhes de clientes e os pedidos que eles fizeram) no mesmo fragmento para reduzir o número de leituras separadas que um aplicativo realiza.Consider denormalizing your data to keep related entities that are commonly queried together (such as the details of customers and the orders that they have placed) in the same shard to reduce the number of separate reads that an application performs.

    Se uma entidade em um fragmento faz referência a uma entidade armazenada em outro fragmento, inclua a chave de fragmentação para a segunda entidade como parte do esquema da primeira entidade.If an entity in one shard references an entity stored in another shard, include the shard key for the second entity as part of the schema for the first entity. Isso pode ajudar a melhorar o desempenho das consultas que fazem referência a dados relacionados entre fragmentos.This can help to improve the performance of queries that reference related data across shards.

  • Se um aplicativo deve executar consultas que recuperam dados de vários fragmentos, pode ser possível buscar esses dados por meio de tarefas paralelas.If an application must perform queries that retrieve data from multiple shards, it might be possible to fetch this data by using parallel tasks. Os exemplos incluem consultas do tipo fan-out, nas quais os dados de vários fragmentos são recuperados em paralelo e agregados em um único resultado.Examples include fan-out queries, where data from multiple shards is retrieved in parallel and then aggregated into a single result. No entanto, essa abordagem inevitavelmente adiciona certa complexidade à lógica de acesso a dados de uma solução.However, this approach inevitably adds some complexity to the data access logic of a solution.

  • Para muitos aplicativos, a criação de um grande número de fragmentos pequenos pode ser mais eficiente do que um pequeno número de fragmentos grandes porque eles podem oferecer mais oportunidades de balanceamento de carga.For many applications, creating a larger number of small shards can be more efficient than having a small number of large shards because they can offer increased opportunities for load balancing. Isso também pode ser útil se você prevê a necessidade de migrar os fragmentos de um local físico para outro.This can also be useful if you anticipate the need to migrate shards from one physical location to another. A movimentação de um fragmento pequeno é mais rápida do que mover um grande.Moving a small shard is quicker than moving a large one.

  • Verifique se os recursos disponíveis para cada nó de armazenamento de fragmento são suficientes para lidar com os requisitos de escalabilidade em termos de tamanho de dados e taxa de transferência.Make sure the resources available to each shard storage node are sufficient to handle the scalability requirements in terms of data size and throughput. Para obter mais informações, consulte a seção "Criando partições para escalabilidade" no Diretrizes de particionamento de dados.For more information, see the section “Designing Partitions for Scalability” in the Data Partitioning Guidance.

  • Considere a possibilidade de replicar dados de referência para todos os fragmentos.Consider replicating reference data to all shards. Se uma operação que recupera dados de um fragmento também faz referência a dados estáticos ou lentos, como parte da mesma consulta, adicione esses dados ao fragmento.If an operation that retrieves data from a shard also references static or slow-moving data as part of the same query, add this data to the shard. O aplicativo pode então buscar todos os dados para a consulta facilmente, sem precisar fazer outro percurso de ida e volta a um repositório de dados separado.The application can then fetch all of the data for the query easily, without having to make an additional round trip to a separate data store.

    Se os dados de referência mantidos em vários fragmentos mudarem, o sistema deve sincronizar essas alterações em todos os fragmentos.If reference data held in multiple shards changes, the system must synchronize these changes across all shards. O sistema pode apresentar um grau de inconsistência enquanto ocorre a sincronização.The system can experience a degree of inconsistency while this synchronization occurs. Se você fizer isso, você deve projetar seus aplicativos para serem capazes de lidar com isso.If you do this, you should design your applications to be able to handle it.

  • Pode ser difícil manter a integridade referencial e a consistência entre os fragmentos, portanto você deve minimizar as operações que afetam os dados em vários fragmentos.It can be difficult to maintain referential integrity and consistency between shards, so you should minimize operations that affect data in multiple shards. Se um aplicativo deve modificar dados em fragmentos, avalie se a consistência total dos dados é realmente necessária.If an application must modify data across shards, evaluate whether complete data consistency is actually required. Em vez disso, uma abordagem comum na nuvem é implementar a consistência eventual.Instead, a common approach in the cloud is to implement eventual consistency. Os dados em cada partição são atualizados separadamente e a lógica do aplicativo deve assumir a responsabilidade de garantir que todas as atualizações concluam com êxito, bem como tratar as inconsistências que possam surgir na consulta de dados durante a execução de uma operação que será consistente em algum momento.The data in each partition is updated separately, and the application logic must take responsibility for ensuring that the updates all complete successfully, as well as handling the inconsistencies that can arise from querying data while an eventually consistent operation is running. Para saber mais sobre como Para saber mais sobre como implementar a consistência eventual, confira Primer de Consistência de Dados.For more information about implementing eventual consistency, see the Data Consistency Primer.

  • A configuração e o gerenciamento de um grande número de fragmentos podem ser um desafio.Configuring and managing a large number of shards can be a challenge. Tarefas como monitoramento, backup, verificação de consistência e registro em log ou auditoria devem ser realizadas em vários fragmentos e servidores, possivelmente mantidos em vários locais.Tasks such as monitoring, backing up, checking for consistency, and logging or auditing must be accomplished on multiple shards and servers, possibly held in multiple locations. Essas tarefas possivelmente podem ser implementadas usando scripts ou outras soluções de automação, mas isso pode não eliminar completamente os requisitos administrativos adicionais.These tasks are likely to be implemented using scripts or other automation solutions, but that might not completely eliminate the additional administrative requirements.

  • Os fragmentos podem ser geolocalizados para que os dados que eles contêm estejam próximos das instâncias de um aplicativo que os usa.Shards can be geolocated so that the data that they contain is close to the instances of an application that use it. Essa abordagem pode melhorar significativamente o desempenho, mas requer considerações adicionais para tarefas que devem acessar vários fragmentos em diferentes locais.This approach can considerably improve performance, but requires additional consideration for tasks that must access multiple shards in different locations.

Quando usar esse padrãoWhen to use this pattern

Use esse padrão quando um repositório de dados possa possivelmente precisar ser dimensionado além dos recursos disponíveis para um único nó de armazenamento ou para melhorar o desempenho reduzindo a contenção em um repositório de dados.Use this pattern when a data store is likely to need to scale beyond the resources available to a single storage node, or to improve performance by reducing contention in a data store.

Observação

O foco principal da fragmentação é melhorar o desempenho e escalabilidade de um sistema, mas como subproduto também pode melhorar a disponibilidade devido a como os dados são divididos em partições separadas.The primary focus of sharding is to improve the performance and scalability of a system, but as a by-product it can also improve availability due to how the data is divided into separate partitions. Uma falha em uma partição não necessariamente impede que um aplicativo acesse os dados mantidos em outras partições e um operador pode realizar manutenção ou recuperação de uma ou mais partições sem tornar todos os dados inacessíveis para um aplicativo.A failure in one partition doesn't necessarily prevent an application from accessing data held in other partitions, and an operator can perform maintenance or recovery of one or more partitions without making the entire data for an application inaccessible. Para saber mais, consulte Diretrizes de particionamento de dados.For more information, see the Data Partitioning Guidance.

ExemploExample

O exemplo a seguir em C# usa um conjunto de bancos de dados do SQL Server atuando como fragmentos.The following example in C# uses a set of SQL Server databases acting as shards. Cada banco de dados contém um subconjunto dos dados usados por um aplicativo.Each database holds a subset of the data used by an application. O aplicativo recupera dados distribuídos entre os fragmentos usando sua própria lógica de fragmentação (esse é um exemplo de uma consulta do tipo fan-out).The application retrieves data that's distributed across the shards using its own sharding logic (this is an example of a fan-out query). Os detalhes dos dados localizados em cada fragmento são retornados por um método chamado GetShards.The details of the data that's located in each shard is returned by a method called GetShards. Esse método retorna uma lista enumerável de objetos ShardInformation, na qual o tipo ShardInformation contém um identificador para cada fragmento e a cadeia de conexão do SQL Server que um aplicativo deve usar para se conectar ao fragmento (as cadeias de conexão não são mostradas no exemplo de código).This method returns an enumerable list of ShardInformation objects, where the ShardInformation type contains an identifier for each shard and the SQL Server connection string that an application should use to connect to the shard (the connection strings aren't shown in the code example).

private IEnumerable<ShardInformation> GetShards()
{
  // This retrieves the connection information from a shard store
  // (commonly a root database).
  return new[]
  {
    new ShardInformation
    {
      Id = 1,
      ConnectionString = ...
    },
    new ShardInformation
    {
      Id = 2,
      ConnectionString = ...
    }
  };
}

O código a seguir mostra como o aplicativo usa a lista de objetos ShardInformation para executar uma consulta que busca os dados de cada fragmento em paralelo.The code below shows how the application uses the list of ShardInformation objects to perform a query that fetches data from each shard in parallel. Os detalhes da consulta não são mostrados, mas os dados recuperados neste exemplo contêm uma cadeia de caracteres que pode conter informações como nome de um cliente se os fragmentos contiverem os detalhes de clientes.The details of the query aren't shown, but in this example the data that's retrieved contains a string that could hold information such as the name of a customer if the shards contain the details of customers. Os resultados são agregados em uma coleção ConcurrentBag a ser processada pelo aplicativo.The results are aggregated into a ConcurrentBag collection for processing by the application.

// Retrieve the shards as a ShardInformation[] instance.
var shards = GetShards();

var results = new ConcurrentBag<string>();

// Execute the query against each shard in the shard list.
// This list would typically be retrieved from configuration
// or from a root/master shard store.
Parallel.ForEach(shards, shard =>
{
  // NOTE: Transient fault handling isn't included,
  // but should be incorporated when used in a real world application.
  using (var con = new SqlConnection(shard.ConnectionString))
  {
    con.Open();
    var cmd = new SqlCommand("SELECT ... FROM ...", con);

    Trace.TraceInformation("Executing command against shard: {0}", shard.Id);

    var reader = cmd.ExecuteReader();
    // Read the results in to a thread-safe data structure.
    while (reader.Read())
    {
      results.Add(reader.GetString(0));
    }
  }
});

Trace.TraceInformation("Fanout query complete - Record Count: {0}",
                        results.Count);

Os padrões e diretrizes a seguir também podem ser relevantes ao implementar esse padrão:The following patterns and guidance might also be relevant when implementing this pattern:

  • Primer de consistência de dados.Data Consistency Primer. Talvez seja necessário manter a consistência de dados distribuídos entre fragmentos diferentes.It might be necessary to maintain consistency for data distributed across different shards. Resume os problemas em torno da manutenção de consistência de dados distribuídos e descreve os benefícios e as vantagens e desvantagens de modelos diferentes de consistência.Summarizes the issues surrounding maintaining consistency over distributed data, and describes the benefits and tradeoffs of different consistency models.
  • Orientação de particionamento de dados.Data Partitioning Guidance. A fragmentação de um repositório de dados pode apresentar uma variedade de outros problemas.Sharding a data store can introduce a range of additional issues. Descreve esses problemas em relação ao particionamento de repositórios de dados na nuvem para melhorar a escalabilidade, reduzir a contenção e otimizar o desempenho.Describes these issues in relation to partitioning data stores in the cloud to improve scalability, reduce contention, and optimize performance.
  • Padrão de Tabela de Índice.Index Table pattern. Às vezes, não é possível oferecem suporte total a consultas apenas por meio do design da chave de fragmentação.Sometimes it isn't possible to completely support queries just through the design of the shard key. Permite que um aplicativo recupere rapidamente os dados de um repositório de dados grande especificando uma chave que não seja a chave de fragmentação.Enables an application to quickly retrieve data from a large data store by specifying a key other than the shard key.
  • Padrão de exibição materializado.Materialized View pattern. Para manter o desempenho de algumas operações de consulta, é útil criar exibições materializadas que agreguem e resumam dados, especialmente se esses dados de resumo se basearem em informações distribuídas entre fragmentos.To maintain the performance of some query operations, it's useful to create materialized views that aggregate and summarize data, especially if this summary data is based on information that's distributed across shards. Descreve como gerar e preencher esses modos de exibição.Describes how to generate and populate these views.