Cartuccia Tarantool: Lua backend sharding in trè linee

Cartuccia Tarantool: Lua backend sharding in trè linee

In u Gruppu Mail.ru avemu Tarantool - questu hè un servitore d'applicazioni in Lua, chì hè ancu doppia cum'è una basa di dati (o vice versa?). Hè veloce è cool, ma e capacità di un servitore ùn sò micca sempre illimitate. A scala verticale ùn hè ancu una panacea, cusì Tarantool hà arnesi per a scala horizontale - u modulu vshard [1]. Permette di sparghje e dati in parechji servitori, ma avete bisognu à fà cuncede per stabilisce è aghjunghje a logica cummerciale.

Una bona nutizia: avemu cullatu alcuni grandi colpi (per esempiu [2], [3]) è hà creatu un altru quadru chì simplificà significativamente a suluzione à stu prublema.

Cartuccia Tarantool hè un novu quadru per u sviluppu di sistemi distribuiti cumplessi. Permette di fucalizza nantu à scrive a logica cummerciale invece di risolve i prublemi di l'infrastruttura. Sottu à u tagliu vi dicu cumu si travaglia stu quadru è cumu scrive servizii distribuiti aduprendu.

Chì ghjè esattamente u prublema?

Avemu una tarantula, avemu vshard - chì vulete più?

Prima, hè una questione di comodità. A cunfigurazione vshard hè cunfigurata attraversu e tavule Lua. Per un sistema distribuitu di parechji prucessi Tarantool per travaglià currettamente, a cunfigurazione deve esse a stessa in ogni locu. Nimu vole fà questu manualmente. Dunque, ogni tipu di script, Ansible è sistemi di implementazione sò usati.

Cartridge stessu gestisce a cunfigurazione vshard, face questu basatu nantu à a so propria cunfigurazione distribuita. Hè essenzialmente un schedariu YAML simplice, una copia di quale hè almacenata in ogni istanza di Tarantool. A simplificazione hè chì u quadru stessu monitoreghja a so cunfigurazione è assicura chì hè u listessu in ogni locu.

Siconda, hè dinò una questione di comodità. A cunfigurazione vshard ùn hà nunda di fà cù u sviluppu di a logica cummerciale è solu distracte u programatore da u so travagliu. Quandu avemu discututu l'architettura di un prughjettu, u più spessu parlemu di cumpunenti individuali è a so interazzione. Hè troppu prestu per pensà à sparghje un cluster à 3 centri di dati.

Avemu risoltu sti prublemi una volta è più, è à un certu puntu avemu riesciutu à sviluppà un approcciu chì simplificà u travagliu cù l'applicazione in tuttu u so ciclu di vita: creazione, sviluppu, teste, CI / CD, mantenimentu.

Cartuccia introduce u cuncettu di un rolu per ogni prucessu Tarantool. I roli sò un cuncettu chì permette à un sviluppatore di fucalizza nantu à scrive codice. Tutti i roli dispunibuli in u prugettu ponu esse eseguiti nantu à una istanza di Tarantool, è questu serà abbastanza per e teste.

Caratteristiche principali di Tarantool Cartridge:

  • orchestrazione di cluster automatizata;
  • espansione a funziunalità di l'applicazione utilizendu novi roles;
  • mudellu di applicazione per u sviluppu è a implementazione;
  • sharding automaticu integratu;
  • integrazione cù u framework di teste Luatest;
  • gestione di cluster cù WebUI è API;
  • Strumenti di imballaggio è implementazione.

Hola, Monde!

Ùn possu aspittà per vede u quadru stessu, cusì lasceremu a storia di l'architettura per più tardi è principià cù qualcosa simplice. Se assumemu chì Tarantool stessu hè digià stallatu, allora tuttu ciò chì resta hè di fà

$ tarantoolctl rocks install cartridge-cli
$ export PATH=$PWD/.rocks/bin/:$PATH

Questi dui cumandamenti installanu l'utilità di linea di cumanda è permettenu di creà a vostra prima applicazione da u mudellu:

$ cartridge create --name myapp

È questu hè ciò chì avemu:

myapp/
├── .git/
├── .gitignore
├── app/roles/custom.lua
├── deps.sh
├── init.lua
├── myapp-scm-1.rockspec
├── test
│   ├── helper
│   │   ├── integration.lua
│   │   └── unit.lua
│   ├── helper.lua
│   ├── integration/api_test.lua
│   └── unit/sample_test.lua
└── tmp/

Questu hè un repository git cun un prontu "Hello, World!" applicazione. Pruvemu di eseguisce subitu, dopu avè installatu prima e dipendenze (cumpresu u quadru stessu):

