Tarantool Cartridge: sharding in Lua backend yn trije rigels

Tarantool Cartridge: sharding in Lua backend yn trije rigels

By Mail.ru Group hawwe wy Tarantool - dit is in applikaasjetsjinner yn Lua, dy't ek dûbelje as in databank (of oarsom?). It is fluch en cool, mar de mooglikheden fan ien server binne noch altyd net ûnbeheind. Fertikale skaalfergrutting is ek gjin panacea, dus Tarantool hat ark foar horizontale skaalfergrutting - de vshard-module [1]. It lit jo gegevens oer ferskate servers sjitte, mar jo moatte dermei tinke om it yn te stellen en de saaklike logika te heakjen.

Goed nijs: wy hawwe wat grutte foto's sammele (bgl [2], [3]) en makke in oar ramt dat de oplossing foar dit probleem signifikant sil ferienfâldigje.

Tarantool Cartridge is in nij ramt foar it ûntwikkeljen fan komplekse ferspraat systemen. It lit jo rjochtsje op it skriuwen fan saaklike logika ynstee fan it oplossen fan ynfrastruktuerproblemen. Under de besuniging sil ik jo fertelle hoe't dit ramt wurket en hoe't jo ferspraat tsjinsten skriuwe mei it.

Wat is krekt it probleem?

Wy hawwe in tarantula, wy hawwe vshard - wat kinne jo mear wolle?

Earst is it in kwestje fan gemak. De vshard-konfiguraasje is konfigureare fia Lua-tabellen. Foar in ferdield systeem fan meardere Tarantool-prosessen om goed te wurkjen, moat de konfiguraasje oeral itselde wêze. Nimmen wol dit mei de hân dwaan. Dêrom wurde allerhanne skripts, Ansible en ynsetsystemen brûkt.

Cartridge sels beheart de vshard-konfiguraasje, it docht dit basearre op har eigen ferspraat konfiguraasje. It is yn wêzen in ienfâldich YAML-bestân, wêrfan in kopy wurdt opslein yn elke Tarantool-eksimplaar. De ferienfâldiging is dat it ramt sels syn konfiguraasje kontrolearret en soarget dat it oeral itselde is.

As twadde is it wer in kwestje fan gemak. De vshard-konfiguraasje hat neat te krijen mei de ûntwikkeling fan saaklike logika en fersteurt allinich de programmeur fan syn wurk. As wy de arsjitektuer fan in projekt besprekke, prate wy meast oer yndividuele komponinten en har ynteraksje. It is te betiid om te tinken oer it útroljen fan in kluster nei 3 datasintra.

Wy hawwe oplost dizze problemen hieltyd wer, en op in stuit wy slagge te ûntwikkeljen in oanpak dy't ferienfâldige wurkjen mei de applikaasje troch syn hiele libben syklus: oanmeitsjen, ûntwikkeling, testen, CI / CD, ûnderhâld.

Cartridge yntrodusearret it konsept fan in rol foar eltse Tarantool proses. Rollen binne in konsept wêrmei in ûntwikkelder te rjochtsjen op it skriuwen fan koade. Alle rollen beskikber yn it projekt kinne wurde útfierd op ien Tarantool eksimplaar, en dit sil wêze genôch foar tests.

Wichtige funksjes fan Tarantool Cartridge:

  • automatisearre klusterorkestraasje;
  • it útwreidzjen fan de funksjonaliteit fan 'e applikaasje mei nije rollen;
  • applikaasje sjabloan foar ûntwikkeling en ynset;
  • ynboude automatyske sharding;
  • yntegraasje mei it Luatest testkader;
  • klusterbehear mei WebUI en API;
  • pakket- en ynset ark.

Hallo wrâld!

Ik kin net wachtsje om it ramt sels te sjen, dat wy litte it ferhaal oer de arsjitektuer foar letter en begjinne mei wat ienfâldich. As wy oannimme dat Tarantool sels al ynstalleare is, dan bliuwt alles te dwaan

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

Dizze twa kommando's sille de kommandorigel-hulpprogramma's ynstallearje en kinne jo jo earste applikaasje meitsje fanút it sjabloan:

$ cartridge create --name myapp

En dit is wat wy krije:

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/

