
Všichni máme rádi příběhy. Rádi si sedneme k ohni a vyprávíme o svých minulých vítězstvích, bitvách nebo prostě o svých pracovních zkušenostech.
Dnes je právě takový den. I když nyní nejste u ohně, máme pro vás příběh. Příběh o tom, jak jsme začali pracovat s úložištěm na Tarantool.
Kdysi dávno měla naše firma několik „monolitů“ a jeden společný „strop“, který se k těmto monolitům pomalu, ale jistě blížil, omezující rozvoj naší firmy. A bylo jasné, že se jednou pevně narazíme na tento strop.
Dnes vládne ideologie rozdělení všeho a všude, počínaje hardwarem a konče obchodní logikou. V důsledku toho máme například dvě DC, prakticky nezávislá na síťové úrovni. Tehdy to však bylo naprosto jinak.
Dnes existuje spousta nástrojů a prostředků pro provádění změn, jako jsou CI/CD, K8S a podobně. V „monolitní“ době jsme však nepotřebovali tolik cizích slov. Stačilo jen opravit „úlohu“ v databázi.
Ale čas plynul vpřed a počet dotazů se posouval vpřed s ním, občas přičemž RPS překonávalo naše možnosti. Při vstupu na trh zemí SNS nezatěžovala zátěž na procesoru DB prvního monolitu pokles pod 90 %, a RPS zůstávaly na úrovni 2400. A to nebyly jen malé selektivky, ale obrovské dotazy se spoustou kontrol a JOINů, které mohly prostoupit téměř polovinou dat v prostředí vysokého I/O.
Když na scéně začaly probíhat skutečné výprodeje během „Černého pátku“, - a Wildberries je začal pořádat jako jeden z prvních v Rusku, - situace se stala opravdu žalostnou. Vždyť zátěž v takových dnech vzrostla třikrát.
Ach, ty „monolitní časy“! Jsem si jist, že i vy jste se setkali s podobným a stále nemůžete pochopit, jak se to mohlo stát vám.
Co se dá dělat — móda se týká i technologií. Ještě před pěti lety jsme museli přepracovat jednu z takových mód v podobě existujícího webu na .NET a MS SQL serveru, který pečlivě uchovával veškerou logiku fungování samotného webu. Uchovával ji tak pečlivě, že rozřezání takového monolitu se ukázalo jako dlouhá a zdaleka nejednoduchá zábava.
Malé odbočení.
Na různých akcích říkám: „Pokud jste neodřízli monolit, nevyrostli jste!“ Zajímá mě váš názor na to, napište mi prosím do komentářů.
A hrom zaburácel
Vrátíme se k našemu "krbu". Abychom rozdělili zátěž "monolitní" funkčnosti, rozhodli jsme se rozdělit systém na mikroslužby založené na technologích s otevřeným zdrojovým kódem. Protože, minimálně, jejich škálování je levnější. A pochopení toho, že se bude muset škálovat (a hodně), jsme měli na 100 %. Už v té době jsme se dostali na trhy sousedních zemí a počet registrací, stejně jako počet objednávek, začal růst ještě rychleji.
Po analýze prvních uchazečů o odchod z monolitu do mikroslužeb jsme pochopili, že v 80 % případů dochází ke 99 % zápisům z back office systémů, zatímco čtení probíhá z front endu. To se především týkalo několika důležitých subsystémů pro nás - uživatelských dat a systému výpočtu konečné ceny zboží na základě informací o dodatečných zákaznických slevách a kuponech.
Na pravomoce odstavce. Teď je těžké si to představit, ale vedle výše zmíněných subsystémů byly z našeho monolitu také vyjmuty produktové katalogy, uživatelský košík, systém vyhledávání produktů, systém filtrování produktových katalogů a různé doporučovací systémy. Pro každého z nich existují samostatné třídy úzce specializovaných systémů, ale kdysi všichni bydleli v jednom "domku".
Okamžitě jsme naplánovali vyjmutí dat o našich zákaznících do shardované systému. Vyjmutí funkčnosti výpočtu konečné ceny zboží vyžadovalo dobrou škálovatelnost v čtení, protože ta vytvářela největší zátěž na RPS a byla nejnáročnější na provedení pro databázi (do procesu výpočtů bylo zapojeno velmi mnoho dat).
V důsledku toho se nám narodila schéma, která se dobře kombinuje s Tarantool.
V té době byly pro fungování mikroslužeb vybrány schémata práce s několika datovými centry na virtuálních a fyzických strojích. Jak ukazují obrázky, byly použity varianty replikací Tarantool jak v režimu master-master, tak master-slave.