$ tarantoolctl rocks make
$ ./init.lua --http-port 8080

Dunque, avemu un nodu in esecuzione per a futura applicazione sharded. Un laico inquisitore pò apre immediatamente l'interfaccia web, cunfigurà un cluster di un node cù u mouse è gode di u risultatu, ma hè troppu prestu per rallegra. Finu a ora, l'appiecazione ùn pò micca fà nunda d'utile, cusì vi dicu nantu à a implementazione dopu, ma avà hè u tempu di scrive codice.

Sviluppu di l'applicazioni

Immaginate, simu cuncependu un prughjettu chì deve riceve dati, salvà è custruisce un rapportu una volta à ghjornu.

Cartuccia Tarantool: Lua backend sharding in trè linee

Cuminciamu à disegnà un diagramma è mette trè cumpunenti nantu à ellu: gateway, storage and scheduler. Travagliemu in più nantu à l'architettura. Siccomu usemu vshard cum'è almacenamiento, aghjunghjemu vshard-router è vshard-storage à u schema. Nè u gateway nè u pianificatore accede direttamente à l'almacenamiento hè per quessa chì u router hè per quessa hè statu creatu.

Cartuccia Tarantool: Lua backend sharding in trè linee

Stu diagramma ùn rapprisenta micca esattamente ciò chì avemu da custruisce in u prugettu perchè i cumpunenti parenu astratti. Avemu sempre bisognu di vede cumu questu serà prughjettatu nantu à u veru Tarantool - raggruppemu i nostri cumpunenti per prucessu.

Cartuccia Tarantool: Lua backend sharding in trè linee

Ci hè pocu puntu di mantene vshard-router è gateway in casi separati. Perchè avemu bisognu di navigà in a reta una volta, se questu hè digià a rispunsabilità di u router? Deve esse eseguite in u stessu prucessu. Questu hè, tramindui gateway è vshard.router.cfg sò inizializzati in un prucessu, è permettenu interagisce in u locu.

À u stadiu di cuncepimentu, era còmuda di travaglià cù trè cumpunenti, ma eiu, cum'è sviluppatore, mentre scrive u codice, ùn vogliu micca pensà à lancià trè casi di Tarnatool. Aghju bisognu di eseguisce e teste è verificate chì aghju scrittu correttu a porta. O forse vogliu dimustrà una funzione à i mo culleghi. Perchè duverebbe passà per u fastidiu di implementà trè copie? Hè cusì chì u cuncettu di roli hè natu. Un rolu hè un modulu luash regulare chì u ciclu di vita hè gestitu da Cartuccia. In questu esempiu, ci sò quattru - gateway, router, storage, scheduler. Ci pò esse più in un altru prughjettu. Tutti i roli ponu esse eseguiti in un prucessu, è questu serà abbastanza.

Cartuccia Tarantool: Lua backend sharding in trè linee

È quandu si tratta di implementazione à staging o produzzione, allora assignemu à ogni prucessu Tarantool u so propiu set di roli secondu e capacità di hardware:

Cartuccia Tarantool: Lua backend sharding in trè linee

Gestione di topulugia

L'infurmazione nantu à induve i roli sò in esecuzione deve esse guardatu in qualchì locu. E questu "in un locu" hè a cunfigurazione distribuita, chì aghju digià citatu sopra. A cosa più impurtante hè a topologia di cluster. Eccu 3 gruppi di replicazione di 5 prucessi Tarantool:

Cartuccia Tarantool: Lua backend sharding in trè linee

Ùn vulemu micca perdiri dati, cusì trattemu l'infurmazioni nantu à i prucessi in esecuzione cun cura. Cartuccia mantene a traccia di a cunfigurazione utilizendu un impegnu in duie fasi. Una volta vulemu aghjurnà a cunfigurazione, prima verifica chì tutti i casi sò dispunibuli è pronti per accettà a nova cunfigurazione. Dopu questu, a seconda fasa applica a cunfigurazione. Cusì, ancu s'è una copia hè temporaneamente indisponibile, ùn succede nunda di male. A cunfigurazione ùn serà micca solu appiicata è vi vede un errore in anticipu.

Ancu in a seccione di topologia, hè indicatu un parametru cusì impurtante cum'è u capu di ogni gruppu di replicazione. Di solitu questu hè a copia chì hè stata arregistrata. U restu sò più spessu in lettura, ancu s'ellu ci ponu esse eccezzioni. Calchì volta i sviluppatori bravi ùn anu micca paura di cunflitti è ponu scrive dati à parechje rèpliche in parallelu, ma ci sò parechje operazioni chì, ùn importa ciò chì, ùn deve esse realizatu duie volte. Per questu ci hè un signu di un capu.

