Fimm nemendur og þrír dreifðu lykilvirðisverslanir

Eða hvernig við skrifuðum C++ bókasafn viðskiptavinar fyrir ZooKeeper, etcd og Consul KV

Í heimi dreifðra kerfa eru nokkur dæmigerð verkefni: geyma upplýsingar um samsetningu klasans, stjórna uppsetningu hnúta, greina gallaða hnúta, velja leiðtoga og aðrir. Til að leysa þessi vandamál hafa verið búin til sérstök dreifð kerfi - samræmingarþjónusta. Nú munum við hafa áhuga á þremur þeirra: ZooKeeper, etcd og Consul. Af allri ríkulegri virkni Consul munum við einbeita okkur að Consul KV.

Fimm nemendur og þrír dreifðu lykilvirðisverslanir

Í meginatriðum eru öll þessi kerfi bilunarþolin, línugeranleg lykilgildageymslur. Þótt gagnalíkön þeirra hafi verulegan mun, sem við munum ræða síðar, leysa þau sömu hagnýtu vandamálin. Augljóslega er hvert forrit sem notar samhæfingarþjónustuna bundið við eitt þeirra, sem getur leitt til þess að þurfa að styðja við nokkur kerfi í einni gagnaver sem leysa sömu vandamálin fyrir mismunandi forrit.

Hugmyndin um að leysa þetta vandamál átti uppruna sinn í ástralskri ráðgjafarstofu og það kom í hlut okkar, litlu teymi nemenda, að hrinda því í framkvæmd, sem ég ætla að tala um.

Okkur tókst að búa til bókasafn sem veitir sameiginlegt viðmót til að vinna með ZooKeeper, etcd og Consul KV. Bókasafnið er skrifað í C++ en áform eru um að flytja það yfir á önnur tungumál.

Gagnalíkön

Til að þróa sameiginlegt viðmót fyrir þrjú mismunandi kerfi þarftu að skilja hvað þau eiga sameiginlegt og hvernig þau eru ólík. Við skulum reikna það út.

Dýragarðsvörður

Fimm nemendur og þrír dreifðu lykilvirðisverslanir

Lyklarnir eru skipulagðir í tré og kallast hnútar. Í samræmi við það, fyrir hnút geturðu fengið lista yfir börn hans. Aðgerðirnar við að búa til znode (búa til) og breyta gildi (setData) eru aðskildar: aðeins núverandi lykla er hægt að lesa og breyta. Hægt er að tengja úr við aðgerðirnar að athuga tilvist hnúts, lesa gildi og fá börn. Watch er einu sinni kveikja sem ræsir þegar útgáfa samsvarandi gagna á þjóninum breytist. Skammlausir hnútar eru notaðir til að greina bilanir. Þau eru bundin við fund viðskiptavinarins sem bjó þau til. Þegar viðskiptavinur lokar lotu eða hættir að tilkynna ZooKeeper um tilvist hennar er þessum hnútum sjálfkrafa eytt. Einföld viðskipti eru studd - mengi aðgerða sem annað hvort heppnast allar eða mistakast ef það er ekki mögulegt fyrir að minnsta kosti eina þeirra.

osfrv

Fimm nemendur og þrír dreifðu lykilvirðisverslanir

Hönnuðir þessa kerfis voru greinilega innblásnir af ZooKeeper og gerðu því allt öðruvísi. Það er ekkert stigveldi lykla, en þeir mynda orðafræðilega raðað mengi. Þú getur fengið eða eytt öllum lyklum sem tilheyra ákveðnu sviði. Þessi uppbygging kann að virðast undarleg, en hún er í raun mjög svipmikil og hægt er að líkja eftir stigveldisskoðun í gegnum hana.

etcd er ekki með staðlaða bera saman og stilla aðgerð, en það hefur eitthvað betra: viðskipti. Auðvitað eru þau til í öllum þremur kerfunum, en etcd viðskipti eru sérstaklega góð. Þau samanstanda af þremur blokkum: athuga, árangur, bilun. Fyrsta blokkin inniheldur sett af skilyrðum, annar og þriðji - aðgerðir. Viðskiptin eru framkvæmd í lotukerfinu. Ef öll skilyrði eru uppfyllt, þá er árangursblokkinn keyrður, annars er bilunarblokkinn keyrður. Í API 3.3 geta árangurs- og bilunarblokkir innihaldið hreiður færslur. Það er, það er hægt að framkvæma frumeindafræðilega skilyrta smíði af nánast handahófskenndu hreiðurstigi. Þú getur lært meira um hvað athuganir og aðgerðir eru til úr skjöl.

