Como parar de se preocupar e começar a viver sem um monólito

Como parar de se preocupar e começar a viver sem um monólito

Todos nós amamos histórias. Gostamos de sentar ao redor do fogo e conversar sobre nossas vitórias, batalhas passadas ou simplesmente sobre nossa experiência de trabalho.

Hoje é um dia assim. E mesmo que você não esteja no fogo agora, temos uma história para você. A história de como começamos a trabalhar com armazenamento no Tarantool.

Era uma vez, a nossa empresa tinha alguns “monólitos” e um “teto” para todos, ao qual esses monólitos se aproximavam lenta mas seguramente, limitando o voo da nossa empresa, o nosso desenvolvimento. E houve um entendimento claro: um dia vamos bater forte nesse teto.

É agora a ideologia predominante de separar tudo e todos, desde o equipamento até à lógica empresarial. Como resultado, temos, por exemplo, dois DCs praticamente independentes no nível da rede. E então tudo foi completamente diferente.

Hoje, existem muitas ferramentas e ferramentas para fazer alterações na forma de CI/CD, K8S, etc. Na época “monolítica”, não precisávamos de tantas palavras estrangeiras. Bastou simplesmente corrigir o “armazenamento” no banco de dados.

Mas o tempo avançou e o número de solicitações avançou junto com ele, às vezes disparando RPS além de nossas capacidades. Com a entrada dos países da CEI no mercado, a carga no processador de banco de dados do primeiro monólito não caiu abaixo de 90%, e o RPS permaneceu no nível de 2400. E estes não eram apenas pequenos seletores, mas consultas pesadas com um um monte de verificações e JOINs que poderiam ser executados para quase metade dos dados no contexto de grandes IO.

Quando as vendas completas da Black Friday começaram a aparecer em cena - e a Wildberries foi uma das primeiras a realizá-las na Rússia - a situação tornou-se completamente triste. Afinal, a carga nesses dias aumenta três vezes.
Ah, estes “tempos monolíticos”! Tenho certeza de que você já passou por algo semelhante e ainda não consegue entender como isso pode acontecer com você.

O que você pode fazer - a moda é inerente à tecnologia. Há cerca de 5 anos, tivemos que repensar um desses mods na forma de um site existente no servidor .NET e MS SQL, que armazenava cuidadosamente toda a lógica do próprio site. Guardei-o com tanto cuidado que serrar tal monólito acabou sendo um prazer longo e nada fácil.
Uma pequena digressão.

Em vários eventos eu digo: “se você não viu um monólito, então você não cresceu!” Estou interessado na sua opinião sobre este assunto, por favor escreva nos comentários.

E o trovão atingiu

Voltemos à nossa “fogueira”. Para distribuir a carga de funcionalidades “monolíticas”, decidimos dividir o sistema em microsserviços baseados em tecnologias de código aberto. Porque, no mínimo, são mais baratos de escalar. E tínhamos 100% de entendimento de que teríamos que escalar (e muito). Afinal, já nessa altura era possível entrar nos mercados dos países vizinhos, e o número de registos, bem como o número de encomendas, começaram a crescer ainda mais fortemente.

Depois de analisar os primeiros candidatos à saída do monólito para os microsserviços, percebemos que 80% da escrita neles vem dos sistemas de back office e da leitura do front office. Em primeiro lugar, tratava-se de alguns subsistemas importantes para nós - dados do usuário e um sistema para calcular o custo final das mercadorias com base em informações sobre descontos e cupons adicionais para clientes.

Recuado. Agora é assustador imaginar, mas além dos subsistemas mencionados acima, catálogos de produtos, carrinho de compras do usuário, sistema de busca de produtos, sistema de filtragem de catálogos de produtos e vários tipos de sistemas de recomendação também foram removidos de nosso monólito. Para a operação de cada um deles, existem classes separadas de sistemas estritamente adaptados, mas era uma vez que todos viviam na mesma “casa”.

Planejamos imediatamente transferir dados sobre nossos clientes para o sistema fragmentado. A retirada da funcionalidade de cálculo do custo final das mercadorias exigiu boa escalabilidade de leitura, pois criava a maior carga de RPS e era a mais difícil de implementar para o banco de dados (muitos dados estão envolvidos no processo de cálculo).

Como resultado, criamos um esquema que se adapta bem ao Tarantool.

Naquela época, para o funcionamento de microsserviços, foram escolhidos esquemas para trabalhar com diversos data centers em máquinas virtuais e de hardware. Conforme mostrado nas figuras, as opções de replicação do Tarantool foram aplicadas nos modos mestre-mestre e mestre-escravo.

Como parar de se preocupar e começar a viver sem um monólito
Arquitetura. Opção 1. Atendimento ao usuário

No momento, existem 24 shards, cada um com 2 instâncias (uma para cada DC), todas no modo master-master.

