Dimensione bancos de dados com o gerenciador de mapas de estilhaços

Aplica-se a:Banco de Dados SQL do Azure

Para expandir facilmente os bancos de dados no Banco de Dados SQL do Azure, use um gerenciador de mapas de estilhaços. O gerenciador de mapas de estilhaços é um banco de dados especial que mantém informações de mapeamento global sobre todos os fragmentos (bancos de dados) em um conjunto de fragmentos. Os metadados permitem que um aplicativo se conecte ao banco de dados correto com base no valor da chave de fragmentação. Além disso, cada fragmento no conjunto contém mapas que rastreiam os dados de fragmentos locais (conhecidos como shardlets).

Shard map management

Entender como esses mapas são construídos é essencial para o gerenciamento de mapas de estilhaços. Isso é feito usando a classe ShardMapManager (Java, .NET), encontrada na biblioteca de cliente do Elastic Database para gerenciar mapas de estilhaços.

Mapas de estilhaços e mapeamentos de estilhaços

Para cada fragmento, você deve selecionar o tipo de mapa de estilhaços a ser criado. A escolha depende da arquitetura do banco de dados:

  1. Locatário único por banco de dados
  2. Vários locatários por banco de dados (dois tipos):
    1. Mapeamento de listas
    2. Mapeamento de alcance

Para um modelo de locatário único, crie um mapa de estilhaços de mapeamento de lista. O modelo de locatário único atribui um banco de dados por locatário. Este é um modelo eficaz para desenvolvedores de SaaS, pois simplifica o gerenciamento de mapas de estilhaços.

List mapping

O modelo multilocatário atribui vários locatários a um banco de dados individual (e você pode distribuir grupos de locatários em vários bancos de dados). Use esse modelo quando você espera que cada locatário tenha pequenas necessidades de dados. Neste modelo, atribua um intervalo de locatários a um banco de dados usando o mapeamento de intervalo.

Range mapping

Ou você pode implementar um modelo de banco de dados multilocatário usando um mapeamento de lista para atribuir vários locatários a um banco de dados individual. Por exemplo, o DB1 é usado para armazenar informações sobre o ID do locatário 1 e 5, e o DB2 armazena dados para o locatário 7 e o locatário 10.

Multiple tenants on single DB

Tipos suportados para chaves de fragmentação

O Elastic Scale suporta os seguintes tipos como chaves de fragmentação:

.NET Java
integer integer
long long
guid uuid
byte[] byte[]
datetime carimbo de data/hora
timespan duration
datetimeoffset OffsetDateTime

Mapas de estilhaços de lista e intervalo

Os mapas de estilhaços podem ser construídos usando listas de valores de chave de fragmentação individuais ou podem ser construídos usando intervalos de valores de chave de fragmentação.

Listar mapas de estilhaços

Os fragmentos contêm shardlets e o mapeamento de shardlets para shardlets é mantido por um mapa de estilhaços. Um mapa de estilhaços de lista é uma associação entre os valores de chave individuais que identificam os shardlets e os bancos de dados que servem como fragmentos. Os mapeamentos de lista são explícitos e diferentes valores de chave podem ser mapeados para o mesmo banco de dados. Por exemplo, o valor-chave 1 mapeia para o banco de dados A e os valores-chave 3 e 6 são mapeados para o banco de dados B.

Key Localização do estilhaço
5 Database_A
3 Database_B
4 Database_C
6 Database_B
... ...

Mapas de estilhaços de alcance

Em um mapa de estilhaços de intervalo, o intervalo de chaves é descrito por um par [Baixo Valor, Alto Valor) onde o Valor Baixo é a chave mínima no intervalo e o Valor Alto é o primeiro valor maior do que o intervalo.

Por exemplo, [0, 100] inclui todos os números inteiros maiores ou iguais a 0 e menores que 100. Observe que vários intervalos podem apontar para o mesmo banco de dados e intervalos separados são suportados (por exemplo, [100.200] e [400.600) ambos apontam para o Banco de Dados C no exemplo a seguir.)

Key Localização do estilhaço
[1,50) Database_A
[50,100) Database_B
[100,200) Database_C
[400,600) Database_C
... ...

Cada uma das tabelas mostradas acima é um exemplo conceitual de um objeto ShardMap . Cada linha é um exemplo simplificado de um objeto individual PointMapping (para o mapa de estilhaços de lista) ou RangeMapping (para o mapa de estilhaços de intervalo).

Gestor de mapas de partições horizontais