Úr eru til hér líka, þó þau séu aðeins flóknari og endurnotanleg. Það er, eftir að hafa sett upp úr á lykilsviði færðu allar uppfærslur á þessu sviði þar til þú hættir við úrið, en ekki bara þá fyrstu. Í etcd eru hliðstæður ZooKeeper viðskiptavinalota leigusamningar.

Ræðismaður K.V.

Það er heldur engin ströng stigveldisskipan hér, en Consul getur búið til það útlit að það sé til: þú getur fengið og eytt öllum lyklum með tilgreindu forskeytinu, það er að segja að vinna með „undirtré“ lykilsins. Slíkar fyrirspurnir eru kallaðar endurkvæmar. Að auki getur Consul aðeins valið lykla sem innihalda ekki tilgreindan staf á eftir forskeytinu, sem samsvarar því að fá strax „börn“. En það er þess virði að muna að þetta er einmitt útlit stigveldisskipulags: það er alveg hægt að búa til lykil ef foreldri hans er ekki til eða eyða lykil sem á börn, á meðan börnin verða áfram geymd í kerfinu.

Fimm nemendur og þrír dreifðu lykilvirðisverslanir
Í stað klukka hefur Consul hindrar HTTP beiðnir. Í meginatriðum eru þetta venjuleg símtöl í gagnalestraraðferðina, þar sem, ásamt öðrum breytum, er síðasta þekkta útgáfan af gögnunum tilgreind. Ef núverandi útgáfa af samsvarandi gögnum á þjóninum er meiri en tilgreind er svarið skilað strax, annars - þegar gildið breytist. Það eru líka lotur sem hægt er að tengja við lykla hvenær sem er. Það er athyglisvert að ólíkt etcd og ZooKeeper, þar sem eyðing lota leiðir til eyðingar á tengdum lyklum, þá er til hamur þar sem lotan er einfaldlega aftengd þeim. Laus viðskipti, án útibúa, en með alls kyns ávísunum.

Að setja þetta allt saman

ZooKeeper er með strangasta gagnalíkanið. Ekki er hægt að líkja eftir svipmiklum sviðsfyrirspurnum sem eru tiltækar í etcd, hvorki í ZooKeeper né Consul. Þegar við reyndum að fella það besta úr allri þjónustunni, enduðum við með viðmót sem jafngildir næstum ZooKeeper viðmótinu með eftirfarandi mikilvægum undantekningum:

  • röð, ílát og TTL hnúta ekki stutt
  • ACL eru ekki studd
  • settaðferðin býr til lykil ef hann er ekki til (í ZK skilar setData villu í þessu tilfelli)
  • sett og cas aðferðir eru aðskildar (í ZK eru þær í meginatriðum sami hluturinn)
  • eyðingaraðferðin eyðir hnút ásamt undirtré hans (í ZK skilar eyða villu ef hnúturinn er með börn)
  • Fyrir hvern lykil er aðeins ein útgáfa - gildisútgáfan (í ZK þeir eru þrír)

Höfnun á raðhnútum er vegna þess að etcd og Consul eru ekki með innbyggðan stuðning fyrir þá og notandinn getur auðveldlega útfært þá ofan á bókasafnsviðmótið sem myndast.

Að innleiða svipaða hegðun og ZooKeeper þegar hornpunkti er eytt myndi krefjast þess að viðhalda sérstökum barnateljara fyrir hvern lykil í etcd og Consul. Þar sem við reyndum að forðast að geyma meta upplýsingar var ákveðið að eyða öllu undirtrénu.

Fínleiki framkvæmdar

Við skulum skoða nánar nokkra þætti við að útfæra bókasafnsviðmótið í mismunandi kerfum.

Stigveldi í etcd