Architektura. Varianta 1. Služba pro uživatele
V současné době se jedná o 24 shardů, z nichž každý má 2 instance (po jedné na každém DC), všechny v režimu master-master.
Nad databázemi se nacházejí aplikace, které komunikují s replikami databáze. Aplikace pracují s Tarantool prostřednictvím naší vlastní knihovny, která implementuje rozhraní Go ovladače Tarantool. Vidí všechny repliky a může pracovat s masterem pro čtení a zápis. V podstatě realizuje model replica set, do kterého byla přidána logika výběru replik, provádění opakovaných pokusů, circuit breaker a rate limit.
Přitom je možné konfigurovat politiku výběru repliky v rámci shardu. Například round-robin.

Architektura. Varianta 2. Služba pro výpočet konečné ceny zboží.
Před několika měsíci většina požadavků na výpočet konečné ceny zboží přešla na novou službu, která v podstatě funguje bez databází, ale nějakou dobu 100 % zpracovávala služba s Tarantool pod kapotou.
Databáze služby to jsou 4 master servery, do kterých synchronizátor shromažďuje data, a každý z těchto masterů prostřednictvím replikace distribuuje data na readonly repliky. Každý master má přibližně 15 takových replik.
Ať už v prvním či druhém schématu, v případě nedostupnosti jednoho DC může aplikace získávat data z druhého.
Je třeba poznamenat, že v Tarantool je replikace poměrně flexibilní a konfigurovatelná za běhu. V jiných systémech mohou nastávat komplikace. Například při změně parametrů max_wal_senders a max_replication_slots v PostgreSQL je vyžadován restart masteru, což v některých případech může vést k přerušení spojení mezi aplikací a DBMS.
Hledejte a naleznete!
Proč jsme neudělali "jako normální lidé" a zvolili netypický způsob? Závisí na tom, co považovat za normální. Mnozí vůbec tvoří klastr z Mongo a rozprostírají ho po třech geograficky distribuovaných DC.
Tehdy už jsme měli dva projekty na Redis. První byl cache a druhý představoval persistentní úložiště pro méně kritická data. S ním to bylo docela složité, částečně i naší vinou. Někdy se v klíči nacházely dost velké objemy a občas to způsobovalo problémy na webu. Tento systém jsme používali v variantě master-slave. A bylo mnoho případů, kdy se s masterem něco dělo a replikace se rozbila.
Redis je tedy dobrý pro stateless úkoly, ne však pro stateful. V zásadě to řešilo většinu problémů, ale pouze pokud šlo o řešení typu key-value s několika indexy. Nicméně v té době měl Redis problémy s perzistencí a replikací. Kromě toho byly i stížnosti na výkon.
Zvažovali jsme MySQL a PostgreSQL. První se u nás nějak neuchytil, zatímco druhý je sám o sobě poměrně složitý produkt a bylo by nevhodné na něm stavět jednoduché služby.
Zkoušeli jsme RIAK, Cassandru, dokonce i grafovou databázi. Všechna tato řešení jsou poměrně specifická a nehodila se jako obecný univerzální nástroj pro vytváření služeb.
Nakonec jsme se rozhodli pro Tarantool.
Oslovili jsme ho, když byl ve verzi 1.6. Zaujal nás v něm symbióza key-value a funkčnost relační databáze. Existují sekundární indexy, transakce a spacety, což jsou jako tabulky, ale složitější, lze v nich uchovávat různé počty sloupců. Ale killer feature Tarantoolu byly sekundární indexy v kombinaci s key-value a transakčním zpracováním.
Důležitou roli hrálo také reagující rusky mluvící společenství, které bylo ochotné pomoci v chatu. Aktivně jsme toho využívali a prakticky jsme žili v chatu. A nesmíme zapomínat na slušnou perzistenci bez zjevného chyb a nedostatků. Pokud se podíváme na naši historii s Tarantool, měli jsme hodně bolestí a problémů s replikací, ale ani jednou jsme díky němu neztratili data!
Zavádění začalo obtížně.
V té době byl naším hlavním vývojovým stackem .NET, pro který neexistoval konektor pro Tarantool. Ihned jsme začali něco dělat v Go. S Lua se také docela dařilo. Hlavní problém v tu chvíli byl s laděním: v .NET bylo vše skvělé, ale poté se ponořit do světa embedded Lua, když máš kromě logů žádné ladění, bylo složité. Kromě toho se replikace z nějakého důvodu občas rozpadla, což nás donutilo hlouběji proniknout do struktury engine Tarantoolu. V tom pomohl chat, méně už dokumentace, někdy jsme se dívali do kódu. V té době byla dokumentace průměrná.
Tak se během několika měsíců podařilo nasbírat zkušenosti a dosáhnout dobrých výsledků při práci s Tarantool. Vytvořili jsme v Gitu vzorové vývojové práce, které pomáhaly při vzniku nových mikroslužeb. Například, když vznikl úkol: vytvořit další mikroslužbu, developer se podíval na zdrojové kódy vzorového řešení v repozitáři a vytvoření nového trvalo maximálně týden.
Byly to zvláštní časy. Tehdy jsi mohl přistoupit k adminovi u vedlejšího stolu a požádat: „Dej mi virtuálku“. Po nějakých třiceti minutách byla mašina už tvoje. Sám jsi se připojoval, všechno instaloval a měli jsi na to přivedený provoz.
Dnes už to takto nefunguje: je třeba nastavit monitoring služby, logování, pokrýt funkcionalitu testy, objednat virtuálku nebo nasazení v Kubernetes atd. Obecně je to lepší, i když je to delší a složitější.
Rozděluj a panuj. Jak to vypadá s Luou?
Byla vážná dilema: některým týmům se nedařilo spolehlivě nasazovat změny v službě s velkým množstvím logiky na Luě. Často to vedlo k nefunkčnosti služby.
To znamená, že vývojáři připravují nějakou změnu. Tarantool začne provádět migraci, zatímco replikace má ještě starý kód; přijde tam nějaký DDL přes replikaci, něco jiného a kód se jednoduše rozpadne, protože to nebylo zohledněno. V důsledku toho byla procedura aktualizace u adminů popsána na listu A4: zastavit replikaci, aktualizovat to, zapnout replikaci, vypnout zde, aktualizovat tam. Hrůza!
Nakonec se dnes snažíme na Luě nic nedělat. Jen pomocí iproto (binární protokol pro komunikaci se serverem) a to je vše. Možná je to nedostatek znalostí u vývojářů, ale z tohoto pohledu je systém složitý.
Nedodržujeme vždy slepě tento scénář. Dnes nemáme černou a bílou: buď všechno na Luě, nebo všechno na Go. Už chápeme, jak to kombinovat, abychom později neměli problémy s migrací.
Kde je nyní Tarantool?
Tarantool se používá ve službě pro výpočet konečné ceny zboží s ohledem na slevové kupóny, známé jako „Promotayzer“. Jak jsem již dříve zmínil, nyní odchází do pozadí: nahrazuje ho nový katalogový servis s předpočítanými cenami, ale ještě před půl rokem se všechny výpočty prováděly v „Promotayzeru“. Dříve byla polovina jeho logiky napsaná v Lua. Před dvěma lety se ze služby stalo úložiště a logika byla přepracována do Go, protože mechanismus práce se slevami se mírně změnil a službě chyběla výkonnost.
Jednou z nejkritičtějších služeb je profil uživatele. To znamená, že všichni uživatelé Wildberries jsou uloženi v Tarantoolu, je jich asi 50 milionů. Systém shardovaný podle ID uživatele, rozložený ve několika datových centrech s vazbou na Go-servisy.
Dříve byl lídrem podle RPS „Promotayzer“, dostal se až na 6000 požadavků. V určitém okamžiku jsme měli 50-60 instancí. Nyní je lídrem podle RPS - profily uživatelů, přibližně 12 tisíc. V této službě se používá vlastní shardování s rozdělením podle rozsahů uživatelských ID. Služba obsluhuje více než 20 strojů, ale to je příliš mnoho, plánujeme snížit vyhrazené zdroje, protože stačí kapacita 4-5 strojů.
Služba relací je náš první servis na vshard a Cartridge. Nastavení vshard a aktualizace Cartridge si vyžádaly určité pracovní náklady, ale nakonec to všechno vyšlo.
Služba pro zobrazování různých bannerů na webu a v mobilní aplikaci byla jednou z prvních, která byla ihned spuštěna na Tarantoolu. Tato služba je zajímavá tím, že je stará asi 6-7 let, stále funguje a nikdy nebyla restartována. Používala se replikace master-master. Nikdy se nic neporouchalo.
Existuje příklad použití Tarantoolu pro funkčnost rychlých adresářů ve skladovém systému, aby bylo možné rychle ověřit informace v některých případech. Zkoušeli jsme na to použít Redis, ale data v paměti zabírala více místa než u Tarantoolu.
Služby čekacích seznamů, klientských předplatných, populárních dnes příběhů a odložených produktů také fungují s Tarantool. Poslední služba zabírá v paměti přibližně 120 GB. To je nejobjemnější služba z výše uvedených.
Závěr
Díky sekundárním indexům v kombinaci s key-value a transakčností je Tarantool skvělou volbou pro architektury založené na mikroslužbách. Nicméně jsme narazili na potíže, když jsme nasazovali změny v serviciích s velkým množstvím logiky v Lua — služby často přestávaly fungovat. Tento problém se nám nepodařilo vyřešit, a časem jsme přešli na různé kombinace Lua a Go: víme, kde je dobré použít jeden jazyk a kde jiný.
Co dalšího si přečíst na toto téma
- Vytváříme od nuly vysoce zatíženou aplikaci na Tarantool
- Spolehlivá volba lídra v Tarantool Cartridge
- Telegram kanál Tarantool s novinkami o produktu
- Diskutovat o Tarantool v komunitním chatu
Zdroj: habr.com
