Pieci studenti un trīs izplatīti atslēgu vērtību veikali

Vai arī kā mēs izveidojām klienta C++ bibliotēku ZooKeeper, etcd un Consul KV

SadalÄ«to sistēmu pasaulē ir vairāki tipiski uzdevumi: informācijas glabāŔana par klastera sastāvu, mezglu konfigurācijas pārvaldÄ«ba, bojātu mezglu noteikÅ”ana, lÄ«dera izvēle cits. Å o problēmu risināŔanai ir izveidotas speciālas izkliedētās sistēmas - koordinācijas dienesti. Tagad mÅ«s interesēs trÄ«s no tiem: ZooKeeper, etcd un Consul. No visas bagātÄ«gās Consul funkcionalitātes mēs koncentrēsimies uz Consul KV.

Pieci studenti un trīs izplatīti atslēgu vērtību veikali

BÅ«tÄ«bā visas Ŕīs sistēmas ir pret defektiem izturÄ«gas, linearizējamas atslēgu vērtÄ«bu glabātuves. Lai gan to datu modeļiem ir bÅ«tiskas atŔķirÄ«bas, par kurām mēs runāsim vēlāk, tie atrisina tās paÅ”as praktiskās problēmas. AcÄ«mredzot katra lietojumprogramma, kas izmanto koordinācijas pakalpojumu, ir piesaistÄ«ta vienai no tām, kas var radÄ«t nepiecieÅ”amÄ«bu atbalstÄ«t vairākas sistēmas vienā datu centrā, kas atrisina vienas un tās paÅ”as problēmas dažādām lietojumprogrammām.

Ideja atrisināt Å”o problēmu radās Austrālijas konsultāciju aÄ£entÅ«rā, un mēs, neliela studentu komanda, nācās to Ä«stenot, par ko es arÄ« runāŔu.

Mums izdevās izveidot bibliotēku, kas nodroÅ”ina kopÄ«gu saskarni darbam ar ZooKeeper, etcd un Consul KV. Bibliotēka ir rakstÄ«ta C++ valodā, taču tiek plānots to pārnest uz citām valodām.

Datu modeļi

Lai izstrādātu kopÄ«gu saskarni trim dažādām sistēmām, jums ir jāsaprot, kas tām ir kopÄ«gs un kā tās atŔķiras. Izdomāsim.

Zoodārza uzraugs

Pieci studenti un trīs izplatīti atslēgu vērtību veikali

Atslēgas ir sakārtotas kokā un tiek sauktas par mezgliem. AttiecÄ«gi mezglam varat iegÅ«t tā bērnu sarakstu. Znode izveides (create) un vērtÄ«bas maiņas (setData) darbÄ«bas ir atdalÄ«tas: var lasÄ«t un mainÄ«t tikai esoŔās atslēgas. Pulksteņus var pievienot mezgla esamÄ«bas pārbaudes, vērtÄ«bas nolasÄ«Å”anas un bērnu iegÅ«Å”anas darbÄ«bām. Watch ir vienreizējs aktivizētājs, kas tiek aktivizēts, kad serverÄ« mainās atbilstoÅ”o datu versija. Lai noteiktu kļūmes, tiek izmantoti Ä«slaicÄ«gi mezgli. Tie ir piesaistÄ«ti klienta sesijai, kas tos izveidoja. Kad klients aizver sesiju vai pārtrauc paziņot ZooKeeper par tās esamÄ«bu, Å”ie mezgli tiek automātiski dzēsti. Tiek atbalstÄ«tas vienkārÅ”as transakcijas ā€“ darbÄ«bu kopums, kuras visas izdodas vai neizdodas, ja tas nav iespējams vismaz vienam no tiem.

utt

Pieci studenti un trīs izplatīti atslēgu vērtību veikali

Å Ä«s sistēmas izstrādātājus nepārprotami iedvesmoja ZooKeeper, un tāpēc viņi visu darÄ«ja savādāk. Atslēgām nav hierarhijas, bet tās veido leksikogrāfiski sakārtotu kopu. Varat iegÅ«t vai dzēst visas atslēgas, kas pieder noteiktam diapazonam. Å Ä« struktÅ«ra var Ŕķist dÄ«vaina, taču patiesÄ«bā tā ir ļoti izteiksmÄ«ga, un caur to var viegli lÄ«dzināties hierarhiskam skatÄ«jumam.

