Há muitos anos, li "Os dez anos da tecnologia Taobao" do professor Ziliu . Este livro se tornou meu livro de iluminação arquitetônica, e uma frase do livro foi enterrada em minha mente como uma semente: "Uma boa arquitetura vem da evolução, não do design " .
Em 2015, entrei para a equipe de P&D do pedido de carros especiais da China e experimentei o processo de "evolução da arquitetura" da camada de dados de carros especiais. Esta experiência de trabalho é muito inspiradora para mim, e também me faz muitas vezes suspirar: "Uma boa arquitetura realmente evolui um pouco."
1 Arquitetura de banco de dados único
No estágio inicial do produto, o objetivo principal da equipe técnica é: "Realizar rapidamente os requisitos do produto e fornecer serviços externos o mais rápido possível " .
Naquela época, o serviço de carro particular estava conectado a um banco de dados SQLServer e a camada de serviço era dividida até certo ponto de acordo com o campo de negócios.
Essa estrutura é muito simples, as equipes podem colaborar separadamente e a eficiência é extremamente alta. Com o aumento contínuo do número de pedidos de carros, nos horários de pico da manhã e da noite, quando os usuários precisam pegar um táxi, muitas vezes não há resposta após clicar para fazer um pedido.
No nível do sistema:
-
Os gargalos do banco de dados aparecem. Operações de disco frequentes levam a um aumento no consumo de E/S do servidor de banco de dados. Ao mesmo tempo, associação multitabela, classificação, agrupamento e consulta condicional de campo sem índice também farão com que a CPU suba, o que acabará levando a um aumento no número de conexões de banco de dados;
-
Tempo limite em massa do gateway. Em um cenário de alta simultaneidade, um grande número de solicitações opera diretamente no banco de dados, os recursos de conexão com o banco de dados não são suficientes e um grande número de solicitações é bloqueado.
2 Otimização SQL e separação leitura-gravação
Para aliviar a pressão sobre o banco de dados principal, é fácil pensar em uma estratégia: otimização de SQL . Por meio da plataforma de monitoramento de desempenho e colegas DBA, o SQL lento do negócio é analisado e o plano de otimização é resolvido:
-
Adicione índices razoavelmente;
-
Reduza a associação JOIN de várias tabelas e reduza a pressão de leitura do banco de dados por meio da montagem do programa;
-
Reduza grandes transações e libere conexões de banco de dados o mais rápido possível.
Outra estratégia é: separação leitura-gravação .
O princípio básico da separação leitura-gravação é permitir que o banco de dados primário lide com operações de adição, modificação e exclusão transacionais (INSERT, UPDATE, DELETE), enquanto o banco de dados escravo lida com operações de consulta SELECT.
Na estrutura fornecida pela equipe especial de arquitetura de carros , a separação de leitura e gravação é suportada, de modo que a arquitetura da camada de dados evolui para a seguinte figura:
A separação de leitura-gravação pode reduzir a pressão de gravação da biblioteca principal, enquanto a biblioteca de leitura-escrava pode ser expandida horizontalmente. Obviamente, a separação leitura-gravação ainda tem limitações:
-
Separação de leitura e escrita pode enfrentar o problema de atraso mestre-escravo.Os requisitos de tempo real são altos no processo de serviço de pedido e carregamento de passageiros.Devido a preocupações com atraso, um grande número de operações ainda usa a consulta principal da biblioteca;
-
A separação de leitura e gravação pode aliviar a pressão de leitura, mas a pressão das operações de gravação não foi efetivamente aliviada com o crescimento explosivo dos negócios.
3 Sub-banco de dados de campos de negócios
Embora o nível do aplicativo tenha sido otimizado e a camada de dados também tenha sido separada da leitura e gravação, a pressão na biblioteca principal ainda é muito alta. Em seguida, todos pensaram unanimemente no sub-banco de dados de domínio de negócios , ou seja: dividir o banco de dados em diferentes bancos de dados de negócios de acordo com o domínio de negócios, e cada sistema acessará apenas o banco de dados correspondente ao negócio.
O subbanco de dados do campo de negócios pode aliviar a pressão de desempenho da biblioteca principal de pedidos e, ao mesmo tempo, reduzir a interação entre os sistemas e melhorar a estabilidade geral do sistema.
O problema resultante é: no caso de um único banco de dados, o uso simples de JOIN pode atender aos requisitos, mas depois que o banco de dados de negócios dividido estiver em instâncias diferentes, JOIN não pode ser usado em bancos de dados, portanto, o limite do sistema precisa ser reorganizado, o o sistema de negócios também precisa ser refatorado .
O foco da refatoração consiste em duas partes:
-
A consulta que originalmente exigia associação JOIN foi alterada para uma chamada RPC e os dados foram reunidos no programa;
-
Os campos adequadamente redundantes nas tabelas de negócios são sincronizados por meio de filas de mensagens ou ferramentas heterogêneas.
4 Cache e MQ
No serviço de carro particular, o serviço de pedidos tem a maior simultaneidade e volume de solicitações, sendo também o serviço principal do negócio. Embora o desempenho do sistema tenha melhorado bastante por meio do subbanco de dados do campo de negócios e da otimização SQL, a pressão de gravação do banco de dados de pedidos ainda é muito alta e o gargalo do sistema ainda é óbvio.
Portanto, o serviço de pedidos apresenta cache e MQ .
O passageiro clica para chamar um carro imediatamente no lado do cliente , o serviço de pedidos cria um pedido, primeiro o salva no banco de dados e, em seguida, salva as informações do pedido no cache de forma síncrona.
No ciclo de vida do pedido do passageiro, a operação de modificação do pedido primeiro modifica o cache, depois envia uma mensagem para MetaQ , o serviço de colocação de pedidos consome a mensagem e julga se as informações do pedido são normais (como se há desordem ) Se os dados do pedido estiverem corretos, então armazenados no banco de dados.
A lógica central tem dois pontos:
-
O cluster de cache armazena detalhes de pedidos dos últimos sete dias e um grande número de pedidos de leitura de pedidos é obtido diretamente do cache;
-
No ciclo de vida do pedido do passageiro, a operação de gravação primeiro modifica o cache e coloca o pedido de forma assíncrona por meio da fila de mensagens, para que a fila de mensagens possa desempenhar um papel na eliminação de pico e também reduzir a pressão no banco de dados.
Essa otimização melhorou o desempenho geral do serviço de pedidos e também estabeleceu uma base sólida para o subbanco de dados subsequente e a subtabela do banco de dados e heterogeneidade do serviço de pedidos.
5 Do SQL Server para o MySQL
O negócio ainda está crescendo de forma explosiva, com centenas de milhares de pedidos por dia, o volume de dados da tabela de pedidos logo ultrapassará 100 milhões e o teto do banco de dados será atingido mais cedo ou mais tarde.
A subtabela do subbanco de dados de pedidos tornou-se o consenso da equipe técnica. Muitas soluções de sub-banco de dados e sub-tabela na indústria são baseadas no banco de dados MySQL. O gerenciamento da tecnologia de carros especiais decidiu primeiro migrar todo o banco de dados de pedidos de SQLServer para MySQL.
Antes de migrar, os preparativos são importantes:
-
O SQLServer e o MySQL possuem algumas diferenças na sintaxe dos dois bancos de dados, e o serviço de pedidos deve se adaptar à sintaxe do MySQL.
-
O order_id do pedido é o incremento automático de chave primária, mas não é adequado no cenário distribuído, e o id do pedido precisa ser ajustado para o modo distribuído.
Quando as preparações estiverem concluídas, inicie a migração.
O processo de migração é dividido em duas partes: migração de dados histórica completa e migração de dados incremental .
A migração completa de dados históricos é principalmente para alunos de DBA sincronizarem o banco de dados de pedidos com um banco de dados MySQL independente por meio de ferramentas.
Migração de dados incremental: como o SQLServer não tem conceito de log binário, soluções semelhantes, como maxwell e canal, não podem ser usadas. A equipe de pedidos refatorou o código de serviço do pedido e, toda vez que um pedido for escrito, ele enviará uma mensagem MQ para o MetaQ. Para garantir a confiabilidade da migração, também é necessário sincronizar os dados do novo banco de dados com o antigo, ou seja, é necessária a sincronização bidirecional .
Processo de migração:
-
Primeiro, o serviço de pedidos (versão SQLServer) envia uma mensagem de alteração de pedido para o MetaQ. Neste momento, o "consumo de mensagens antigas do banco de dados" não está habilitado, de modo que as mensagens são acumuladas no MetaQ primeiro;
-
Em seguida, inicie a migração da quantidade total de dados históricos. Após a conclusão da migração completa, ative "Consumo de mensagens do banco de dados antigo", para que o novo banco de dados de pedidos possa ser sincronizado com os dados do banco de dados de pedidos antigos;
-
Ative "consumo de novas mensagens do banco de dados" e, em seguida, implante o serviço de pedidos (versão MySQL). No momento, duas versões do serviço de pedidos estão sendo executadas ao mesmo tempo. Depois que os dados de detecção estiverem corretos, aumente gradualmente o tráfego do novo serviço de pedidos até que o antigo serviço de pedidos esteja completamente offline.
6 Componentes de sub-banco de dados e sub-tabela autodesenvolvidos
Existem geralmente dois gêneros de sub-banco de dados e sub-tabela na indústria: proxy e cliente.
▍ modo proxy
As soluções de sharding de camada proxy incluem Mycat , cobar , etc. na indústria.
Suas vantagens: o aplicativo não tem alterações, não tem nada a ver com o idioma e pode reduzir o consumo de conexões por meio do compartilhamento de conexão. Desvantagem: Por ser uma camada de proxy, há atraso adicional.
▍ modo cliente
As soluções de sharding da camada de aplicativos incluem sharding-jdbc , TDDL, etc. na indústria.
Suas vantagens: conexão direta com o banco de dados, baixo overhead, implementação simples e middleware leve. Desvantagens: Incapaz de reduzir o consumo de conexões, um tanto intrusivo, e a maioria suporta apenas a linguagem Java.
A equipe de arquitetura de Shenzhou escolheu o sub-banco de dados autodesenvolvido e os componentes da sub-tabela, adotou o modo cliente e nomeou os componentes: SDDL .
O serviço de pedido precisa importar o pacote SDDL jar e configurar as informações da fonte de dados , chave de fragmentação , regras de roteamento etc. no centro de configuração. O serviço de pedido só precisa configurar um datasourceId .
7 Estratégia de subtabela do subbanco de dados
7.1 Dimensão do passageiro
A principal dimensão de consulta do banco de dados de pedidos de carros particulares é: passageiro , o terminal de passageiros tem a maior frequência de consulta de acordo com o passageiro user_id e order_id , escolhemos user_id como a chave de fragmentação e os dados do pedido do mesmo usuário são armazenados no mesmo base de dados.
O componente de sub-banco de dados e sub-tabela SDDL é muito semelhante ao algoritmo de roteamento cobar do middleware de banco de dados de código aberto de Ali.
Para facilitar a expansão do pensamento, primeiro introduza brevemente o algoritmo de fragmentação de cobar.
Suponha que a tabela de pedidos precise ser dividida uniformemente em 4 subbibliotecas shard0, shard1, shard2 e shard3. Primeiro divida [0-1023] em 4 seções: [0-255], [256-511], [512-767], [768-1023] e depois a string (ou substring, pelo usuário Custom) para fazer hash, e o resultado do hash é o módulo 1024, e o segmento no qual o slot do resultado final se enquadra será roteado para qual sub-biblioteca.
O algoritmo de roteamento padrão do Cobar pode ser naturalmente integrado ao algoritmo do floco de neve . O order_id usa o algoritmo do floco de neve e podemos salvar o valor do slot no ID da máquina do trabalhador de 10 dígitos .
O slot pode ser detectado inversamente por meio do order_id do pedido e a partição na qual os dados do pedido do usuário são armazenados pode ser localizada.
1
Integer getWorkerId(PedidoId longo) {
2
Long workerId = (orderId >> 12) & 0x03ff;
3
return workerId.intValue();
4
}
As diferenças entre o algoritmo de fragmentação SDDL do carro particular e o cobar são:
-
O Cobar suporta um número máximo de fragmentos de 1024, enquanto o SDDL suporta um número máximo de fragmentos de 1024 * 8 = 8192. Ele também é dividido em quatro bibliotecas de pedidos e o intervalo de slot de cada fragmento é 2048;
-
Para dar suporte a 8192 fragmentos, o algoritmo do floco de neve precisa ser ajustado. A máquina de trabalho de 10 bits do algoritmo do floco de neve é alterada para uma máquina de trabalho de 13 bits e o carimbo de data/hora também é ajustado para: carimbo de data/hora de 38 bits (o número de milissegundos a partir de um determinado ponto no tempo).
7.2 Dimensões do Condutor
Embora o problema da sub-base de dados e sub-tabela de passageiros na dimensão principal tenha sido resolvido, existe uma outra dimensão de consulta do carro especial, no cliente motorista, o motorista precisa consultar as informações do pedido que lhe foram atribuídas.
Usamos o user_id do passageiro como a chave de fragmentação. Se consultarmos o pedido de acordo com o driver driver_id , ele precisa ser transmitido para cada subbanco de dados e agregado e retornado. Com base nisso, a equipe técnica optou por heterogeneizar os dados do pedido da dimensão do passageiro para o banco de dados da dimensão do motorista.
A estratégia de tabela e subbanco de dados da dimensão do motorista é a mesma da dimensão do passageiro, exceto que a chave de fragmentação se torna o driver_id .
O canal de artefato heterogêneo analisa os binlogs dos quatro subbancos de dados da dimensão do passageiro e os grava nos quatro subbancos de dados da dimensão do motorista por meio do SDDL .
Aqui você pode ter uma pergunta: Embora os pedidos possam ser sincronizados de forma heterogênea ao sub-banco de dados da dimensão do motorista, afinal, há um pequeno atraso, como garantir que o motorista possa consultar os últimos dados do pedido no lado do motorista?
Na seção sobre armazenamento em cache e MQ , é mencionado que o cluster de cache armazena os detalhes do pedido nos últimos sete dias e um grande número de pedidos de leitura do pedido é obtido diretamente do cache. O serviço de pedidos armazenará em cache o mapeamento entre o driver e o pedido atual, de modo que um grande número de solicitações do lado do driver possa ser obtido diretamente do cache, enquanto a frequência de consulta da lista de pedidos no lado do driver não é tão alta , e o atraso de replicação heterogêneo está entre 10 milissegundos e 30 milissegundos. é perfeitamente aceitável.
7.3 Dimensões de Operação
No back-end do gerenciamento de carros especiais, os operadores geralmente precisam consultar as informações do pedido e as condições de consulta serão mais complicadas. O método adotado pela equipe técnica do carro especial é: depois que os dados do pedido são colocados no subbanco de dados do pedido de Na dimensão do passageiro, os dados são sincronizados com o Elastic Search por meio do canal.
7.4 Transmissão de relógio pequeno
Existem algumas tabelas de configuração no negócio, que armazenam configurações importantes, e leem mais e escrevem menos. Na consulta de negócios real, muitas tabelas de negócios executarão consultas de dados conjuntas com tabelas de configuração. Mas depois que o banco de dados é dividido horizontalmente, a tabela de configuração não pode ser dividida.
O princípio da transmissão de mesa pequena é: transmitir automaticamente (ou seja, copiar) todos os dados da mesa pequena (incluindo atualizações incrementais) para a máquina da mesa grande. Dessa forma, a consulta JOIN distribuída original torna-se uma consulta local autônoma, o que melhora muito a eficiência.
No cenário de carros particulares, a transmissão de pequenos relógios é um requisito muito prático. Por exemplo: a tabela city é uma tabela de configuração muito importante com uma quantidade muito pequena de dados, mas o serviço de pedidos, o serviço de despacho e o serviço ao usuário dependem dessa tabela.
Sincronize a tabela de cidades do banco de dados de configuração básica com o banco de dados de pedidos, banco de dados de despacho e banco de dados de usuários por meio do canal.
8 Migração Suave
Depois que o desenvolvimento do SDDL do componente de sub-banco de dados e sub-tabela for concluído e o ambiente de produção tiver sido verificado até certo ponto, as condições para migrar o serviço de pedidos do modo MySQL de banco de dados único para o sub-banco de dados e sub -table mode estão maduros.
A ideia de migração é realmente muito semelhante à do SQL Server para o MySQL .
Processo geral de migração:
-
Os alunos de DBA preparam quatro subbancos de dados para dimensões de passageiros e quatro subbancos de dados para dimensões de motoristas, cada um contendo dados completos em um momento recente;
-
Os oito subbancos de dados são todos dados em escala real, e os dados redundantes dos oito subbancos de dados precisam ser excluídos de acordo com as regras do subbanco de dados e da tabela;
-
Ative a sincronização direta e os dados do pedido antigo serão transferidos para o subbanco de dados da dimensão do passageiro de acordo com o subbanco de dados e a estratégia da tabela, e os dados do pedido do subbanco de dados da dimensão do passageiro serão copiados de forma heterogênea para o sub-base de dados da dimensão do driver através do canal;
-
Ative a sincronização reversa, modifique a configuração da fonte de dados do aplicativo de pedidos, reinicie o serviço de pedidos e os pedidos recém-criados do serviço de pedidos serão colocados no subbanco de dados da dimensão do passageiro e os dados do pedido da dimensão do passageiro o sub-banco de dados é heterogêneo ao banco de dados de pedidos completo e ao driver através do banco de dados de dimensões do canal;
-
Depois de verificar se os dados estão corretos, atualize gradualmente a configuração da fonte de dados do serviço de pedidos para concluir a migração geral.
9 plataforma de troca de dados
O pedido do carro especial foi dividido em bancos de dados e tabelas, e vale a pena revisar muitos detalhes:
-
A quantidade total de migração de dados históricos requer intervenção de DBA e a equipe técnica não possui ferramentas ou produtos maduros para concluí-la facilmente;
-
A migração de dados incremental é obtida através do canal. Com o crescimento explosivo do negócio de carros particulares, há cada vez mais demandas por espelhamento de banco de dados, construção de índices em tempo real e subbancos de dados heterogêneos. Embora o canal seja muito bom, ele ainda apresenta falhas, como falta de consoles de tarefas, recursos de gerenciamento de fonte e níveis de tarefa Monitoramento e alarme, auditoria de operação e outras funções.
Diante desses problemas, o objetivo da equipe de arquitetura é construir uma plataforma que possa satisfazer a sincronização incremental em tempo real e a sincronização completa off-line entre várias fontes de dados heterogêneas e apoiar o rápido desenvolvimento dos negócios da empresa.
Com base nesse objetivo, a equipe de arquitetura desenvolveu o dataLink para sincronização incremental de dados e personalizou profundamente o dataX de código aberto do Alibaba para sincronização completa de dados.
10 escrever até o fim
A evolução da arquitetura do carro particular não foi fácil, e também há voltas e reviravoltas, mas passo a passo, a reserva técnica do carro particular está ficando cada vez mais profunda.
A Luckin Coffee foi incubada dentro do Grupo UCAR em 2017. Essas reservas técnicas do carro especial melhoraram muito a eficiência de P&D da equipe técnica da Luckin Coffee e apoiaram o rápido desenvolvimento do negócio. Por exemplo, quando o banco de dados de pedidos da Ruixing Coffee foi planejado pela primeira vez, ele se dividiu em 8 instâncias de banco de dados de acordo com a dimensão do usuário e a dimensão da loja, respectivamente. O subbanco de dados e os componentes da subtabela SDDL e a plataforma de troca de dados desempenharam um papel fundamental .
Bem, este texto está escrito aqui. Vejo você na próxima vez.
Se meu artigo for útil para você, por favor , goste, leia e encaminhe . Seu apoio me inspirará a produzir artigos de maior qualidade, muito obrigado!