Hur man slutar oroa sig och börjar leva utan en monolit

Hur man slutar oroa sig och börjar leva utan en monolit

Vi älskar alla berättelser. Vi gillar att sitta runt elden och prata om våra tidigare segrar, strider eller helt enkelt vår arbetslivserfarenhet.

Idag är bara en sådan dag. Och även om du inte är vid elden just nu, har vi en historia för dig. Berättelsen om hur vi började arbeta med lagring på Tarantool.

En gång i tiden hade vårt företag ett par "monoliter" och ett "tak" för alla, som dessa monoliter sakta men säkert närmade sig, vilket begränsade vårt företags flykt, vår utveckling. Och det fanns en klar förståelse: en dag kommer vi att slå hårt i det här taket.

Det är nu den rådande ideologin att separera allt och alla, från utrustning till affärslogik. Som ett resultat har vi till exempel två DC:er som är praktiskt taget oberoende på nätverksnivå. Och sedan var allt helt annorlunda.

Idag finns det en hel del verktyg och verktyg för att göra förändringar i form av CI/CD, K8S osv. På den "monolitiska" tiden behövde vi inte så många främmande ord. Det räckte med att helt enkelt korrigera "lagringen" i databasen.

Men tiden gick framåt, och antalet förfrågningar gick framåt tillsammans med det, ibland sköt RPS bortom våra möjligheter. Med CIS-ländernas inträde på marknaden föll inte belastningen på databasprocessorn för den första monoliten under 90%, och RPS förblev på nivån 2400. Och dessa var inte bara små väljare, utan rejäla frågor med en en massa kontroller och JOINs som kan köras nästan för hälften av datan mot bakgrund av stora IO.

När fullfjädrade Black Friday-försäljningar började dyka upp på scenen – och Wildberries var en av de första som höll dem i Ryssland – blev situationen helt sorglig. Trots allt ökar belastningen på sådana dagar tre gånger.
Åh, dessa "monolitiska tider"! Jag är säker på att du har upplevt något liknande, och du kan fortfarande inte förstå hur detta kunde hända dig.

Vad kan du göra - mode är inneboende i tekniken. För ungefär 5 år sedan var vi tvungna att ompröva en av dessa mods i form av en befintlig sajt på .NET och MS SQL-server, som noggrant lagrade all logik för själva sajten. Jag höll det så noggrant att det att såga en sådan monolit visade sig vara ett långt och inte alls lätt nöje.
En liten utvikning.

Vid olika evenemang säger jag: "om du inte såg en monolit, så växte du inte!" Jag är intresserad av din åsikt i denna fråga, skriv den i kommentarerna.

Ett ljud av åska

Låt oss återvända till vår "brasa". För att fördela belastningen av "monolitisk" funktionalitet bestämde vi oss för att dela upp systemet i mikrotjänster baserade på öppen källkodsteknologi. Eftersom de åtminstone är billigare att skala. Och vi hade 100% förståelse för att vi skulle behöva skala (och mycket). När allt kommer omkring var det redan vid den tiden möjligt att komma in på marknaderna i grannländerna, och antalet registreringar, såväl som antalet beställningar, började växa ännu starkare.

Efter att ha analyserat de första kandidaterna för avgång från monoliten till mikrotjänster insåg vi att 80 % av skrivningen i dem kommer från backoffice-system och läsning från front office. Först och främst gällde det ett par viktiga delsystem för oss – användardata och ett system för att beräkna slutkostnaden för varor utifrån information om ytterligare kundrabatter och kuponger.

Indragen. Nu är det läskigt att föreställa sig, men förutom de ovan nämnda undersystemen togs även produktkataloger, en kundvagn, ett produktsökningssystem, ett filtreringssystem för produktkataloger och olika typer av rekommendationssystem bort från vår monolit. För driften av var och en av dem finns det separata klasser av snävt skräddarsydda system, men en gång i tiden bodde de alla i ett "hus".

Vi planerade omedelbart att överföra data om våra kunder till det fragmenterade systemet. Borttagandet av funktionalitet för att beräkna slutkostnaden för varor krävde god skalbarhet för läsning, eftersom det skapade den största RPS-belastningen och var den svåraste att implementera för databasen (mycket data är inblandat i beräkningsprocessen).

Som ett resultat kom vi fram till ett schema som passar bra med Tarantool.

Vid den tiden, för driften av mikrotjänster, valdes scheman för att arbeta med flera datacenter på virtuella och hårdvarumaskiner. Som visas i figurerna användes Tarantool-replikeringsalternativ i både master-master- och master-slave-lägen.

Hur man slutar oroa sig och börjar leva utan en monolit
Arkitektur. Alternativ 1. Användartjänst

För närvarande finns det 24 skärvor, som var och en har 2 instanser (en för varje DC), alla i master-master-läge.