Dit is in git-repository mei in klearmakke "Hallo, wrâld!" oanfraach. Litte wy besykje it direkt út te fieren, nei't wy de ôfhinklikens earder ynstalleare (ynklusyf it ramt sels):

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

Dat, wy hawwe ien knooppunt dy't rint foar de takomstige sharded applikaasje. In nijsgjirrige leek kin de webynterface fuortendaliks iepenje, in kluster fan ien knooppunt mei de mûs konfigurearje en genietsje fan it resultaat, mar it is te betiid om bliid te wêzen. Oant no kin de applikaasje neat nuttich dwaan, dus ik sil jo letter fertelle oer ynset, mar no is it tiid om koade te skriuwen.

Applikaasje Untwikkeling

Stel jo gewoan foar, wy ûntwerpe in projekt dat gegevens moat ûntfange, opslaan en ien kear deis in rapport bouwe.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Wy begjinne it tekenjen fan in diagram en pleatse der trije komponinten op: gateway, opslach en planner. Wy wurkje fierder oan de arsjitektuer. Om't wy vshard brûke as opslach, foegje wy vshard-router en vshard-opslach ta oan it skema. Noch de gateway noch de planner sille direkt tagong krije ta de opslach; dêr is de router foar, dêr is it foar makke.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Dit diagram stiet noch altyd net krekt foar wat wy sille bouwe yn it projekt, om't de komponinten abstrakt sjogge. Wy moatte noch sjen hoe't dit sil wurde projekteare op it echte Tarantool - litte wy ús komponinten groepearje per proses.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

D'r is net folle nut om vshard-router en gateway op aparte eksimplaren te hâlden. Wêrom moatte wy nochris op it netwurk surfe as dit al de ferantwurdlikens is fan 'e router? Se moatte wurde útfierd binnen itselde proses. Dat is, sawol gateway en vshard.router.cfg wurde inisjalisearre yn ien proses, en lit se ynteraksje lokaal.

Op it ûntwerpstadium wie it handich om te wurkjen mei trije komponinten, mar ik, as ûntwikkelder, by it skriuwen fan de koade, wol net tinke oer it lansearjen fan trije eksimplaren fan Tarnatool. Ik moat tests útfiere en kontrolearje dat ik gateway goed skreaun haw. Of miskien wol ik in eigenskip oan myn kollega's demonstrearje. Wêrom moat ik gean troch it gedoe fan it ynsetten fan trije eksimplaren? Dit is hoe't it konsept fan rollen berne is. In rol is in reguliere luash module waans libben syklus wurdt beheard troch Cartridge. Yn dit foarbyld binne d'r fjouwer fan har - gateway, router, opslach, planner. Der kin mear yn in oar projekt. Alle rollen kinne wurde útfierd yn ien proses, en dit sil wêze genôch.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

En as it giet om ynset foar staging as produksje, dan sille wy elk Tarantool-proses in eigen set rollen tawize ôfhinklik fan de hardwaremooglikheden:

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Topology behear

Ynformaasje oer wêr't hokker rollen rinne moat earne opslein wurde. En dit "earne" is de ferdielde konfiguraasje, dy't ik hjirboppe al neamde. It wichtichste ding oer it is de klustertopology. Hjir binne 3 replikaasjegroepen fan 5 Tarantool-prosessen:

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Wy wolle gjin gegevens ferlieze, dus behannelje wy ynformaasje oer rinnende prosessen mei soarch. Cartridge hâldt de konfiguraasje by mei in twa-fase commit. Sadree't wy de konfiguraasje bywurkje wolle, kontrolearret it earst dat alle eksimplaren beskikber binne en klear binne om de nije konfiguraasje te akseptearjen. Hjirnei jildt de twadde faze de konfiguraasje. Sels as ien eksimplaar tydlik net beskikber blykt te wêzen, bart der dus neat slims. De konfiguraasje sil gewoan net tapast wurde en jo sille foarôf in flater sjen.

