Como deixar de preocuparse e comezar a vivir sen un monolito

Como deixar de preocuparse e comezar a vivir sen un monolito

A todos nos encantan as historias. Gústanos sentarnos ao redor do lume e falar das nosas vitorias pasadas, batallas ou simplemente da nosa experiencia laboral.

Hoxe é só un día así. E aínda que non esteas no lume agora mesmo, temos unha historia para ti. A historia de como comezamos a traballar co almacenamento en Tarantool.

Noutro tempo, a nosa empresa tiña un par de “monolitos” e un “teito” para todos, aos que pouco a pouco se foron achegando estes monolitos, limitando o voo da nosa empresa, o noso desenvolvemento. E había un claro entendemento: algún día golpearemos con forza este teito.

Agora é a ideoloxía imperante de separar todo e todos, dende os equipos ata a lóxica empresarial. Como resultado, temos, por exemplo, dous DC que son practicamente independentes a nivel de rede. E entón todo foi completamente diferente.

Hoxe, hai moitas ferramentas e ferramentas para facer cambios en forma de CI/CD, K8S, etc. No tempo "monolítico", non necesitabamos tantas palabras estranxeiras. Bastaba con simplemente corrixir o "almacenamento" na base de datos.

Pero o tempo avanzou e o número de solicitudes avanzou xunto con el, ás veces disparando RPS máis aló das nosas capacidades. Coa entrada dos países da CEI no mercado, a carga do procesador de bases de datos do primeiro monolito non caeu por debaixo do 90% e RPS mantívose no nivel de 2400. E estes non eran só pequenos selectores, senón consultas pesadas cun un montón de comprobacións e JOIN que poderían executarse case a metade dos datos no fondo dunha IO grande.

Cando as rebaixas do Black Friday comezaron a aparecer en escena -e Wildberries foi un dos primeiros que as fixo en Rusia- a situación volveuse completamente triste. Despois de todo, a carga nestes días aumenta tres veces.
Ai, estes "tempos monolíticos"! Estou seguro de que experimentaches algo semellante e aínda non podes entender como che pode pasar isto.

Que podes facer: a moda é inherente á tecnoloxía. Hai uns 5 anos, tivemos que repensar un destes mods en forma dun sitio existente no servidor .NET e MS SQL, que gardaba coidadosamente toda a lóxica do propio sitio. Gardeino con tanto coidado que serrar tal monolito resultou ser un pracer longo e nada fácil.
Unha pequena digresión.

En varios eventos digo: "se non viu un monolito, entón non creceu!" Estou interesado na túa opinión sobre este asunto, escríbena nos comentarios.

Un Son de Trono

Volvemos á nosa "fogueira". Para distribuír a carga de funcionalidades "monolíticas", decidimos dividir o sistema en microservizos baseados en tecnoloxías de código aberto. Porque, como mínimo, son máis baratos de escalar. E tiñamos 100% entendendo que teriamos que escalar (e moito). Despois de todo, xa naquel momento era posible entrar nos mercados dos países veciños e o número de rexistros, así como o número de pedidos, comezaron a crecer aínda máis.

Unha vez analizados os primeiros candidatos para a saída do monolito cara aos microservizos, decatámonos de que o 80% da escrita neles procede de sistemas de back office, e de lectura desde front office. En primeiro lugar, se trataba dun par de subsistemas importantes para nós: datos do usuario e un sistema para calcular o custo final dos bens en función da información sobre descontos e cupóns adicionais dos clientes.

Sangrado. Agora dá medo imaxinar, pero ademais dos subsistemas mencionados anteriormente, tamén se eliminaron do noso monólito catálogos de produtos, un carro da compra de usuarios, un sistema de busca de produtos, un sistema de filtrado para catálogos de produtos e varios tipos de sistemas de recomendación. Para o funcionamento de cada un deles, hai clases separadas de sistemas estreitamente adaptados, pero noutrora todos vivían nunha "casa".

Inmediatamente planeamos transferir datos sobre os nosos clientes ao sistema dividido. A eliminación da funcionalidade para calcular o custo final dos bens requiriu unha boa escalabilidade para a lectura, porque creaba a maior carga RPS e era a máis difícil de implementar para a base de datos (no proceso de cálculo están implicados moitos datos).

Como resultado, creamos un esquema que encaixa ben con Tarantool.

Daquela, para o funcionamento dos microservizos escolléronse esquemas de traballo con varios centros de datos en máquinas virtuais e de hardware. Como se mostra nas figuras, as opcións de replicación de Tarantool aplicáronse tanto en modo mestre-mestre como mestre-escravo.

Como deixar de preocuparse e comezar a vivir sen un monolito
Arquitectura. Opción 1. Servizo de usuario

Actualmente, hai 24 fragmentos, cada un dos cales ten 2 instancias (unha para cada DC), todas en modo mestre-mestre.