Ovanpå databasen finns applikationer som får åtkomst till databasrepliker. Applikationer fungerar med Tarantool genom vårt anpassade bibliotek, som implementerar Tarantool Go-drivrutinsgränssnittet. Hon ser alla replikerna och kan arbeta med mästaren för att läsa och skriva. I huvudsak implementerar den replikuppsättningsmodellen, som lägger till logik för att välja repliker, utföra omförsök, en strömbrytare och en hastighetsgräns.

I det här fallet är det möjligt att konfigurera replikvalspolicyn i sammanhanget av skärvor. Till exempel roundrobin.

Hur man slutar oroa sig och börjar leva utan en monolit
Arkitektur. Alternativ 2. Tjänst för beräkning av den slutliga kostnaden för varor

För några månader sedan gick de flesta förfrågningarna om att beräkna den slutliga kostnaden för varor till en ny tjänst, som i princip fungerar utan databaser, men för en tid sedan behandlades allt till 100% av en tjänst med Tarantool under huven.

Tjänstedatabasen består av 4 masters i vilka synkroniseraren samlar in data, och var och en av dessa replikeringsmaster distribuerar data till skrivskyddade repliker. Varje master har cirka 15 sådana repliker.

Antingen i det första eller i det andra schemat, om en DC är otillgänglig, kan applikationen ta emot data i den andra.

Det är värt att notera att replikering i Tarantool är ganska flexibel och kan konfigureras under körning. I andra system uppstod svårigheter. Att till exempel ändra parametrarna max_wal_senders och max_replication_slots i PostgreSQL kräver en omstart av guiden, vilket i vissa fall kan leda till att anslutningarna mellan applikationen och DBMS bryts.

Sök och hitta!

Varför gjorde vi det inte "som vanliga människor", utan valde ett atypiskt sätt? Det beror på vad som anses normalt. Många människor gör i allmänhet ett kluster från Mongo och sprider det över tre geodistribuerade DC:er.

Då hade vi redan två Redis-projekt. Den första var en cache och den andra var en beständig lagring för inte alltför kritiska data. Det var ganska svårt med honom, delvis på grund av vårt fel. Ibland låg ganska stora volymer i nyckeln, och då och då blev platsen dålig. Vi använde detta system i master-slave-versionen. Och det fanns många fall där något hände med befälhavaren och replikeringen gick sönder.

Det vill säga Redis är bra för statslösa uppgifter, inte tillståndslösa. I princip tillät det att lösa de flesta problem, men bara om de var nyckel-värde lösningar med ett par index. Men Redis vid den tiden var ganska ledsen med uthållighet och replikering. Dessutom kom klagomål på prestanda.

Vi funderade på MySQL och PostgreSQL. Men den första fick på något sätt inte tag i oss, och den andra är en ganska sofistikerad produkt i sig, och det skulle vara olämpligt att bygga enkla tjänster på den.
Vi provade RIAK, Cassandra, till och med en grafdatabas. Dessa är alla ganska nischade lösningar som inte var lämpliga för rollen som ett allmänt universellt verktyg för att skapa tjänster.

Till slut bosatte vi oss på Tarantool.

Vi vände oss till det när det var i version 1.6. Vi var intresserade av det av symbiosen mellan nyckel-värde och funktionaliteten hos en relationsdatabas. Det finns sekundära index, transaktioner och mellanslag, dessa är som tabeller, men inte enkelt, du kan lagra olika antal kolumner i dem. Men den mördande egenskapen hos Tarantool var sekundära index kombinerat med nyckel-värde och transaktionalitet.

Det lyhörda rysktalande samhället, redo att hjälpa till i chatten, spelade också en roll. Vi använde detta aktivt och lever direkt i chatten. Och glöm inte anständigt ihållande utan uppenbara misstag och misstag. Om du tittar på vår historia med Tarantool, hade vi mycket smärta och misslyckanden med replikering, men vi förlorade aldrig data på grund av dess fel!

Implementeringen fick en tuff start

På den tiden var vår huvudsakliga utvecklingsstack .NET, som det inte fanns någon anslutning till för Tarantool. Vi började genast göra något i Go. Det fungerade bra med Lua också. Det största problemet på den tiden var med felsökning: i .NET är allt bra med detta, men efter det var det svårt att kasta sig in i världen av inbäddade Lua, när du inte har någon felsökning förutom loggar. Dessutom föll replikeringen av någon anledning med jämna mellanrum, så jag var tvungen att fördjupa mig i strukturen för Tarantool-motorn. Chatten hjälpte till med detta, och i mindre utsträckning, dokumentationen, ibland tittade vi på koden. På den tiden var dokumentationen sisådär.

Så under loppet av flera månader lyckades jag ta mig runt och få anständiga resultat av att arbeta med Tarantool. Vi sammanställde referensutvecklingar inom git som hjälpte till med bildandet av nya mikrotjänster. Till exempel, när en uppgift uppstod: att skapa en annan mikrotjänst tittade utvecklaren på källkoden för referenslösningen i förvaret, och det tog inte mer än en vecka att skapa en ny.