No topo do banco de dados estão os aplicativos que acessam as réplicas do banco de dados. Os aplicativos funcionam com o Tarantool por meio de nossa biblioteca personalizada, que implementa a interface do driver Tarantool Go. Ela vê todas as réplicas e pode trabalhar com o mestre para ler e escrever. Essencialmente, ele implementa o modelo de conjunto de réplicas, que adiciona lógica para seleção de réplicas, realização de novas tentativas, um disjuntor e um limite de taxa.

Neste caso, é possível configurar a política de seleção de réplicas no contexto dos shards. Por exemplo, roundrobin.

Como parar de se preocupar e começar a viver sem um monólito
Arquitetura. Opção 2. Serviço de cálculo do custo final das mercadorias

Há alguns meses, a maior parte dos pedidos de cálculo do custo final das mercadorias iam para um novo serviço, que, em princípio, funciona sem bases de dados, mas há algum tempo tudo era processado 100% por um serviço com Tarantool nos bastidores.

O banco de dados de serviço consiste em 4 mestres nos quais o sincronizador coleta dados, e cada um desses mestres de replicação distribui dados para réplicas somente leitura. Cada mestre possui aproximadamente 15 dessas réplicas.

Seja no primeiro ou no segundo esquema, se um DC estiver indisponível, a aplicação poderá receber dados no segundo.

Vale ressaltar que a replicação no Tarantool é bastante flexível e pode ser configurada em tempo de execução. Em outros sistemas, surgiram dificuldades. Por exemplo, alterar os parâmetros max_wal_senders e max_replication_slots no PostgreSQL requer a reinicialização do assistente, o que em alguns casos pode levar ao corte de conexões entre a aplicação e o SGBD.

Pesquise e encontre!

Por que não fizemos “como gente normal”, mas escolhemos um caminho atípico? Depende do que é considerado normal. Muitas pessoas geralmente criam um cluster do Mongo e o espalham por três DCs distribuídos geograficamente.

Naquela época, já tínhamos dois projetos Redis. O primeiro era um cache e o segundo era um armazenamento persistente para dados não muito críticos. Foi muito difícil para ele, em parte por culpa nossa. Às vezes, volumes bastante grandes estavam na chave e, de tempos em tempos, o site não estava bem. Usamos este sistema na versão master-slave. E houve muitos casos em que algo aconteceu com o mestre e a replicação falhou.

Ou seja, o Redis é bom para tarefas sem estado, não com estado. Em princípio, permitia resolver a maioria dos problemas, mas apenas se fossem soluções de valor-chave com um par de índices. Mas o Redis naquela época estava bastante triste com a persistência e a replicação. Além disso, houve reclamações sobre desempenho.

Pensamos em MySQL e PostgreSQL. Mas o primeiro, de alguma forma, não pegou entre nós, e o segundo é um produto bastante sofisticado em si, e seria inapropriado construir serviços simples sobre ele.
Tentamos RIAK, Cassandra e até um banco de dados gráfico. Todas essas são soluções bastante específicas que não eram adequadas para o papel de uma ferramenta universal geral para a criação de serviços.

No final das contas, decidimos pelo Tarantool.

Recorremos a ele quando estava na versão 1.6. Estávamos interessados ​​​​nele pela simbiose entre valor-chave e a funcionalidade de um banco de dados relacional. Existem índices secundários, transações e espaços, são como tabelas, mas não são simples, você pode armazenar diferentes números de colunas neles. Mas o recurso matador do Tarantool eram os índices secundários combinados com valor-chave e transacionalidade.

A receptiva comunidade de língua russa, pronta para ajudar no chat, também desempenhou um papel importante. Usamos isso ativamente e vivemos diretamente no chat. E não se esqueça da persistência decente, sem erros e erros óbvios. Se você olhar nossa história com o Tarantool, tivemos muitos problemas e falhas com replicação, mas nunca perdemos dados por culpa dele!

A implementação teve um início difícil

Naquela época, nossa principal pilha de desenvolvimento era o .NET, para o qual não havia conector para o Tarantool. Imediatamente começamos a fazer algo em Go. Funcionou bem com Lua também. O principal problema naquela época era com a depuração: no .NET tudo fica ótimo com isso, mas depois disso foi difícil mergulhar no mundo da Lua embarcada, quando você não tem depuração, exceto logs. Além disso, por algum motivo, a replicação desmoronava periodicamente, então tive que me aprofundar na estrutura do mecanismo Tarantool. O chat ajudou nisso e, em menor medida, a documentação; às vezes olhávamos o código. Naquela época, a documentação era mais ou menos.

Assim, ao longo de vários meses, consegui me concentrar e obter resultados decentes trabalhando com o Tarantool. Compilamos desenvolvimentos de referência em git que ajudaram na formação de novos microsserviços. Por exemplo, quando surgiu uma tarefa: criar outro microsserviço, o desenvolvedor olhou o código-fonte da solução de referência no repositório e não demorou mais de uma semana para criar um novo.