Cartuccia Tarantool: Lua backend sharding in trè linee

A vita di roli

Per esse un rolu astrattu in una tale architettura, u quadru deve in qualchì manera gestisce. Naturalmente, u cuntrollu si faci senza riavvia u prucessu Tarantool. Ci sò 4 callbacks per gestisce i roli. Cartuccia stessu li chjamarà secondu ciò chì hè scrittu in a so cunfigurazione distribuita, applicà cusì a cunfigurazione à roli specifichi.

function init()
function validate_config()
function apply_config()
function stop()

Ogni rolu hà una funzione init. Hè chjamatu una volta o quandu u rolu hè attivatu o quandu Tarantool hè riavviatu. Hè cunvenutu quì, per esempiu, per inizializà box.space.create, o u scheduler pò lancià una fibra di fondu chì hà da fà u travagliu in certi intervalli di tempu.

Una funzione init pò esse micca abbastanza. Cartuccia permette à i roli di prufittà di a cunfigurazione distribuita chì usa per almacenà a topologia. Pudemu dichjarà una nova sezione in a listessa cunfigurazione è almacenà un fragmentu di a cunfigurazione cummerciale in questu. In u mo esempiu, questu puderia esse un schema di dati o paràmetri di pianificazione per u rolu di pianificatore.

Chjama di cluster validate_config и apply_config ogni volta chì a cunfigurazione distribuita cambia. Quandu una cunfigurazione hè appiicata da un impegnu in dui fasi, u cluster verifica chì ogni rolu hè prontu à accettà sta nova cunfigurazione è, se ne necessariu, informa un errore à l'utilizatore. Quandu tutti accunsenu chì a cunfigurazione hè normale, allora u apply_config.

I roli anu ancu un metudu stop, chì hè necessariu per pulizziari l'output di u rolu. Se dicemu chì u pianificatore ùn hè più necessariu in questu servitore, pò piantà quelli fibre chì hà cuminciatu init.

I roli ponu interagisce cù l'altri. Semu abituati à scrive e chjama di funzione in Lua, ma pò accade chì un prucessu datu ùn hà micca u rolu chì avemu bisognu. Per facilità e chjama nantu à a reta, usemu u modulu ausiliariu rpc (call procedure remote), chì hè custruitu nantu à a basa di a netbox standard integrata in Tarantool. Questu pò esse utile se, per esempiu, u vostru gateway vole dumandà direttamente à u pianificatore per fà u travagliu avà, invece di aspittà un ghjornu.

Un altru puntu impurtante hè di assicurà a tolleranza di difetti. Cartuccia usa u protocolu SWIM per monitorizà a salute [4]. In corta, i prucessi scambià "rumori" cù l'altri nantu à UDP - ogni prucessu dice à i so vicini l'ultime nutizie, è rispondenu. Se di colpu a risposta ùn vene micca, Tarantool principia à suspettà chì qualcosa hè sbagliatu, è dopu un pocu tempu recita a morte è principia à dì à tutti sta nutizia.

Cartuccia Tarantool: Lua backend sharding in trè linee

Basatu annantu à stu protokollu, Cartuccia urganizeghja u prucessu di fallimentu automaticu. Ogni prucessu monitoreghja u so ambiente, è se u capu di colpu smette di risponde, a replica pò piglià u so rolu, è Cartridge cunfigura i roli in esecuzione in cunseguenza.

Cartuccia Tarantool: Lua backend sharding in trè linee

Avete bisognu à esse attentu quì, perchè u cambiamentu frequente avanti è avanti pò purtà à cunflitti di dati durante a replicazione. Di sicuru, ùn deve micca attivà u failover automaticu à l'aleatoriu. Avemu da capisce chjaramente ciò chì succede è esse sicuru chì a replicazione ùn si romperà dopu chì u capu hè restauratu è a corona hè tornata à ellu.

Da tuttu questu, pudete avè a sensazione chì i roli sò simili à i microservizi. In un sensu, sò solu questu, solu cum'è moduli in i prucessi Tarantool. Ma ci sò ancu una quantità di differenzi fundamentali. Prima, tutti i roli di u prughjettu devenu campà in a stessa basa di codice. E tutti i prucessi di Tarantool deve esse lanciatu da a listessa basa di codice, perchè ùn ci sò micca sorprese cum'è quelli chì avemu da pruvà à inizializà u scheduler, ma simpricimenti ùn esiste micca. Inoltre, ùn deve micca permette di differenzi in versioni di codice, perchè u cumpurtamentu di u sistema in una tale situazione hè assai difficiuli di predichendu è debug.