Det var speciella tider. Vanligtvis kan du gå fram till administratören vid nästa bord och fråga: "Ge mig en virtuell maskin." Cirka trettio minuter senare var bilen redan med dig. Du kopplade upp dig själv, installerade allt och trafik skickades till dig.

Idag kommer detta inte längre att fungera: du behöver lägga till övervakning och loggning till tjänsten, täcka funktionaliteten med tester, beställa en virtuell maskin eller leverans till Kuber, etc. I allmänhet kommer det att bli bättre på det här sättet, även om det tar längre tid och blir mer besvärligt.

Söndra och härska. Vad är grejen med Lua?

Det fanns ett allvarligt dilemma: vissa team kunde inte på ett tillförlitligt sätt implementera ändringar i en tjänst med mycket logik i Lua. Detta åtföljdes ofta av att tjänsten inte fungerade.

Det vill säga att utvecklarna förbereder någon form av förändring. Tarantool börjar göra migreringen, men repliken är fortfarande med den gamla koden; Någon DDL eller något annat kommer dit via replikering, och koden faller helt enkelt sönder för att den inte tas med i beräkningen. Som ett resultat lades uppdateringsproceduren för administratörerna ut på A4-ark: stoppa replikering, uppdatera detta, slå på replikering, stäng av här, uppdatera där. Mardröm!

Som ett resultat försöker vi nu oftast göra ingenting i Lua. Använd bara iproto (ett binärt protokoll för att interagera med servern), och det är allt. Kanske är detta en brist på kunskap bland utvecklarna, men ur denna synvinkel är systemet komplext.

Vi följer inte alltid blint det här manuset. Idag har vi inte svart och vitt: antingen är allt i Lua, eller så är allt i Go. Vi förstår redan hur vi kan kombinera dem så att vi inte hamnar i migreringsproblem senare.

Var är Tarantool nu?
Tarantool används i tjänsten för att beräkna den slutliga kostnaden för varor med hänsyn till rabattkuponger, även känd som "Promoter". Som jag sa tidigare går han nu i pension: han ersätts av en ny katalogtjänst med föruträknade priser, men för ett halvår sedan gjordes alla beräkningar i Promotizer. Tidigare var hälften av dess logik skriven i Lua. För två år sedan gjordes tjänsten om till en lagringsanläggning, och logiken skrevs om i Go, eftersom mekaniken med rabatter hade förändrats lite och tjänsten saknade prestanda.

En av de mest kritiska tjänsterna är användarprofilen. Det vill säga att alla Wildberries-användare är lagrade i Tarantool, och det finns cirka 50 miljoner av dem. Ett system som delas av användar-ID, fördelat på flera DC:er anslutna till Go-tjänster.
Enligt RPS var Promoter en gång ledaren och nådde 6 tusen förfrågningar. Vid ett tillfälle hade vi 50-60 exemplar. Nu är ledaren inom RPS användarprofiler, cirka 12 20. Den här tjänsten använder anpassad sönderdelning, dividerat med intervall av användar-ID. Tjänsten betjänar mer än 4 maskiner, men detta är för många, vi planerar att minska de tilldelade resurserna, eftersom kapaciteten på 5-XNUMX maskiner räcker för det.

Sessionstjänst är vår första tjänst på vshard och Cartridge. Att ställa in vshard och uppdatera Cartridge krävde en del ansträngning från oss, men till slut löste sig allt.

Tjänsten för att visa olika banners på hemsidan och i mobilapplikationen var en av de första som släpptes direkt på Tarantool. Den här tjänsten är anmärkningsvärd för det faktum att den är 6-7 år gammal, den är fortfarande i drift och har aldrig startat om. Master-master replikering användes. Inget gick sönder.

Det finns ett exempel på att använda Tarantool för snabbreferensfunktionalitet i ett lagersystem för att snabbt dubbelkolla information i vissa fall. Vi försökte använda Redis för detta, men data i minnet tog mer plats än Tarantool.

Tjänsterna med en väntelista, kundabonnemang, för närvarande fashionabla berättelser och uppskjutna varor fungerar också med Tarantool. Den sista tjänsten i minnet tar upp cirka 120 GB. Detta är den mest omfattande tjänsten av ovanstående.

Slutsats

Tack vare sekundära index kombinerat med nyckel-värde och transaktionalitet är Tarantool väl lämpat för mikrotjänster-baserade arkitekturer. Vi stötte dock på svårigheter när vi rullade ut ändringar av tjänster med mycket logik i Lua - tjänsterna slutade ofta att fungera. Vi kunde inte övervinna detta och med tiden kom vi fram till olika kombinationer av Lua och Go: vi vet var vi ska använda ett språk och var vi ska använda ett annat.

Vad mer att läsa om ämnet

Källa: will.com

Lägg en kommentar