etcd nav standarta salÄ«dzināŔanas un iestatÄ«Å”anas darbÄ«bas, taču tai ir kaut kas labāks: transakcijas. Protams, tie pastāv visās trÄ«s sistēmās, bet etcd darÄ«jumi ir Ä«paÅ”i labi. Tie sastāv no trim blokiem: pārbaude, veiksme, neveiksme. Pirmajā blokā ir nosacÄ«jumu kopums, otrajā un treÅ”ajā - darbÄ«bas. DarÄ«jums tiek izpildÄ«ts atomiski. Ja visi nosacÄ«jumi ir patiesi, tad tiek izpildÄ«ts veiksmes bloks, pretējā gadÄ«jumā tiek izpildÄ«ts neveiksmju bloks. API 3.3 veiksmes un neveiksmes blokos var bÅ«t ligzdotas transakcijas. Tas ir, ir iespējams atomiski izpildÄ«t gandrÄ«z patvaļīga ligzdoÅ”anas lÄ«meņa nosacÄ«juma konstrukcijas. Varat uzzināt vairāk par to, no kā tiek veiktas pārbaudes un darbÄ«bas dokumentācija.

Pulksteņi pastāv arÄ« Å”eit, lai gan tie ir nedaudz sarežģītāki un ir atkārtoti lietojami. Tas nozÄ«mē, ka pēc pulksteņa instalÄ“Å”anas atslēgu diapazonā jÅ«s saņemsit visus Ŕī diapazona atjauninājumus, lÄ«dz atcelsit pulksteni, nevis tikai pirmo. Programmā etcd ZooKeeper klientu sesiju analogs ir noma.

Konsuls K.V.

Å eit nav arÄ« stingras hierarhiskas struktÅ«ras, taču konsuls var radÄ«t izskatu, ka tā pastāv: jÅ«s varat iegÅ«t un izdzēst visas atslēgas ar norādÄ«to prefiksu, tas ir, strādāt ar atslēgas ā€œapakÅ”kokuā€. Šādus vaicājumus sauc par rekursÄ«viem. Turklāt konsuls var atlasÄ«t tikai atslēgas, kurās pēc prefiksa nav norādÄ«tā rakstzÄ«me, kas atbilst tÅ«lÄ«tējai ā€œbērnuā€ iegÅ«Å”anai. Bet ir vērts atcerēties, ka tas ir tieÅ”i hierarhiskas struktÅ«ras izskats: ir pilnÄ«gi iespējams izveidot atslēgu, ja tās vecāka nav, vai izdzēst atslēgu, kurai ir bērni, kamēr bērni turpinās saglabāties sistēmā.

Pieci studenti un trīs izplatīti atslēgu vērtību veikali
Pulksteņu vietā konsuls bloķē HTTP pieprasÄ«jumus. BÅ«tÄ«bā tie ir parastie datu nolasÄ«Å”anas metodes izsaukumi, kuriem kopā ar citiem parametriem tiek norādÄ«ta pēdējā zināmā datu versija. Ja atbilstoÅ”o datu paÅ”reizējā versija serverÄ« ir lielāka par norādÄ«to, atbilde tiek atgriezta nekavējoties, pretējā gadÄ«jumā - mainoties vērtÄ«bai. Ir arÄ« sesijas, kuras jebkurā laikā var pievienot atslēgām. Ir vērts atzÄ«mēt, ka atŔķirÄ«bā no etcd un ZooKeeper, kur sesiju dzÄ“Å”ana noved pie saistÄ«to atslēgu dzÄ“Å”anas, ir režīms, kurā sesija tiek vienkārÅ”i atsaistÄ«ta no tām. Pieejams darÄ«jumiem, bez zariem, bet ar visādiem čekiem.

Saliekot to visu kopā