A cuntrariu di Docker, ùn pudemu micca solu piglià un rolu "imaghjini", piglià à un'altra macchina è eseguisce quì. I nostri roli ùn sò micca cusì isolati cum'è i cuntenituri Docker. Inoltre, ùn pudemu micca eseguisce dui roli identichi nantu à una istanza. Un rolu o esiste o ùn hè micca in un sensu, hè un singleton. E terzu, i roli devenu esse listessi in tuttu u gruppu di replicazione, perchè altrimenti seria assurdu - i dati sò listessi, ma a cunfigurazione hè diversa.

Strumenti di implementazione

Aghju prumessu di mostrà cumu Cartridge aiuta à implementà l'applicazioni. Per fà a vita più faciule per l'altri, i pacchetti di framework RPM:

$ cartridge pack rpm myapp -- упакует для нас ./myapp-0.1.0-1.rpm
$ sudo yum install ./myapp-0.1.0-1.rpm

U pacchettu installatu cuntene guasi tuttu ciò chì avete bisognu: sia l'applicazione sia e dipendenze installate. Tarantool ghjunghjerà ancu in u servitore cum'è una dependenza di u pacchettu RPM, è u nostru serviziu hè prontu à lancià. Questu hè fattu attraversu systemd, ma prima avete bisognu di scrive un pocu cunfigurazione. À u minimu, specificate l'URI di ogni prucessu. Trè hè abbastanza per esempiu.

$ sudo tee /etc/tarantool/conf.d/demo.yml <<CONFIG
myapp.router: {"advertise_uri": "localhost:3301", "http_port": 8080}
myapp.storage_A: {"advertise_uri": "localhost:3302", "http_enabled": False}
myapp.storage_B: {"advertise_uri": "localhost:3303", "http_enabled": False}
CONFIG

Ci hè una sfumatura interessante quì. Invece di specificà solu u portu di protokollu binariu, specifiemu l'indirizzu publicu tutale di u prucessu cumpresu u nome d'ospite. Questu hè necessariu per chì i nodi di cluster sappianu cumu cunnette cù l'altri. Hè una mala idea di utilizà 0.0.0.0 cum'è l'indirizzu advertise_uri deve esse un indirizzu IP esternu, micca un socket bind. Senza ellu, nunda ùn hà da travaglià, cusì Cartridge simpricimenti ùn vi permetterà di lancià un node cù u advertise_uri sbagliatu.

Avà chì a cunfigurazione hè pronta, pudete inizià i prucessi. Siccomu una unità systemd regulare ùn permettenu micca più di un prucessu per inizià, l'applicazioni nantu à a Cartuccia sò stallate da u cusì chjamatu. unità instantiate chì funzionanu cusì:

$ sudo systemctl start myapp@router
$ sudo systemctl start myapp@storage_A
$ sudo systemctl start myapp@storage_B

In a cunfigurazione, avemu specificatu u portu HTTP nantu à quale Cartridge serve l'interfaccia web - 8080. Andemu à ellu è fate un ochju:

Cartuccia Tarantool: Lua backend sharding in trè linee

Avemu vistu chì ancu se i prucessi sò in esecuzione, ùn sò micca cunfigurati. U cartucciu ùn sapi ancu quale deve riplicà cù quale è ùn pò micca fà una decisione per sè stessu, cusì aspetta per e nostre azzioni. Ma ùn avemu micca assai scelta: a vita di un novu cluster principia cù a cunfigurazione di u primu node. Allora aghjunghjemu l'altri à u cluster, l'assignemu roli, è à questu puntu a implementazione pò esse cunsiderata cum'è successu.

Versemu un vetru di a vostra bevanda preferita è rilassate dopu una longa settimana di travagliu. L'applicazione pò esse usata.

Cartuccia Tarantool: Lua backend sharding in trè linee

Risultati

Chì sò i risultati ? Pruvate, aduprate, lasciate feedback, create biglietti nantu à Github.

referenze

[1] Tarantool » 2.2 » Riferimentu » Riferimentu Rocks » Module vshard

[2] Cume avemu implementatu u core di l'affari d'investimentu di Alfa-Bank basatu in Tarantool

[3] Architettura di fattura di nova generazione: trasfurmazioni cù a transizione à Tarantool

[4] SWIM - protocolu di custruzzione di cluster

[5] GitHub - tarantool/cartuccia-cli

[6] GitHub - tarantool/cartuccia

Source: www.habr.com

Add a comment