Hoe je kunt stoppen met piekeren en kunt gaan leven zonder monoliet

Hoe je kunt stoppen met piekeren en kunt gaan leven zonder monoliet

We houden allemaal van verhalen. We zitten graag rond het vuur en praten over onze overwinningen, veldslagen of gewoonweg onze werkervaring.

Vandaag is zo’n dag. En ook als je nu niet bij de brand staat, hebben wij een verhaal voor je. Het verhaal van hoe we begonnen te werken met opslag op Tarantool.

Er was eens een paar ‘monolieten’ en één ‘plafond’ voor iedereen, waar deze monolieten langzaam maar zeker naartoe naderden, waardoor de vlucht van ons bedrijf, onze ontwikkeling, werd beperkt. En er was een duidelijk inzicht: op een dag zullen we dit plafond hard bereiken.

Het is nu de heersende ideologie van het scheiden van alles en iedereen, van apparatuur tot bedrijfslogica. Hierdoor hebben we bijvoorbeeld twee DC’s die op netwerkniveau vrijwel onafhankelijk zijn. En toen was alles compleet anders.

Tegenwoordig zijn er veel tools en tools om wijzigingen aan te brengen in de vorm van CI/CD, K8S, enz. In de ‘monolithische’ tijd hadden we niet zoveel buitenlandse woorden nodig. Het was voldoende om simpelweg de “opslag” in de database te corrigeren.

Maar de tijd schoof vooruit en het aantal verzoeken ging mee, waardoor RPS soms buiten onze mogelijkheden schoot. Met de komst van de GOS-landen op de markt daalde de belasting van de databaseprocessor van de eerste monoliet niet onder de 90% en bleef de RPS op het niveau van 2400. En dit waren niet alleen kleine selectors, maar zware zoekopdrachten met een een stel controles en JOIN's die bijna de helft van de gegevens zouden kunnen uitvoeren tegen de achtergrond van grote IO.

Toen volwaardige Black Friday-verkopen op het toneel verschenen - en Wildberries was een van de eersten die ze in Rusland vasthielden - werd de situatie volkomen triest. De belasting op zulke dagen neemt immers drie keer toe.
O, deze ‘monolithische tijden’! Ik ben er zeker van dat je iets soortgelijks hebt meegemaakt, en je kunt nog steeds niet begrijpen hoe dit je kan overkomen.

Wat kun je doen - mode is inherent aan technologie. Ongeveer 5 jaar geleden moesten we een van deze mods heroverwegen in de vorm van een bestaande site op .NET en MS SQL-server, die zorgvuldig alle logica van de site zelf opsloeg. Ik bewaarde het zo zorgvuldig dat het zagen van zo'n monoliet een lang en helemaal niet gemakkelijk plezier bleek te zijn.
Een kleine uitweiding.

Bij verschillende evenementen zeg ik: “als je geen monoliet zag, dan ben je niet gegroeid!” Ik ben geïnteresseerd in uw mening over deze kwestie, schrijf deze in de reacties.

Een geluid van donder

Laten we terugkeren naar ons "vreugdevuur". Om de last van de “monolithische” functionaliteit te verdelen, hebben we besloten het systeem op te delen in microservices op basis van opensource-technologieën. Omdat ze op zijn minst goedkoper zijn om te schalen. En we hadden 100% begrip dat we zouden moeten opschalen (en veel). Het was immers al in die tijd mogelijk om de markten van de buurlanden te betreden en het aantal registraties, evenals het aantal bestellingen, begon nog sterker te groeien.

Nadat we de eerste kandidaten voor het vertrek van de monoliet naar microservices hadden geanalyseerd, realiseerden we ons dat 80% van het schrijven daarin afkomstig is van backofficesystemen en van het frontoffice. Allereerst betrof dit voor ons een aantal belangrijke subsystemen: gebruikersgegevens en een systeem voor het berekenen van de uiteindelijke kosten van goederen op basis van informatie over extra klantenkortingen en kortingsbonnen.