Na parte superior da base de datos hai aplicacións que acceden ás réplicas da base de datos. As aplicacións funcionan con Tarantool a través da nosa biblioteca personalizada, que implementa a interface do controlador Tarantool Go. Ela ve todas as réplicas e pode traballar co mestre para ler e escribir. Esencialmente, implementa o modelo de conxunto de réplicas, que engade lóxica para seleccionar réplicas, realizar reintentos, un interruptor automático e un límite de taxa.

Neste caso, é posible configurar a política de selección de réplicas no contexto de fragmentos. Por exemplo, roundrobin.

Como deixar de preocuparse e comezar a vivir sen un monolito
Arquitectura. Opción 2. Servizo de cálculo do custo final da mercadoría

Hai uns meses, a maioría das solicitudes de cálculo do custo final dos bens dirixíanse a un novo servizo que, en principio, funciona sen bases de datos, pero hai tempo que todo foi procesado ao 100% por un servizo con Tarantool baixo o capó.

A base de datos do servizo consta de 4 mestres nos que o sincronizador recolle datos e cada un destes mestres de replicación distribúe os datos a réplicas de só lectura. Cada mestre ten aproximadamente 15 réplicas deste tipo.

Tanto no primeiro como no segundo esquema, se un DC non está dispoñible, a aplicación pode recibir datos no segundo.

Paga a pena notar que a replicación en Tarantool é bastante flexible e pódese configurar en tempo de execución. Noutros sistemas xurdiron dificultades. Por exemplo, cambiar os parámetros max_wal_senters e max_replication_slots en PostgreSQL require un reinicio do asistente, o que nalgúns casos pode provocar a interrupción das conexións entre a aplicación e o DBMS.

Busca e atoparás!

Por que non o fixemos "como a xente normal", senón que escollemos un xeito atípico? Depende do que se considere normal. Moitos fan xeralmente un clúster a partir de Mongo e espállao en tres DC xeodistribuídos.

Daquela xa tiñamos dous proxectos de Redis. O primeiro era unha caché e o segundo era un almacenamento persistente para datos non demasiado críticos. Foi bastante difícil con el, en parte pola nosa culpa. Ás veces había volumes bastante grandes na clave, e de cando en vez o sitio estaba enfermo. Usamos este sistema na versión mestre-escravo. E houbo moitos casos nos que algo lle pasou ao mestre e a réplica fallou.

É dicir, Redis é bo para tarefas sen estado, non para as con estado. En principio, permitía resolver a maioría dos problemas, pero só se eran solucións clave-valor cun par de índices. Pero Redis naquel momento estaba bastante triste coa persistencia e a replicación. Ademais, houbo queixas sobre o rendemento.

Pensamos en MySQL e PostgreSQL. Pero o primeiro dalgunha maneira non nos conseguiu, e o segundo é un produto bastante sofisticado en si mesmo, e sería inapropiado construír servizos sinxelos nel.
Probamos RIAK, Cassandra, incluso unha base de datos gráfica. Todas estas son solucións bastante nichos que non eran adecuadas para o papel de ferramenta universal xeral para a creación de servizos.

Ao final decidimos Tarantool.

Recorremos a el cando estaba na versión 1.6. Interesábanos a simbiose de clave-valor e a funcionalidade dunha base de datos relacional. Hai índices secundarios, transaccións e espazos, son como táboas, pero non simples, podes almacenar nelas diferentes números de columnas. Pero a característica principal de Tarantool foron os índices secundarios combinados con clave-valor e transaccionalidade.

A comunidade de fala rusa sensible, lista para axudar no chat, tamén xogou un papel. Usamos isto activamente e vivimos directamente no chat. E non te esquezas de persistentes decentes sen erros e erros evidentes. Se miras a nosa historia con Tarantool, tivemos moita dor e fallos coa replicación, pero nunca perdemos datos debido á súa culpa.

A implantación tivo un comezo difícil

Nese momento, a nosa pila de desenvolvemento principal era .NET, ao que non había ningún conector para Tarantool. Inmediatamente comezamos a facer algo en Go. Tamén funcionou ben con Lua. O principal problema daquela era coa depuración: en .NET todo está moi ben con isto, pero despois diso foi difícil mergullarse no mundo do Lua incrustado, cando non tes depuración excepto rexistros. Ademais, por algún motivo a replicación caía periodicamente, polo que tiven que afondar na estrutura do motor Tarantool. O chat axudou con isto e, en menor medida, coa documentación; ás veces mirabamos o código. Daquela, a documentación era así.

Entón, ao longo de varios meses, conseguín darme a cabeza e obter resultados decentes ao traballar con Tarantool. Compilamos desenvolvementos de referencia en git que axudaron á formación de novos microservizos. Por exemplo, cando xurdiu unha tarefa: para crear outro microservizo, o programador mirou o código fonte da solución de referencia no repositorio e non tardou máis dunha semana en crear un novo.