ZooKeeper ir visstingrākais datu modelis. IzteiksmÄ«gos diapazona vaicājumus, kas pieejami programmā etcd, nevar efektÄ«vi emulēt ne ZooKeeper, ne Consul. Mēģinot iekļaut labāko no visiem pakalpojumiem, mēs ieguvām saskarni, kas ir gandrÄ«z lÄ«dzvērtÄ«ga ZooKeeper saskarnei ar Ŕādiem bÅ«tiskiem izņēmumiem:

  • secÄ«ba, konteiners un TTL mezgli nav atbalstÄ«ts
  • ACL netiek atbalstÄ«ti
  • iestatÄ«Å”anas metode izveido atslēgu, ja tā neeksistē (ZK gadÄ«jumā setData atgriež kļūdu)
  • set un cas metodes ir atdalÄ«tas (ZK tās bÅ«tÄ«bā ir viena un tā pati)
  • dzÄ“Å”anas metode izdzÄ“Å” mezglu kopā ar tā apakÅ”koku (ZK gadÄ«jumā delete atgriež kļūdu, ja mezglam ir bērni)
  • Katrai atslēgai ir tikai viena versija - vērtÄ«bas versija (ZK tādi ir trÄ«s)

SecÄ«go mezglu noraidÄ«Å”ana ir saistÄ«ta ar faktu, ka etcd un Consul tiem nav iebÅ«vēta atbalsta, un lietotājs tos var viegli ieviest iegÅ«tajā bibliotēkas saskarnē.

IevieÅ”ot ZooKeeper lÄ«dzÄ«gu rÄ«cÄ«bu, dzÄ“Å”ot virsotni, katrai atslēgai ir jāuztur atseviŔķs bērnskaitlis programmā etcd un Consul. Tā kā mēs centāmies izvairÄ«ties no meta informācijas glabāŔanas, tika nolemts izdzēst visu apakÅ”koku.

ÄŖstenoÅ”anas smalkumi

SÄ«kāk apskatÄ«sim dažus bibliotēkas saskarnes ievieÅ”anas aspektus dažādās sistēmās.

Hierarhija utt

Hierarhiskā skatÄ«juma uzturÄ“Å”ana programmā etcd izrādÄ«jās viens no interesantākajiem uzdevumiem. Diapazona vaicājumi ļauj viegli izgÅ«t atslēgu sarakstu ar noteiktu prefiksu. Piemēram, ja jums ir nepiecieÅ”ams viss, kas sākas ar "/foo", jÅ«s lÅ«dzat diapazonu ["/foo", "/fop"). Bet tas atgrieztu visu atslēgas apakÅ”koku, kas var nebÅ«t pieņemams, ja apakÅ”koks ir liels. Sākumā mēs plānojām izmantot galveno tulkoÅ”anas mehānismu, ieviests zetcd. Tas ietver viena baita pievienoÅ”anu atslēgas sākumā, kas ir vienāds ar mezgla dziļumu kokā. Ä»aujiet man sniegt jums piemēru.

"/foo" -> "u01/foo"
"/foo/bar" -> "u02/foo/bar"

Pēc tam iegūstiet visus tūlītējos atslēgas bērnus "/foo" iespējams, pieprasot diapazonu ["u02/foo/", "u02/foo0"). Jā, ASCII formātā "0" stāv uzreiz pēc "/".

Bet kā Å”ajā gadÄ«jumā Ä«stenot virsotnes noņemÅ”anu? Izrādās, ka jums ir jāizdzÄ“Å” visi veida diapazoni ["uXX/foo/", "uXX/foo0") XX no 01 lÄ«dz FF. Un tad mēs saskrējāmies operāciju skaita ierobežojums viena darÄ«juma ietvaros.

Rezultātā tika izgudrota vienkārÅ”a atslēgu konvertÄ“Å”anas sistēma, kas ļāva efektÄ«vi realizēt gan atslēgas dzÄ“Å”anu, gan bērnu saraksta iegÅ«Å”anu. Pietiek pirms pēdējā marÄ·iera pievienot Ä«paÅ”u rakstzÄ«mi. Piemēram:

"/very" -> "/u00very"
"/very/long" -> "/very/u00long"
"/very/long/path" -> "/very/long/u00path"

Pēc tam izdzÄ“Å”ot atslēgu "/very" pārvērÅ”as par dzÄ“Å”anu "/u00very" un diapazons ["/very/", "/very0"), un saņemt visus bērnus - pieprasot atslēgas no diapazona ["/very/u00", "/very/u01").

Atslēgas noņemÅ”ana programmā ZooKeeper