Ek yn 'e topology-seksje wurdt sa'n wichtige parameter as de lieder fan elke replikaasjegroep oanjûn. Meastal is dit de kopy dy't opnommen wurdt. De rest is meastentiids allinnich-lês, al kinne der útsûnderings wêze. Soms binne dappere ûntwikkelders net bang foar konflikten en kinne parallel gegevens skriuwe nei ferskate replika's, mar d'r binne guon operaasjes dy't, wat dan ek, net twa kear moatte wurde útfierd. Dêrfoar is der in teken fan in lieder.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

It libben fan rollen

Om in abstrakte rol te bestean yn sa'n arsjitektuer, moat it ramt se op ien of oare manier beheare. Natuerlik komt kontrôle foar sûnder it Tarantool-proses opnij te begjinnen. D'r binne 4 callbacks om rollen te behearjen. Cartridge sels sil neame se ôfhinklik fan wat is skreaun yn syn ferspraat konfiguraasje, dêrmei it tapassen fan de konfiguraasje foar spesifike rollen.

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

Elke rol hat in funksje init. It wurdt ien kear neamd as de rol ynskeakele is of as Tarantool opnij starte. It is dêr handich om bygelyks box.space.create te inisjalisearjen, of de planner kin wat eftergrûnfaser starte dy't wurk op bepaalde tiidintervallen sil útfiere.

Ien funksje init kin net genôch. Cartridge lit rollen profitearje fan 'e ferdielde konfiguraasje dy't it brûkt om de topology te bewarjen. Wy kinne in nije seksje yn deselde konfiguraasje ferklearje en in fragmint fan 'e saaklike konfiguraasje dêryn opslaan. Yn myn foarbyld kin dit in gegevensskema of skema-ynstellings wêze foar de rol fan 'e planner.

Cluster calls validate_config и apply_config elke kear as de ferdielde konfiguraasje feroaret. As in konfiguraasje wurdt tapast troch in twa-faze commit, it kluster kontrolearret dat elke rol is klear om te akseptearjen dizze nije konfiguraasje en, as it nedich is, rapportearret in flater oan de brûker. As elkenien it iens is dat de konfiguraasje normaal is, dan is de apply_config.

Ek rollen hawwe in metoade stop, dy't nedich is om de útfier fan 'e rol op te romjen. As wy sizze dat planner is net mear nedich op dizze tsjinner, it kin stopje dy fezels dat it begûn mei init.

Rollen kinne mei-inoar ynteraksje. Wy binne wend oan it skriuwen fan funksje-oanroppen yn Lua, mar it kin barre dat in bepaald proses net de rol hat dy't wy nedich binne. Om petearen oer it netwurk te fasilitearjen, brûke wy de helpmodule rpc (oprop op ôfstânproseduere), dy't boud is op basis fan 'e standert netbox yn Tarantool boud. Dit kin nuttich wêze as bygelyks jo poarte de planner direkt wol freegje om it wurk no direkt te dwaan, ynstee fan in dei te wachtsjen.

In oar wichtich punt is it garandearjen fan fouttolerânsje. Cartridge brûkt it SWIM-protokol om sûnens te kontrolearjen [4]. Koartsein, prosessen útwikselje "geroften" mei elkoar oer UDP-elk proses fertelt syn buorlju it lêste nijs, en se reagearje. As it antwurd ynienen net komt, begjint Tarantool te fermoedzjen dat der wat mis is, en nei in skoft reciteert it de dea en begjint elkenien om dit nijs te fertellen.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Op grûn fan dit protokol organisearret Cartridge automatyske flaterferwurking. Elk proses kontrolearret syn omjouwing, en as de lieder ynienen ophâldt te reagearjen, kin de replika syn rol oernimme, en Cartridge konfigurearret de rinnende rollen neffens.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Jo moatte hjir foarsichtich wêze, om't faak heen en wer wikselje kin liede ta gegevenskonflikten by replikaasje. Fansels moatte jo automatyske failover net willekeurich ynskeakelje. Wy moatte dúdlik begripe wat der bart en der wis fan wêze dat replikaasje net sil brekke nei't de lieder is restaurearre en de kroan wurdt weromjûn oan him.

