Temos um banco de dados de nível empresarial de escala muito grande. Como parte do nosso modelo de negócios, todos os usuários da Web acessam nossos servidores da Web ao mesmo tempo todos os meses, o que, por sua vez, martela nossa caixa sql. O tráfego é muito pesado e continua aumentando, quanto maior a empresa crescer. A otimização do proc sql foi realizada e o hardware já foi escalado para um nível muito alto.
Estamos procurando fragmentar o banco de dados agora para garantir que possamos lidar com o crescimento da empresa e com as cargas futuras.
Decidimos quais dados específicos devem ser fragmentados. É um subconjunto do nosso banco de dados que é altamente utilizado.
No entanto, minha pergunta é sobre os dados não fragmentados que são comuns / universais. Um exemplo de dados como esse pode ser uma tabela de inventário, por exemplo, ou possivelmente uma tabela de funcionários, tabela de usuários etc.
Vejo duas opções para lidar com esses dados comuns / universais:
1) design 1 - Coloque os dados comuns / universais em um banco de dados externo. Todas as gravações ocorrerão aqui. Esses dados serão replicados para cada fragmento, permitindo que cada fragmento leia esses dados e junte-os a esses dados em procs t-sql.
2) design 2 - Dê a cada fragmento sua própria cópia de todos os dados comuns / universais. Deixe cada shard gravar localmente nessas tabelas e utilizar a replicação de mesclagem sql para atualizar / sincronizar esses dados em todos os outros shards.
preocupações com o design nº 1
1) Problemas transacionais: se você tiver uma situação em que deve gravar ou atualizar dados em um shard e depois gravar / atualizar uma tabela comum / universal em 1 processo armazenado, por exemplo, não será mais possível fazer isso facilmente. Os dados agora existem em instâncias e bancos de dados sql separados. Pode ser necessário envolver o MS DTS para verificar se é possível agrupar essas gravações em uma transação, pois elas estão em um banco de dados separado. O desempenho é uma preocupação aqui e possíveis reescritas podem estar envolvidas para procs que gravam em dados compartilhados e comuns.
2) perda de integridade referencial. Não é possível fazer integridade referencial entre bancos de dados.
3) Recodificação de grandes áreas do sistema para que ele saiba gravar dados comuns no novo banco de dados universal, mas leia dados comuns dos shards.
4) aumento de viagens de banco de dados. Como no 1 acima, quando você se deparar com uma situação em que deve atualizar dados fragmentados e dados comuns, fará várias viagens de ida e volta para fazer isso, pois os dados agora estão em bancos de dados separados. Alguma latência de rede aqui, mas não estou preocupada com esse problema tanto quanto as anteriores 3.
preocupações sobre o projeto nº 2
No projeto nº 2, cada shard obtém sua própria instância de todos os dados comuns / universais. Isso significa que todo o código que une ou atualiza dados comuns continua a funcionar / executar exatamente como hoje. Há muito pouca recodificação / reescrita necessária da equipe de desenvolvimento. No entanto, esse design depende completamente da replicação de mesclagem para manter os dados sincronizados em todos os shards. os dbas são altamente qualificados e estão muito preocupados que a replicação de mesclagem possa não ser capaz de lidar com isso e que a replicação falhe, que a recuperação dessa falha não é boa e pode nos impactar muito negativamente.
Estou curioso para saber se alguém optou pela opção de design nº 2. Também estou curioso para saber se estou com vista para uma terceira ou quarta opção de design que não vejo.
Agradeço antecipadamente.
fonte
Respostas:
Sua pergunta se concentrou nisso:
Quando você está fazendo sharding e possui dados que todos os shards precisam ver, é necessário classificá-los com alguns atributos:
Isso muda com frequência? Nos seus exemplos, você listou Inventário, Funcionário e Usuário. Normalmente, o inventário muda muito rapidamente, mas os registros de funcionários mudam apenas periodicamente (por exemplo, algumas centenas de atualizações por dia).
Quanto atraso cada fragmento pode tolerar?Mesmo que o inventário possa estar constantemente mudando, você normalmente pode tolerar uma grande quantidade de atraso (minutos ou até horas) em uma tabela como essa. Se você estiver vendendo itens exclusivos com uma quantidade muito limitada que nunca poderá ser reabastecida (pense em obras de arte originais), não será possível compartilhar esses dados - você só consulta o banco de dados original. No entanto, na maioria das lojas on-line, você não está vendendo todos os itens todos os dias e, de qualquer maneira, reabastece as coisas rapidamente, para não precisar realmente de contagens de inventário de até milissegundos. De fato, na maioria dos casos, você só precisa de um sinalizador de estoque que seja 0 ou 1, e um processo central atualiza esse sinalizador. Dessa forma, você não precisa enviar todos os agrupamentos para cima / para baixo da contagem de itens para cada fragmento. Dados de funcionários ou usuários, por outro lado,
Você se juntará das mesas fragmentadas às não-fragmentadas? Idealmente, a resposta aqui é não - você deve fazer duas consultas separadas para obter os dados e depois se juntar a elas no lado do aplicativo. Isso fica muito mais difícil do ponto de vista do aplicativo, mas oferece a capacidade de obter os dados mais recentes de cada fonte.
Esses dados são originais ou copiados?Outra maneira de pensar nessa pergunta: do que você precisa fazer backup e com que frequência? Normalmente, em um ambiente de sharding de alto volume, você deseja que os backups sejam o mais rápido e o menor possível. (Afinal, você precisa proteger cada nó e deseja que todos os shards façam failover no DR no mesmo momento - não tenham alguns shards com dados mais recentes que outros.) Isso significa que os dados sharded e os não dados fragmentados devem estar em bancos de dados completamente separados - mesmo se estiverem no mesmo servidor. Talvez eu precise de backups constantes do log de transações dos meus dados fragmentados (originais), mas talvez não seja necessário fazer backup dos dados não fragmentados. Provavelmente é mais fácil atualizar minha tabela Funcionários ou Usuários da fonte única da verdade, em vez de fazer backup em todos os fragmentos. Se todos os meus dados estiverem em um único banco de dados,
Agora, sobre suas preocupações:
"Problemas transacionais ... você não poderá mais fazer isso facilmente." Corrigir. Em cenários fragmentados, jogue o conceito de uma transação pela janela. Também fica pior - para os dados fragmentados, você pode ter um fragmento ativo e online e outro fragmentado temporariamente devido a um failover ou reinicialização da instância de cluster. Você precisa planejar a falha de qualquer parte do sistema, a qualquer momento.
"Não é possível fazer integridade referencial entre bancos de dados." Corrigir. Ao dividir uma única tabela em vários servidores, você coloca suas calças e avisa ao servidor de banco de dados que está assumindo tarefas difíceis, como backups pontuais, relacionamentos entre tabelas e combinação de dados de Várias fontes. Está em você e no seu código agora.
"Recodificando grandes áreas do sistema para que ele saiba gravar dados comuns no novo banco de dados universal, mas leia dados comuns dos fragmentos". Corrija aqui também. Não há um botão fácil para isso, mas depois de incorporá-lo ao aplicativo, você pode escalar como um louco. Eu diria que a maneira mais fácil de fazer isso é dividir as conexões do aplicativo por leituras .
"aumento de viagens ao banco de dados." - Sim, se você dividir os dados em vários servidores, o aplicativo precisará acessar mais a rede. A chave é implementar o cache também, para que alguns desses dados possam ser armazenados em sistemas de baixo custo, maior rendimento e sem bloqueios. A consulta mais rápida é aquela que você nunca faz.
Também expus mais prós e contras da divisão de bancos de dados multilocatários aqui , como ajuste de desempenho em shards individuais, diferentes estratégias de backup / recuperação por shard e desafios de implantação de esquema.
fonte
Em um nível alto, a maneira típica de fragmentar (ou particionar horizontalmente) dados é fragmentar as tabelas transacionais e replicar as tabelas de nível mestre. Como a maioria das soluções de tecnologia, isso obviamente resolve um conjunto de problemas e cria um novo conjunto de problemas ... mas todos estamos acostumados a isso agora, não estamos? ;-)
Gostaria de perguntar se o SQLServer é sua melhor solução para isso, no entanto. A carga de trabalho é mais parecida com OLTP ou mais com DW / BI?
Saúde, Dave Sisk
fonte
Uma possível terceira opção. Usando o compartilhamento relacional (em vez do compartilhamento de caixa preta), você poderá compartilhar e distribuir todo o banco de dados. Como é construído a partir de um modelo de dados relacional tradicional, o banco de dados sabe quais dados são armazenados em quais servidores e, portanto, onde encontrá-los, para que todos os seus dados possam ser considerados 'comuns / universais'. Confira o dbShards como uma possibilidade para facilitar todo o processo de fragmentação.
fonte