Kā jau minēju, ZooKeeper nevar izdzēst mezglu, ja tam ir bērni. Mēs vēlamies dzēst atslēgu kopā ar apakÅ”koku. Ko man darÄ«t? Mēs to darām ar optimismu. Pirmkārt, mēs rekursÄ«vi Ŕķērsojam apakÅ”koku, iegÅ«stot katras virsotnes atvasinājumus ar atseviŔķu vaicājumu. Pēc tam mēs izveidojam darÄ«jumu, kas mēģina dzēst visus apakÅ”koka mezglus pareizajā secÄ«bā. Protams, starp apakÅ”koka nolasÄ«Å”anu un dzÄ“Å”anu var notikt izmaiņas. Å ajā gadÄ«jumā darÄ«jums neizdosies. Turklāt apakÅ”koks var mainÄ«ties lasÄ«Å”anas procesā. PieprasÄ«jums par nākamā mezgla bērniem var atgriezt kļūdu, ja, piemēram, Å”is mezgls jau ir dzēsts. Abos gadÄ«jumos mēs atkārtojam visu procesu vēlreiz.

Å Ä« pieeja padara atslēgas dzÄ“Å”anu ļoti neefektÄ«vu, ja tai ir bērni, un vēl jo vairāk, ja lietojumprogramma turpina strādāt ar apakÅ”koku, dzÄ“Å”ot un veidojot atslēgas. Tomēr tas ļāva mums izvairÄ«ties no citu metožu ievieÅ”anas sarežģījumiem etcd un Consul.

iestatīts ZooKeeper

Programmā ZooKeeper ir atseviŔķas metodes, kas darbojas ar koka struktÅ«ru (create, delete, getChildren) un kas darbojas ar datiem mezglos (setData, getData). Turklāt visām metodēm ir stingri priekÅ”noteikumi: Create atgriezÄ«s kļūdu, ja mezgls jau ir ir izveidots, dzēst vai setData ā€“ ja tas vēl neeksistē. Mums bija nepiecieÅ”ama noteikta metode, kuru var izsaukt, nedomājot par atslēgas klātbÅ«tni.

Viena iespēja ir izvēlēties optimistisku pieeju, tāpat kā ar svÄ«troÅ”anu. Pārbaudiet, vai mezgls pastāv. Ja tāda ir, izsauciet setData, pretējā gadÄ«jumā izveidojiet. Ja pēdējā metode radÄ«ja kļūdu, atkārtojiet to vēlreiz. Vispirms jāatzÄ«mē, ka eksistences pārbaude ir bezjēdzÄ«ga. JÅ«s varat nekavējoties piezvanÄ«t izveidot. VeiksmÄ«ga pabeigÅ”ana nozÄ«mēs, ka mezgls neeksistēja un tas tika izveidots. Pretējā gadÄ«jumā Create atgriezÄ«s atbilstoÅ”o kļūdu, pēc kuras jums jāizsauc setData. Protams, starp zvaniem virsotne var tikt izdzēsta ar konkurējoÅ”u zvanu, un setData arÄ« atgrieztu kļūdu. Å ajā gadÄ«jumā jÅ«s varat darÄ«t visu no jauna, bet vai tas ir tā vērts?

Ja abas metodes atgriež kļūdu, mēs droÅ”i zinām, ka ir notikusi konkurējoÅ”a dzÄ“Å”ana. Iedomāsimies, ka Ŕī dzÄ“Å”ana notika pēc kopas izsaukÅ”anas. Tad jebkura nozÄ«me, ko mēs cenÅ”amies noteikt, jau ir izdzēsta. Tas nozÄ«mē, ka mēs varam pieņemt, ka kopa tika veiksmÄ«gi izpildÄ«ta, pat ja patiesÄ«bā nekas netika uzrakstÄ«ts.

Sīkāka tehniskā informācija

Å ajā sadaļā mēs atpÅ«tÄ«simies no izplatÄ«tajām sistēmām un runāsim par kodÄ“Å”anu.
Viena no klienta galvenajām prasībām bija starpplatformu sistēma: vismaz vienam no pakalpojumiem jābūt atbalstītiem operētājsistēmās Linux, MacOS un Windows. Sākotnēji mēs izstrādājām tikai Linux, un vēlāk sākām testēt citās sistēmās. Tas radīja daudz problēmu, kurām kādu laiku bija pilnīgi neskaidrs, kā pieiet. Rezultātā visi trīs koordinācijas pakalpojumi tagad tiek atbalstīti operētājsistēmās Linux un MacOS, savukārt operētājsistēmā Windows tiek atbalstīts tikai Consul KV.