Fan dit alles kinne jo it gefoel krije dat rollen fergelykber binne mei mikrotsjinsten. Yn in sin binne se krekt dat, allinich as modules binnen Tarantool-prosessen. Mar der binne ek in oantal fûnemintele ferskillen. Earst moatte alle projektrollen yn deselde koadebasis libje. En alle Tarantool-prosessen moatte wurde lansearre fanút deselde koadebasis, sadat d'r gjin ferrassingen binne lykas wannear't wy besykje de planner te inisjalisearjen, mar it bestiet gewoan net. Ek moatte jo gjin ferskillen yn koadeferzjes tastean, om't it gedrach fan it systeem yn sa'n situaasje heul lestich is om te foarsizzen en te debuggen.

Oars as Docker kinne wy ​​net gewoan in rol "ôfbylding" nimme, it nei in oare masine nimme en it dêr útfiere. Us rollen binne net sa isolearre as Docker-konteners. Ek kinne wy ​​​​net twa identike rollen op ien eksimplaar útfiere. In rol bestiet of net; yn in sin is it in singleton. En as tredde moatte de rollen itselde wêze binnen de hiele replikaasjegroep, want oars soe it absurd wêze - de gegevens binne itselde, mar de konfiguraasje is oars.

Ynset ark

Ik tasein om sjen te litten hoe't Cartridge helpt by it ynsetten fan applikaasjes. Om it libben makliker te meitsjen foar oaren, pakket it ramt RPM-pakketten:

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

It ynstalleare pakket befettet hast alles wat jo nedich binne: sawol de applikaasje as de ynstalleare ôfhinklikens. Tarantool sil ek op 'e server komme as ôfhinklikens fan it RPM-pakket, en ús tsjinst is klear om te starten. Dit wurdt dien fia systemd, mar earst moatte jo in bytsje konfiguraasje skriuwe. Spesifisearje op syn minst de URI fan elk proses. Trije is genôch bygelyks.

$ 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

D'r is hjir in nijsgjirrige nuânse. Ynstee fan allinich de binêre protokolpoarte op te jaan, spesifisearje wy it folsleine iepenbiere adres fan it proses ynklusyf de hostnamme. Dit is nedich sadat de klusterknooppunten witte hoe't se mei elkoar ferbine kinne. It is in min idee om 0.0.0.0 te brûken as it advertise_uri-adres; it moat in ekstern IP-adres wêze, net in socket-bining. Sûnder it sil neat wurkje, dus Cartridge lit jo gewoan gjin knooppunt mei de ferkearde advertise_uri lansearje.

No't de konfiguraasje klear is, kinne jo de prosessen begjinne. Sûnt in reguliere systemd ienheid net tastean mear as ien proses om te begjinnen, wurde applikaasjes op de Cartridge ynstallearre troch de saneamde. ynstantiearre ienheden dy't sa wurkje:

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

Yn 'e konfiguraasje hawwe wy de HTTP-poarte opjûn wêrop Cartridge de webynterface tsjinnet - 8080. Litte wy nei it gean en sjoch ris:

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Wy sjogge dat hoewol de prosessen rinne, se noch net konfigureare binne. De cartridge wit noch net wa't mei wa replikearje moat en kin net sels in beslút nimme, dus it wachtet op ús aksjes. Mar wy hawwe net folle kar: it libben fan in nij kluster begjint mei de konfiguraasje fan it earste knooppunt. Dan sille wy de oaren tafoegje oan it kluster, har rollen tawize, en op dit punt kin de ynset wurde beskôge as suksesfol foltôge.

Litte wy in glês fan jo favorite drankje skinke en ûntspanne nei in lange wurkwike. De applikaasje kin brûkt wurde.

Tarantool Cartridge: sharding in Lua backend yn trije rigels

Resultaten

Wat binne de resultaten? Besykje it, brûk it, lit feedback, meitsje kaartsjes op Github.

referinsjes

[1] Tarantool » 2.2 » Referinsje » Rocks referinsje » Module vshard

[2] Hoe't wy de kearn fan 'e ynvestearringsbedriuw fan Alfa-Bank ymplementeare basearre op Tarantool

[3] Nije generaasje billing-arsjitektuer: transformaasje mei de oergong nei Tarantool

[4] SWIM - kluster konstruksje protokol

[5] GitHub - tarantool/cartridge-cli

[6] GitHub - tarantool / cartridge

Boarne: www.habr.com

Add a comment