Ingesprongen. Nu is het eng om je voor te stellen, maar naast de bovengenoemde subsystemen zijn ook productcatalogi, een gebruikerswinkelwagentje, een productzoeksysteem, een filtersysteem voor productcatalogi en verschillende soorten aanbevelingssystemen uit onze monoliet verwijderd. Voor de werking van elk van hen zijn er afzonderlijke klassen van nauw op maat gemaakte systemen, maar ooit woonden ze allemaal in één ‘huis’.

We waren onmiddellijk van plan om gegevens over onze klanten over te dragen naar het sharded-systeem. Het verwijderen van de functionaliteit voor het berekenen van de uiteindelijke kosten van goederen vereiste een goede schaalbaarheid voor het lezen, omdat dit de grootste RPS-belasting veroorzaakte en het moeilijkst te implementeren was voor de database (er zijn veel gegevens betrokken bij het berekeningsproces).

Hierdoor kwamen we tot een schema dat goed bij Tarantool past.

Destijds werd voor de werking van microservices gekozen voor schema's voor het werken met verschillende datacenters op virtuele en hardwaremachines. Zoals te zien is in de figuren, werden de replicatieopties van Tarantool toegepast in zowel de master-master- als de master-slave-modus.

Hoe je kunt stoppen met piekeren en kunt gaan leven zonder monoliet
Architectuur. Optie 1. Gebruikersservice

Op dit moment zijn er 24 shards, die elk twee exemplaren hebben (één voor elke DC), allemaal in master-master-modus.

Bovenop de database bevinden zich toepassingen die toegang hebben tot databasereplica's. Applicaties werken met Tarantool via onze aangepaste bibliotheek, die de Tarantool Go-stuurprogramma-interface implementeert. Ze ziet alle replica's en kan samen met de meester lezen en schrijven. In wezen implementeert het het replicasetmodel, dat logica toevoegt voor het selecteren van replica's, het uitvoeren van nieuwe pogingen, een stroomonderbreker en een snelheidslimiet.

In dit geval is het mogelijk om het replicaselectiebeleid te configureren in de context van shards. Roundrobin bijvoorbeeld.

Hoe je kunt stoppen met piekeren en kunt gaan leven zonder monoliet
Architectuur. Optie 2. Dienst voor het berekenen van de uiteindelijke kosten van goederen

Een paar maanden geleden gingen de meeste verzoeken voor het berekenen van de uiteindelijke kosten van goederen naar een nieuwe dienst, die in principe zonder databases werkt, maar een tijdje geleden werd alles 100% verwerkt door een dienst met Tarantool onder de motorkap.

De servicedatabase bestaat uit vier masters waarin de synchronisator gegevens verzamelt, en elk van deze replicatiemasters distribueert gegevens naar alleen-lezen replica's. Elke meester heeft ongeveer 4 van dergelijke replica's.

Als in het eerste of in het tweede schema één DC niet beschikbaar is, kan de applicatie gegevens ontvangen in het tweede.

Het is vermeldenswaard dat replicatie in Tarantool vrij flexibel is en tijdens runtime kan worden geconfigureerd. In andere systemen deden zich moeilijkheden voor. Het wijzigen van de parameters max_wal_senders en max_replication_slots in PostgreSQL vereist bijvoorbeeld een herstart van de wizard, wat in sommige gevallen kan leiden tot het verbreken van verbindingen tussen de applicatie en het DBMS.

Zoek en vind!

Waarom deden we het niet ‘zoals normale mensen’, maar kozen we voor een atypische manier? Het hangt ervan af wat als normaal wordt beschouwd. Veel mensen maken over het algemeen een cluster van Mongo en verspreiden deze over drie geografisch gedistribueerde DC's.

We hadden toen al twee Redis-projecten. De eerste was een cache en de tweede was een permanente opslag voor niet al te kritische gegevens. Het was best lastig met hem, mede door onze schuld. Soms zaten er behoorlijk grote volumes in de sleutel, en van tijd tot tijd werd de site onwel. Wij hebben dit systeem gebruikt in de master-slave-versie. En er waren veel gevallen waarin er iets met de master gebeurde en de replicatie mislukte.

