O passado da evolução da arquitetura do carro: uma boa arquitetura é desenvolvida, não projetada

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:

  1. 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;

  2. 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:

  1. Adicione índices razoavelmente;

  2. 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;

  3. 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:

  1. 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;

  2. 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:

  1. A consulta que originalmente exigia associação JOIN foi alterada para  uma chamada RPC  e os dados foram reunidos no programa;

  2. 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:

  1. 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;

  2. 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:

  1. 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.

  2. 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:

  1. 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;

  2. 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;

  3. 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:

  1. 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;

  1. 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:

  1. 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;

  2. 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;

  3. 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;

  4. 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;

  5. 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:

  1. 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;

  2. 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!

Acho que você gosta

Origin blog.csdn.net/makemyownlife/article/details/123697722
Recomendado
Clasificación