Na biblioteca do cliente, o gerenciador de mapas de estilhaços é uma coleção de mapas de estilhaços. Os dados gerenciados por uma instância do ShardMapManager são mantidos em três locais:

  1. Global Shard Map (GSM): Você especifica um banco de dados para servir como repositório para todos os seus mapas e mapeamentos de estilhaços. Tabelas especiais e procedimentos armazenados são criados automaticamente para gerenciar as informações. Este é normalmente um banco de dados pequeno e levemente acessado, e não deve ser usado para outras necessidades do aplicativo. As tabelas estão em um esquema especial chamado __ShardManagement.
  2. Mapa de estilhaços locais (LSM): Cada banco de dados especificado como um fragmento é modificado para conter várias tabelas pequenas e procedimentos armazenados especiais que contêm e gerenciam informações de mapa de estilhaços específicas para esse fragmento. Esta informação é redundante com a informação no GSM, e permite que a aplicação valide a informação do mapa de estilhaços em cache sem colocar qualquer carga no GSM; o aplicativo usa o LSM para determinar se um mapeamento armazenado em cache ainda é válido. As tabelas correspondentes ao LSM em cada fragmento também estão no esquema __ShardManagement.
  3. Cache do aplicativo: cada instância do aplicativo que acessa um objeto ShardMapManager mantém um cache local na memória de seus mapeamentos. Ele armazena informações de roteamento que foram recuperadas recentemente.

Construindo um ShardMapManager

Um objeto ShardMapManager é construído usando um padrão de fábrica (Java, .NET). O método ShardMapManagerFactory.GetSqlShardMapManager (Java, .NET) usa credenciais (incluindo o nome do servidor e o nome do banco de dados que contém o GSM) na forma de um ConnectionString e retorna uma instância de um ShardMapManager.

Observação: O ShardMapManager deve ser instanciado apenas uma vez por domínio de aplicativo, dentro do código de inicialização de um aplicativo. A criação de instâncias adicionais do ShardMapManager no mesmo domínio do aplicativo resulta no aumento da utilização da memória e da CPU do aplicativo. Um ShardMapManager pode conter qualquer número de mapas de estilhaços. Embora um único mapa de estilhaços possa ser suficiente para muitos aplicativos, há momentos em que diferentes conjuntos de bancos de dados são usados para esquemas diferentes ou para fins exclusivos; nesses casos, podem ser preferíveis vários mapas de estilhaços.

Neste código, um aplicativo tenta abrir um ShardMapManager existente com o TryGetSqlShardMapManager (Java, método .NET . Se os objetos que representam um Global ShardMapManager (GSM) ainda não existirem dentro do banco de dados, a biblioteca de cliente os criará usando o método CreateSqlShardMapManager (Java, .NET).

// Try to get a reference to the Shard Map Manager in the shardMapManager database.
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager = null;
boolean shardMapManagerExists = ShardMapManagerFactory.tryGetSqlShardMapManager(shardMapManagerConnectionString,ShardMapManagerLoadPolicy.Lazy, refShardMapManager);
shardMapManager = refShardMapManager.argValue;

if (shardMapManagerExists) {
    ConsoleUtils.writeInfo("Shard Map %s already exists", shardMapManager);
}
else {
    // The Shard Map Manager does not exist, so create it
    shardMapManager = ShardMapManagerFactory.createSqlShardMapManager(shardMapManagerConnectionString);
    ConsoleUtils.writeInfo("Created Shard Map %s", shardMapManager);
}
// Try to get a reference to the Shard Map Manager via the Shard Map Manager database.  
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager;
bool shardMapManagerExists = ShardMapManagerFactory.TryGetSqlShardMapManager(
                                        connectionString,
                                        ShardMapManagerLoadPolicy.Lazy,
                                        out shardMapManager);

if (shardMapManagerExists)
{
    Console.WriteLine("Shard Map Manager already exists");
}
else
{
    // Create the Shard Map Manager.
    ShardMapManagerFactory.CreateSqlShardMapManager(connectionString);
    Console.WriteLine("Created SqlShardMapManager");

    shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
            connectionString,
            ShardMapManagerLoadPolicy.Lazy);

// The connectionString contains server name, database name, and admin credentials for privileges on both the GSM and the shards themselves.
}

Para a versão .NET, você pode usar o PowerShell para criar um novo Gerenciador de Mapas de Fragmentos. Um exemplo está disponível aqui.

Obter um RangeShardMap ou ListShardMap

Depois de criar um gerenciador de mapas de estilhaços, você pode obter o RangeShardMap (Java, .NET) ou ListShardMap (Java, .NET) usando o TryGetRangeShardMap (Java, .NET), o TryGetListShardMap (Java, .NET) ou o método GetShardMap (Java, .NET).

// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
static <T> RangeShardMap<T> createOrGetRangeShardMap(ShardMapManager shardMapManager,
            String shardMapName,
            ShardKeyType keyType) {
    // Try to get a reference to the Shard Map.
    ReferenceObjectHelper<RangeShardMap<T>> refRangeShardMap = new ReferenceObjectHelper<>(null);
    boolean isGetSuccess = shardMapManager.tryGetRangeShardMap(shardMapName, keyType, refRangeShardMap);
    RangeShardMap<T> shardMap = refRangeShardMap.argValue;

    if (isGetSuccess && shardMap != null) {
        ConsoleUtils.writeInfo("Shard Map %1$s already exists", shardMap.getName());
    }
    else {
        // The Shard Map does not exist, so create it
        try {
            shardMap = shardMapManager.createRangeShardMap(shardMapName, keyType);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        ConsoleUtils.writeInfo("Created Shard Map %1$s", shardMap.getName());
    }

    return shardMap;
}
// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
public static RangeShardMap<T> CreateOrGetRangeShardMap<T>(ShardMapManager shardMapManager, string shardMapName)
{
    // Try to get a reference to the Shard Map.
    RangeShardMap<T> shardMap;
    bool shardMapExists = shardMapManager.TryGetRangeShardMap(shardMapName, out shardMap);

    if (shardMapExists)
    {
        ConsoleUtils.WriteInfo("Shard Map {0} already exists", shardMap.Name);
    }
    else
    {
        // The Shard Map does not exist, so create it
        shardMap = shardMapManager.CreateRangeShardMap<T>(shardMapName);
        ConsoleUtils.WriteInfo("Created Shard Map {0}", shardMap.Name);
    }

    return shardMap;
}

Credenciais de administração do mapa de estilhaços

Os aplicativos que administram e manipulam mapas de estilhaços são diferentes daqueles que usam os mapas de estilhaços para rotear conexões.

Para administrar mapas de estilhaços (adicionar ou alterar fragmentos, mapas de estilhaços, mapeamentos de estilhaços, etc.) você deve instanciar o ShardMapManager usando credenciais que tenham privilégios de leitura/gravação no banco de dados GSM e em cada banco de dados que serve como fragmento. As credenciais devem permitir gravações nas tabelas no GSM e LSM à medida que as informações do mapa de estilhaços são inseridas ou alteradas, bem como para a criação de tabelas LSM em novos fragmentos.

Consulte Credenciais usadas para acessar a biblioteca de cliente do Elastic Database.

Apenas metadados afetados

Os métodos usados para preencher ou alterar os dados do ShardMapManager não alteram os dados do usuário armazenados nos próprios fragmentos. Por exemplo, métodos como CreateShard, DeleteShard, UpdateMapping, etc. afetam apenas os metadados do mapa de estilhaços. Eles não removem, adicionam ou alteram os dados do usuário contidos nos fragmentos. Em vez disso, esses métodos são projetados para serem usados em conjunto com operações separadas que você executa para criar ou remover bancos de dados reais, ou que movem linhas de um fragmento para outro para reequilibrar um ambiente fragmentado. (A ferramenta de mesclagem dividida incluída nas ferramentas de banco de dados elástico usa essas APIs juntamente com a orquestração da movimentação real de dados entre fragmentos.) Consulte Dimensionamento usando a ferramenta de mesclagem dividida do Banco de Dados Elástico.

Encaminhamento dependente de dados

O gerenciador de mapa de estilhaços é usado em aplicativos que exigem conexões de banco de dados para executar as operações de dados específicas do aplicativo. Essas conexões devem ser associadas ao banco de dados correto. Isso é conhecido como Roteamento Dependente de Dados. Para esses aplicativos, instancie um objeto do gerenciador de mapas de estilhaços de fábrica usando credenciais que tenham acesso somente leitura no banco de dados GSM. Solicitações individuais para conexões posteriores fornecem credenciais necessárias para se conectar ao banco de dados de estilhaços apropriado.

Observe que esses aplicativos (usando ShardMapManager aberto com credenciais somente leitura) não podem fazer alterações nos mapas ou mapeamentos. Para essas necessidades, crie aplicativos administrativos específicos ou scripts do PowerShell que forneçam credenciais com privilégios mais altos, conforme discutido anteriormente. Consulte Credenciais usadas para acessar a biblioteca de cliente do Elastic Database.

Para obter mais informações, consulte Roteamento dependente de dados.

Modificando um mapa de estilhaços

Um mapa de estilhaços pode ser alterado de diferentes maneiras. Todos os métodos a seguir modificam os metadados que descrevem os fragmentos e seus mapeamentos, mas não modificam fisicamente os dados dentro dos fragmentos, nem criam ou excluem os bancos de dados reais. Algumas das operações no mapa de estilhaços descritas abaixo podem precisar ser coordenadas com ações administrativas que movem dados fisicamente ou que adicionam e removem bancos de dados que servem como fragmentos.

Esses métodos funcionam juntos como os blocos de construção disponíveis para modificar a distribuição geral de dados em seu ambiente de banco de dados fragmentado.

  • Para adicionar ou remover fragmentos: use CreateShard (Java, .NET) e DeleteShard (Java, .NET) da classe shardmap (Java, .NET).

    O servidor e o banco de dados que representam o fragmento de destino já devem existir para que essas operações sejam executadas. Esses métodos não têm qualquer impacto nos bancos de dados em si, apenas nos metadados no mapa de estilhaços.

  • Para criar ou remover pontos ou intervalos mapeados para os fragmentos: use CreateRangeMapping (Java, .NET), DeleteMapping (Java, .NET) da classe RangeShardMapping (Java, .NET) e CreatePointMapping (Java, .NET) da classe ListShardMap (Java, .NET).

    Muitos pontos ou intervalos diferentes podem ser mapeados para o mesmo fragmento. Esses métodos afetam apenas metadados - eles não afetam quaisquer dados que já possam estar presentes em fragmentos. Se os dados precisarem ser removidos do banco de dados para serem consistentes com as operações DeleteMapping, execute essas operações separadamente, mas em conjunto com o uso desses métodos.

  • Para dividir intervalos existentes em dois ou mesclar intervalos adjacentes em um: use SplitMapping (Java, .NET) e MergeMappings (Java, .NET).

    Observe que as operações de divisão e mesclagem não alteram o fragmento para o qual os valores de chave são mapeados. Uma divisão divide um intervalo existente em duas partes, mas deixa ambas mapeadas para o mesmo fragmento. Uma mesclagem opera em dois intervalos adjacentes que já estão mapeados para o mesmo fragmento, aglutinando-os em um único intervalo. O movimento de pontos ou intervalos entre fragmentos precisa ser coordenado usando UpdateMapping em conjunto com o movimento real de dados. Você pode usar o serviço Dividir/Mesclar que faz parte das ferramentas de banco de dados elástico para coordenar as alterações do mapa de estilhaços com a movimentação de dados, quando a movimentação for necessária.

  • Para remapear (ou mover) pontos ou intervalos individuais para fragmentos diferentes: use UpdateMapping (Java, .NET).

    Como os dados podem precisar ser movidos de um fragmento para outro para serem consistentes com as operações UpdateMapping, você precisa executar esse movimento separadamente, mas em conjunto com o uso desses métodos.

  • Para realizar mapeamentos online e offline: use MarkMappingOffline (Java, .NET) e MarkMappingOnline (Java, .NET) para controlar o estado online de um mapeamento.

    Certas operações em mapeamentos de estilhaços só são permitidas quando um mapeamento está em um estado offline, incluindo UpdateMapping e DeleteMapping. Quando um mapeamento está offline, uma solicitação dependente de dados baseada em uma chave incluída nesse mapeamento retorna um erro. Além disso, quando um intervalo é colocado offline pela primeira vez, todas as conexões com o fragmento afetado são automaticamente eliminadas para evitar resultados inconsistentes ou incompletos para consultas direcionadas contra intervalos que estão sendo alterados.

Mapeamentos são objetos imutáveis no .NET. Todos os métodos acima que alteram mapeamentos também invalidam quaisquer referências a eles em seu código. Para facilitar a execução de sequências de operações que alteram o estado de um mapeamento, todos os métodos que alteram um mapeamento retornam uma nova referência de mapeamento, para que as operações possam ser encadeadas. Por exemplo, para excluir um mapeamento existente no shardmap sm que contém a chave 25, você pode executar o seguinte:

    sm.DeleteMapping(sm.MarkMappingOffline(sm.GetMappingForKey(25)));

Adicionar um fragmento

Os aplicativos geralmente precisam adicionar novos fragmentos para lidar com dados esperados de novas chaves ou intervalos de chaves, para um mapa de estilhaços que já existe. Por exemplo, um aplicativo fragmentado pela ID do locatário pode precisar provisionar um novo fragmento para um novo locatário ou os dados fragmentados mensalmente podem precisar de um novo fragmento provisionado antes do início de cada novo mês.

Se o novo intervalo de valores de chave ainda não fizer parte de um mapeamento existente e nenhuma movimentação de dados for necessária, é simples adicionar o novo fragmento e associar a nova chave ou intervalo a esse fragmento. Para obter detalhes sobre como adicionar novos fragmentos, consulte Adicionando um novo fragmento.

Para cenários que exigem movimentação de dados, no entanto, a ferramenta de mesclagem dividida é necessária para orquestrar a movimentação de dados entre fragmentos em combinação com as atualizações de mapa de estilhaços necessárias. Para obter detalhes sobre como usar a ferramenta de mesclagem dividida, consulte Visão geral da mesclagem dividida

Recursos adicionais

Ainda não está usando ferramentas de banco de dados elástico? Consulte o nosso Guia de Introdução. Para dúvidas, entre em contato conosco na página de perguntas e respostas da Microsoft para o Banco de dados SQL e para solicitações de recursos, adicione novas ideias ou vote em ideias existentes no fórum de comentários do Banco de dados SQL.