No paÅ”a sākuma mēs centāmies izmantot gatavas bibliotēkas, lai piekļūtu pakalpojumiem. ZooKeeper gadÄ«jumā izvēle krita ZooKeeper C++, kuru galu galā neizdevās kompilēt operētājsistēmā Windows. Tomēr tas nav pārsteidzoÅ”i: bibliotēka ir novietota tikai Linux. Konsulam vienÄ«gā iespēja bija ppkonsuls. Tam bija jāpievieno atbalsts sesijas Šø darÄ«jumiem. AttiecÄ«bā uz etcd netika atrasta pilnvērtÄ«ga bibliotēka, kas atbalsta jaunāko protokola versiju, tāpēc mēs vienkārÅ”i Ä£enerēts grpc klients.

Iedvesmojoties no ZooKeeper C++ bibliotēkas asinhronās saskarnes, mēs nolēmām ieviest arÄ« asinhrono saskarni. ZooKeeper C++ Å”im nolÅ«kam izmanto nākotnes/solÄ«jumu primitÄ«vus. STL, diemžēl, tie tiek Ä«stenoti ļoti pieticÄ«gi. Piemēram, nē tad metode, kas piemēro nodoto funkciju nākotnes rezultātam, kad tas kļūst pieejams. MÅ«su gadÄ«jumā Ŕāda metode ir nepiecieÅ”ama, lai pārvērstu rezultātu mÅ«su bibliotēkas formātā. Lai apietu Å”o problēmu, mums bija jāievieÅ” savs vienkārÅ”s pavedienu kopums, jo pēc klienta pieprasÄ«juma mēs nevarējām izmantot smagas treÅ”o puÅ”u bibliotēkas, piemēram, Boost.

MÅ«su toreizējā ievieÅ”ana darbojas Ŕādi. Izsaucot, tiek izveidots papildu solÄ«jums/nākotnes pāris. Jaunā nākotne tiek atgriezta, un nodotā ā€‹ā€‹tiek ievietota rindā kopā ar atbilstoÅ”o funkciju un papildu solÄ«jumu. Pavediens no kopas atlasa vairākus nākotnes lÄ«gumus no rindas un aptauj tos, izmantojot gaidÄ«t_for. Kad rezultāts kļūst pieejams, tiek izsaukta atbilstoŔā funkcija un tās atgrieÅ”anas vērtÄ«ba tiek nodota solÄ«jumam.

Mēs izmantojām to paÅ”u pavedienu kopu, lai izpildÄ«tu vaicājumus etcd un Consul. Tas nozÄ«mē, ka pamatā esoÅ”ajām bibliotēkām var piekļūt, izmantojot vairākus dažādus pavedienus. ppconsul nav pavedienu droÅ”s, tāpēc zvani uz to ir aizsargāti ar slēdzenēm.
JÅ«s varat strādāt ar grpc no vairākiem pavedieniem, taču ir arÄ« smalkumi. In etcd pulksteņi tiek ieviesti, izmantojot grpc straumes. Tie ir divvirzienu kanāli noteikta veida ziņojumiem. Bibliotēka izveido vienu pavedienu visiem pulksteņiem un vienu pavedienu, kas apstrādā ienākoÅ”os ziņojumus. Tātad grpc aizliedz paralēlu rakstÄ«Å”anu straumē. Tas nozÄ«mē, ka, inicializējot vai dzÄ“Å”ot pulksteni, pirms nākamā pieprasÄ«juma nosÅ«tÄ«Å”anas ir jāgaida, lÄ«dz iepriekŔējā pieprasÄ«juma nosÅ«tÄ«Å”ana ir pabeigta. Mēs izmantojam sinhronizācijai nosacÄ«juma mainÄ«gie.

Kopsavilkums

Skatīt sevi: liboffkv.

MÅ«su komanda: Rēds Romanovs, Ivans GluÅ”enkovs, Dmitrijs Kamaldinovs, Viktors Krapivenskis, Vitālijs Ivanins.

Avots: www.habr.com

Pievieno komentāru