Eran tempos especiais. Convencionalmente, entón podes acudir ao administrador da mesa seguinte e preguntarlle: "Dáme unha máquina virtual". Uns trinta minutos despois o coche xa estaba contigo. Conectácheste, instalaches todo e enviáchesche tráfico.

Hoxe isto xa non funcionará: cómpre engadir seguimento e rexistro ao servizo, cubrir a funcionalidade con probas, pedir unha máquina virtual ou entregar a Kuber, etc. En xeral, será mellor deste xeito, aínda que levará máis tempo e será máis problemático.

Divide e goberna. Cal é o trato con Lua?

Houbo un serio dilema: algúns equipos non foron capaces de implementar de forma fiable cambios nun servizo con moita lóxica en Lua. Isto a miúdo ía acompañado de que o servizo non funcionaba.

É dicir, os desenvolvedores están a preparar algún tipo de cambio. Tarantool comeza a facer a migración, pero a réplica aínda está co código antigo; Algún DDL ou outra cousa chega alí a través da replicación, e o código simplemente desfaise porque non se ten en conta. Como resultado, o procedemento de actualización para os administradores presentouse nunha folla A4: deter a replicación, actualizar isto, activar a replicación, desactivar aquí, actualizar alí. Pesadelo!

Como resultado, agora a maioría das veces tentamos non facer nada en Lua. Simplemente use iproto (un protocolo binario para interactuar co servidor), e xa está. Quizais isto sexa unha falta de coñecemento entre os desenvolvedores, pero desde este punto de vista o sistema é complexo.

Non sempre seguimos cegamente este guión. Hoxe non temos branco e negro: ou todo está en Lua, ou todo está en Go. Xa entendemos como podemos combinalos para que despois non acabemos con problemas migratorios.

Onde está Tarantool agora?
Tarantool úsase no servizo para calcular o custo final dos bens tendo en conta os cupóns de desconto, tamén coñecidos como "Promotor". Como dixen antes, agora xa se xubila: substitúese por un novo servizo de catálogo con prezos precalculados, pero hai seis meses todos os cálculos fixéronse en Promotizer. Anteriormente, a metade da súa lóxica estaba escrita en Lua. Hai dous anos, o servizo converteuse nun almacén, e a lóxica foi reescrita en Go, porque a mecánica dos descontos cambiara un pouco e o servizo carecía de rendemento.

Un dos servizos máis críticos é o perfil de usuario. É dicir, todos os usuarios de Wildberries están almacenados en Tarantool, e hai uns 50 millóns deles.Un sistema dividido por ID de usuario, distribuído en varios DC conectados aos servizos Go.
Segundo RPS, Promoter foi unha vez o líder, chegando a 6 mil solicitudes. Nun momento dado tivemos 50-60 exemplares. Agora o líder en RPS son os perfís de usuarios, uns 12 mil. Este servizo usa fragmentos personalizados, divididos por intervalos de ID de usuario. O servizo dá servizo a máis de 20 máquinas, pero son demasiadas; pensamos reducir os recursos asignados, porque a capacidade de 4-5 máquinas é suficiente para iso.

O servizo de sesión é o noso primeiro servizo en vshard e Cartridge. Configurar vshard e actualizar Cartridge requiriunos algún esforzo, pero ao final todo funcionou.

O servizo de exhibición de diferentes banners na web e na aplicación móbil foi un dos primeiros en lanzarse directamente en Tarantool. Este servizo destaca polo feito de que ten 6-7 anos de antigüidade, aínda está en funcionamento e nunca se reiniciou. Utilizouse a replicación mestre-mestre. Nunca se rompeu nada.

Hai un exemplo de uso de Tarantool para a funcionalidade de referencia rápida nun sistema de almacén para comprobar rapidamente a información nalgúns casos. Tentamos usar Redis para iso, pero os datos da memoria ocupaban máis espazo que Tarantool.

Tamén funcionan con Tarantool os servizos dunha lista de espera, subscricións de clientes, historias de moda actualmente e produtos diferidos. O último servizo na memoria ocupa uns 120 GB. Este é o servizo máis completo dos anteriores.

Conclusión

Grazas aos índices secundarios combinados con clave-valor e transaccionalidade, Tarantool é moi axeitado para arquitecturas baseadas en microservizos. Non obstante, atopamos dificultades ao implementar cambios nos servizos con moita lóxica en Lua: os servizos moitas veces deixaron de funcionar. Non puidemos superalo, e co paso do tempo chegamos a diferentes combinacións de Lua e Go: sabemos onde usar unha lingua e onde usar outra.

Que máis ler sobre o tema

Fonte: www.habr.com

Engadir un comentario