Að viðhalda stigveldisskoðun í etcd reyndist vera eitt áhugaverðasta verkefnið. Sviðsfyrirspurnir gera það auðvelt að sækja lista yfir lykla með tilteknu forskeyti. Til dæmis, ef þú þarft allt sem byrjar á "/foo", þú ert að biðja um svið ["/foo", "/fop"). En þetta myndi skila öllu undirtré lykilsins, sem gæti ekki verið ásættanlegt ef undirtréð er stórt. Í fyrstu ætluðum við að nota lykilþýðingarkerfi, útfært í zetcd. Það felur í sér að bæta við einu bæti í upphafi lyklins, jafnt og dýpt hnútsins í trénu. Leyfðu mér að gefa þér dæmi.

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

Fáðu síðan öll næstu börn lykilsins "/foo" mögulegt með því að biðja um svið ["u02/foo/", "u02/foo0"). Já, í ASCII "0" stendur rétt á eftir "/".

En hvernig á að framkvæma að fjarlægja hornpunkt í þessu tilfelli? Það kemur í ljós að þú þarft að eyða öllum sviðum af gerðinni ["uXX/foo/", "uXX/foo0") fyrir XX frá 01 til FF. Og svo rákumst við á takmörkun aðgerðafjölda innan einnar færslu.

Í kjölfarið var fundið upp einfalt lyklabreytingarkerfi sem gerði það mögulegt að útfæra á áhrifaríkan hátt bæði að eyða lykli og fá lista yfir börn. Það er nóg að bæta við sérstökum karakter fyrir síðasta táknið. Til dæmis:

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

Síðan er lyklinum eytt "/very" breytist í eyðingu "/u00very" og svið ["/very/", "/very0"), og fá öll börn - í beiðni um lykla af sviðinu ["/very/u00", "/very/u01").

Fjarlægir lykil í ZooKeeper

Eins og ég hef áður nefnt, í ZooKeeper er ekki hægt að eyða hnút ef hann á börn. Við viljum eyða lyklinum ásamt undirtrénu. Hvað ætti ég að gera? Við gerum þetta með bjartsýni. Í fyrsta lagi förum við endurkvæmt yfir undirtréð og fáum börn hvers hornpunkts með sérstakri fyrirspurn. Síðan byggjum við upp færslu sem reynir að eyða öllum hnútum undirtrésins í réttri röð. Auðvitað geta breytingar orðið á milli þess að lesa undirtré og eyða því. Í þessu tilviki munu viðskiptin mistakast. Þar að auki getur undirtréð breyst meðan á lestrinum stendur. Beiðni um börn næsta hnút getur skilað villu ef td þessum hnút hefur þegar verið eytt. Í báðum tilfellum endurtökum við allt ferlið aftur.

Þessi nálgun gerir það að verkum að það er mjög ómarkvisst að eyða lykli ef hann á börn, og enn frekar ef forritið heldur áfram að vinna með undirtrénu, eyðir og býr til lykla. Hins vegar gerði þetta okkur kleift að forðast að torvelda innleiðingu annarra aðferða í etcd og Consul.

gerist í ZooKeeper

Í ZooKeeper eru sérstakar aðferðir sem vinna með trébygginguna (create, delete, getChildren) og sem vinna með gögn í hnútum (setData, getData) Þar að auki hafa allar aðferðir strangar forsendur: create mun skila villu ef hnúturinn hefur þegar verið búið til, eytt eða setData – ef það er ekki þegar til. Okkur vantaði fasta aðferð sem hægt er að kalla án þess að hugsa um tilvist lykils.

Einn valkostur er að taka bjartsýni, eins og með eyðingu. Athugaðu hvort hnútur sé til. Ef það er til skaltu hringja í setData, annars búa til. Ef síðasta aðferðin skilaði villu skaltu endurtaka hana aftur. Það fyrsta sem þarf að hafa í huga er að tilvistarprófið er tilgangslaust. Þú getur strax hringt í create. Árangursrík uppfylling þýðir að hnúturinn var ekki til og hann var búinn til. Annars mun create skila viðeigandi villu, eftir það þarftu að hringja í setData. Auðvitað, á milli símtala, gæti hornpunkti verið eytt með samkeppnissímtali og setData myndi einnig skila villu. Í þessu tilfelli geturðu gert allt aftur, en er það þess virði?