Dat wil zeggen: Redis is goed voor staatloze taken, niet voor staatstaken. In principe maakte het het mogelijk de meeste problemen op te lossen, maar alleen als het sleutel-waardeoplossingen waren met een paar indexen. Maar Redis was in die tijd behoorlijk verdrietig over volharding en replicatie. Daarnaast waren er klachten over de prestaties.

We dachten aan MySQL en PostgreSQL. Maar de eerste sloeg op de een of andere manier niet bij ons aan, en de tweede is op zichzelf een nogal geavanceerd product, en het zou ongepast zijn om er eenvoudige diensten op te bouwen.
We hebben RIAK, Cassandra en zelfs een grafiekendatabase geprobeerd. Dit zijn allemaal tamelijk nicheoplossingen die niet geschikt waren voor de rol van een algemeen universeel instrument voor het creëren van diensten.

Uiteindelijk hebben we gekozen voor Tarantool.

We zijn er naar toe gegaan toen het in versie 1.6 was. We waren erin geïnteresseerd vanwege de symbiose van sleutelwaarde en de functionaliteit van een relationele database. Er zijn secundaire indexen, transacties en spaties, dit lijken op tabellen, maar niet eenvoudig, je kunt er verschillende aantallen kolommen in opslaan. Maar het killer-kenmerk van Tarantool waren de secundaire indexen in combinatie met sleutelwaarde en transactionaliteit.

De responsieve Russischsprekende gemeenschap, klaar om te helpen tijdens de chat, speelde ook een rol. Wij hebben hier actief gebruik van gemaakt en leven direct in de chat. En vergeet fatsoenlijke persistentie zonder duidelijke blunders en fouten niet. Als je naar onze geschiedenis met Tarantool kijkt, hebben we veel pijn en mislukkingen gehad met replicatie, maar we zijn nooit gegevens kwijtgeraakt vanwege de fout ervan!

De implementatie kende een moeizame start

Op dat moment was onze belangrijkste ontwikkelingsstack .NET, waarvoor geen connector voor Tarantool bestond. We zijn meteen iets gaan doen in Go. Bij Lua werkte het ook goed. Het grootste probleem in die tijd was het debuggen: in .NET is alles geweldig, maar daarna was het moeilijk om in de wereld van embedded Lua te duiken, als je geen debugging hebt behalve logs. Bovendien viel de replicatie om de een of andere reden periodiek uit elkaar, dus moest ik me verdiepen in de structuur van de Tarantool-engine. De chat hielp hierbij, en in mindere mate de documentatie; soms keken we naar de code. Destijds was de documentatie matig.

Dus in de loop van een aantal maanden slaagde ik erin om mijn hoofd erbij te houden en behoorlijke resultaten te behalen door met Tarantool te werken. We hebben referentie-ontwikkelingen in git verzameld die hebben geholpen bij de vorming van nieuwe microservices. Toen zich bijvoorbeeld een taak voordeed: om nog een microservice te maken, keek de ontwikkelaar naar de broncode van de referentieoplossing in de repository en het duurde niet meer dan een week om een ​​nieuwe te maken.

Het waren bijzondere tijden. Normaal gesproken zou u dan naar de beheerder aan de volgende tafel kunnen gaan en vragen: "Geef mij een virtuele machine." Ongeveer dertig minuten later was de auto al bij je. Je hebt zelf verbinding gemaakt, alles geïnstalleerd en het verkeer werd naar je gestuurd.

Tegenwoordig werkt dit niet meer: ​​je moet monitoring en logging aan de dienst toevoegen, de functionaliteit afdekken met tests, een virtuele machine bestellen of aan Kuber leveren, etc. Over het algemeen zal het op deze manier beter zijn, hoewel het langer zal duren en lastiger zal zijn.

Verdeel en heers. Hoe is het met Lua?

Er was sprake van een serieus dilemma: sommige teams slaagden er niet in om op betrouwbare wijze wijzigingen door te voeren in een dienst met veel logica in Lua. Dit ging vaak gepaard met het feit dat de service niet werkte.

Dat wil zeggen, de ontwikkelaars bereiden een soort verandering voor. Tarantool begint met de migratie, maar de replica bevat nog steeds de oude code; Er komt wat DDL of iets anders binnen via replicatie, en de code valt eenvoudigweg uit elkaar omdat er geen rekening mee wordt gehouden. Als gevolg hiervan werd de updateprocedure voor de beheerders op een A4-tje vastgelegd: replicatie stoppen, deze updaten, replicatie aanzetten, hier uitschakelen, daar updaten. Nachtmerrie!