Foram momentos especiais. Convencionalmente, você poderia ir até o administrador na mesa ao lado e perguntar: “Dê-me uma máquina virtual”. Cerca de trinta minutos depois o carro já estava com você. Você se conectou, instalou tudo e o tráfego foi enviado para você.

Hoje isso não funcionará mais: você precisa adicionar monitoramento e log ao serviço, cobrir a funcionalidade com testes, solicitar uma máquina virtual ou entrega no Kuber, etc. Em geral, será melhor assim, embora demore mais e seja mais problemático.

Dividir para reinar. Qual é o problema com Lua?

Havia um sério dilema: algumas equipes não conseguiam implementar alterações de maneira confiável em um serviço com muita lógica em Lua. Muitas vezes isso era acompanhado pelo não funcionamento do serviço.

Ou seja, os desenvolvedores estão preparando algum tipo de mudança. Tarantool começa a fazer a migração, mas a réplica ainda está com o código antigo; Algum DDL ou qualquer outra coisa chega lá via replicação, e o código simplesmente desmorona porque não é levado em consideração. Como resultado, o procedimento de atualização para os administradores foi apresentado em folha A4: parar a replicação, atualizar isso, ativar a replicação, desligar aqui, atualizar ali. Pesadelo!

Como resultado, agora na maioria das vezes tentamos não fazer nada em Lua. Basta usar o iproto (um protocolo binário para interagir com o servidor) e pronto. Talvez seja falta de conhecimento dos desenvolvedores, mas desse ponto de vista o sistema é complexo.

Nem sempre seguimos cegamente esse roteiro. Hoje não temos preto e branco: ou tudo está em Lua, ou tudo está em Go. Já entendemos como podemos combiná-los para não termos problemas de migração mais tarde.

Onde está Tarantool agora?
O Tarantool é utilizado no serviço de cálculo do custo final da mercadoria levando em consideração cupons de desconto, também conhecido como “Promotor”. Como falei antes, ele agora está se aposentando: está sendo substituído por um novo serviço de catálogo com preços pré-calculados, mas há seis meses todos os cálculos eram feitos no Promotizer. Anteriormente, metade de sua lógica era escrita em Lua. Há dois anos, o serviço foi transformado em armazenamento e a lógica foi reescrita em Go, porque a mecânica dos descontos mudou um pouco e o serviço faltou desempenho.

Um dos serviços mais críticos é o perfil do usuário. Ou seja, todos os usuários do Wildberries estão armazenados no Tarantool, e são cerca de 50 milhões, um sistema fragmentado por ID de usuário, distribuído por vários DCs conectados aos serviços Go.
Segundo a RPS, o Promotor já foi líder, atingindo 6 mil solicitações. A certa altura, tínhamos 50-60 cópias. Já o líder em RPS são os perfis de usuário, cerca de 12 mil.Este serviço utiliza sharding customizado, dividido por intervalos de IDs de usuário. O serviço atende mais de 20 máquinas, mas são demais, pretendemos reduzir os recursos alocados, pois a capacidade de 4 a 5 máquinas é suficiente para isso.

O serviço de sessão é nosso primeiro serviço no vshard e no cartucho. Configurar o vshard e atualizar o Cartridge exigiu algum esforço de nossa parte, mas no final deu tudo certo.

O serviço de exibição de diversos banners no site e no aplicativo mobile foi um dos primeiros a ser lançado diretamente no Tarantool. Este serviço destaca-se pelo facto de ter entre 6 e 7 anos, ainda estar em funcionamento e nunca ter sido reiniciado. A replicação mestre-mestre foi usada. Nada nunca quebrou.

Há um exemplo de uso do Tarantool para funcionalidade de referência rápida em um sistema de warehouse para verificar rapidamente as informações em alguns casos. Tentamos usar o Redis para isso, mas os dados na memória ocupavam mais espaço que o Tarantool.

Os serviços de lista de espera, assinaturas de clientes, histórias da moda e bens diferidos também funcionam com a Tarantool. O último serviço na memória ocupa cerca de 120 GB. Este é o serviço mais completo dos acima.

Conclusão

Graças aos índices secundários combinados com valor-chave e transacionalidade, o Tarantool é adequado para arquiteturas baseadas em microsserviços. No entanto, encontramos dificuldades ao implementar alterações em serviços com muita lógica em Lua - os serviços frequentemente paravam de funcionar. Não conseguimos superar isso e, com o tempo, chegamos a diferentes combinações de Lua e Go: sabemos onde usar uma linguagem e onde usar outra.

O que mais ler sobre o assunto

Fonte: habr.com

Adicionar um comentário