Ef báðar aðferðirnar skila villu, þá vitum við fyrir víst að keppandi eyðing átti sér stað. Við skulum ímynda okkur að þessi eyðing hafi átt sér stað eftir að hringt var sett. Þá er sú merking sem við erum að reyna að koma á þegar eytt. Þetta þýðir að við getum gert ráð fyrir að settið hafi verið keyrt með góðum árangri, jafnvel þótt ekkert hafi í raun verið skrifað.

Fleiri tæknilegar upplýsingar

Í þessum kafla munum við taka hlé frá dreifðum kerfum og tala um kóðun.
Ein helsta krafa viðskiptavinarins var þvert á vettvang: að minnsta kosti ein af þjónustunum verður að vera studd á Linux, MacOS og Windows. Upphaflega þróuðum við aðeins fyrir Linux og byrjuðum að prófa á öðrum kerfum síðar. Þetta olli miklum vandræðum sem um tíma var algjörlega óljóst hvernig ætti að nálgast. Þess vegna eru allar þrjár samhæfingarþjónusturnar nú studdar á Linux og MacOS, en aðeins Consul KV er studd á Windows.

Strax í upphafi reyndum við að nota tilbúin bókasöfn til að fá aðgang að þjónustu. Í tilviki ZooKeeper féll valið á ZooKeeper C++, sem á endanum tókst ekki að safna saman á Windows. Þetta kemur hins vegar ekki á óvart: bókasafnið er staðsett sem linux eingöngu. Fyrir ræðismann var eini kosturinn ppconsul. Það þurfti að bæta við stuðningi fundur и viðskipti. Fyrir etcd fannst ekki fullbúið bókasafn sem styður nýjustu útgáfu samskiptareglunnar, svo við einfaldlega myndaður grpc viðskiptavinur.

Innblásin af ósamstilltu viðmóti ZooKeeper C++ bókasafnsins ákváðum við að innleiða einnig ósamstillt viðmót. ZooKeeper C++ notar frumstæður framtíðar/lofa fyrir þetta. Í STL eru þau því miður útfærð mjög hóflega. Til dæmis, nei þá aðferð, sem beitir samþykktu fallinu á niðurstöðu framtíðarinnar þegar hún verður tiltæk. Í okkar tilviki er slík aðferð nauðsynleg til að breyta niðurstöðunni í snið bókasafnsins okkar. Til að komast hjá þessu vandamáli þurftum við að innleiða okkar eigin einfalda þráðasafn, þar sem að beiðni viðskiptavinarins gátum við ekki notað þung þriðju aðila bókasöfn eins og Boost.

Útfærslan okkar þá virkar svona. Þegar hringt er í það myndast viðbótarloforð/framtíðarpar. Nýja framtíðinni er skilað og sú sem er liðin er sett ásamt samsvarandi aðgerð og viðbótarloforð í biðröðina. Þráður úr hópnum velur nokkra framtíð úr röðinni og skoðar þær með wait_for. Þegar niðurstaða verður tiltæk er samsvarandi fall kallað og skilagildi hennar er sent til loforðið.

Við notuðum sama þráðasafn til að framkvæma fyrirspurnir til etcd og Consul. Þetta þýðir að hægt er að nálgast undirliggjandi bókasöfn með mörgum mismunandi þráðum. ppconsul er ekki þráð öruggt, svo símtöl í það eru varin með læsingum.
Þú getur unnið með grpc úr mörgum þráðum, en það eru fíngerðir. Í etcd eru klukkur útfærðar í gegnum grpc strauma. Þetta eru tvíátta rásir fyrir skilaboð af ákveðinni gerð. Bókasafnið býr til einn þráð fyrir allar klukkur og einn þráð sem vinnur úr skilaboðum sem berast. Svo grpc bannar samhliða skrif til að streyma. Þetta þýðir að þegar þú frumstillir eða eyðir úri verður þú að bíða þar til fyrri beiðni hefur lokið við sendingu áður en þú sendir þá næstu. Við notum til samstillingar skilyrtar breytur.

Samtals

Sjá fyrir þér: liboffkv.

Okkar lið: Raed Romanov, Ivan Glushenkov, Dmitry Kamaldinov, Victor Krapivensky, Vitaly Ivanin.

Heimild: www.habr.com

Bæta við athugasemd