Als gevolg hiervan proberen we nu meestal niets te doen in Lua. Gebruik gewoon iproto (een binair protocol voor interactie met de server), en dat is alles. Misschien is dit een gebrek aan kennis bij de ontwikkelaars, maar vanuit dit oogpunt is het systeem complex.

We volgen dit script niet altijd blindelings. Tegenwoordig hebben we geen zwart-wit: alles staat in Lua, of alles staat in Go. We begrijpen al hoe we ze kunnen combineren, zodat we later niet met migratieproblemen komen te zitten.

Waar is Tarantool nu?
Tarantool wordt in de service gebruikt voor het berekenen van de uiteindelijke kosten van goederen, rekening houdend met kortingsbonnen, ook wel “Promoter” genoemd. Zoals ik al eerder zei, gaat hij nu met pensioen: hij wordt vervangen door een nieuwe catalogusdienst met vooraf berekende prijzen, maar een half jaar geleden werden alle berekeningen in Promotizer gemaakt. Voorheen werd de helft van de logica in Lua geschreven. Twee jaar geleden werd de dienst omgevormd tot een opslagfaciliteit en werd de logica herschreven in Go, omdat de werking van de kortingen een beetje was veranderd en de dienst niet goed presteerde.

Een van de meest kritische services is het gebruikersprofiel. Dat wil zeggen dat alle Wildberries-gebruikers zijn opgeslagen in Tarantool, en dat zijn er ongeveer 50 miljoen. Een systeem verdeeld op basis van gebruikers-ID, verdeeld over verschillende DC's die zijn verbonden met Go-services.
Volgens RPS was Promoter ooit de leider en bereikte hij 6 verzoeken. Op een gegeven moment hadden we 50-60 exemplaren. Nu zijn de leider in RPS gebruikersprofielen, ongeveer 12 duizend. Deze service maakt gebruik van aangepaste sharding, gedeeld door reeksen gebruikers-ID's. De service bedient meer dan 20 machines, maar dit is te veel; we zijn van plan de toegewezen middelen te verminderen, omdat de capaciteit van 4-5 machines daarvoor voldoende is.

Sessieservice is onze eerste service op vshard en Cartridge. Het opzetten van vshard en het updaten van Cartridge vergde wat inspanning van ons, maar uiteindelijk is alles gelukt.

De dienst voor het weergeven van verschillende banners op de website en in de mobiele applicatie was een van de eerste die rechtstreeks op Tarantool werd uitgebracht. Deze service valt op door het feit dat deze 6-7 jaar oud is, nog steeds in gebruik is en nooit opnieuw is opgestart. Er werd gebruik gemaakt van master-masterreplicatie. Er is nooit iets kapot gegaan.

Er is een voorbeeld van het gebruik van Tarantool voor snelle referentiefunctionaliteit in een magazijnsysteem om in sommige gevallen snel informatie te dubbelchecken. We hebben geprobeerd Redis hiervoor te gebruiken, maar de gegevens in het geheugen namen meer ruimte in beslag dan Tarantool.

De diensten van een wachtlijst, klantabonnementen, momenteel modieuze verhalen en uitgestelde goederen werken ook met Tarantool. De laatste service in het geheugen neemt ongeveer 120 GB in beslag. Dit is de meest uitgebreide service van bovenstaande.

Conclusie

Dankzij secundaire indexen gecombineerd met sleutelwaarde en transactionaliteit is Tarantool zeer geschikt voor op microservices gebaseerde architecturen. We ondervonden echter problemen bij het doorvoeren van wijzigingen in services met veel logica in Lua: de services werkten vaak niet meer. We konden dit niet overwinnen en in de loop van de tijd kwamen we tot verschillende combinaties van Lua en Go: we weten waar we de ene taal moeten gebruiken en waar we de andere moeten gebruiken.

Wat nog meer te lezen over het onderwerp

Bron: www.habr.com

Voeg een reactie