Iminumungkahi kong basahin mo ang transcript ng lecture na "Hadoop. ZooKeeper" mula sa seryeng "Mga pamamaraan para sa distributed processing ng malalaking volume ng data sa Hadoop"
Ano ang ZooKeeper, ang lugar nito sa Hadoop ecosystem. Mga kasinungalingan tungkol sa distributed computing. Diagram ng isang karaniwang ipinamamahaging sistema. Kahirapan sa pag-coordinate ng mga distributed system. Mga karaniwang problema sa koordinasyon. Ang mga prinsipyo sa likod ng disenyo ng ZooKeeper. Modelo ng data ng ZooKeeper. mga flag ng znode. Mga session. Client API. Primitives (configuration, membership ng grupo, simpleng mga kandado, halalan ng pinuno, pag-lock nang walang herd effect). Arkitektura ng ZooKeeper. ZooKeeper DB. ZAB. Humiling ng handler.


Ngayon ay pag-uusapan natin ang tungkol sa ZooKeeper. Ang bagay na ito ay lubhang kapaki-pakinabang. Ito, tulad ng anumang produkto ng Apache Hadoop, ay may logo. Inilalarawan nito ang isang lalaki.
Bago ito, pangunahing napag-usapan namin kung paano mapoproseso ang data doon, kung paano iimbak ito, iyon ay, kung paano ito gamitin kahit papaano at gagana dito kahit papaano. At ngayon gusto kong makipag-usap ng kaunti tungkol sa pagbuo ng mga ipinamamahaging aplikasyon. At ang ZooKeeper ay isa sa mga bagay na nagbibigay-daan sa iyong pasimplehin ang bagay na ito. Ito ay isang uri ng serbisyo na nilayon para sa ilang uri ng koordinasyon ng pakikipag-ugnayan ng mga proseso sa mga distributed system, sa mga distributed application.
Ang pangangailangan para sa mga naturang aplikasyon ay nagiging higit at higit pa araw-araw, iyon ang tungkol sa aming kurso. Sa isang banda, ang MapReduce at ang handa na balangkas na ito ay nagpapahintulot sa iyo na i-level out ang pagiging kumplikado at palayain ang programmer mula sa pagsusulat ng mga primitive tulad ng pakikipag-ugnayan at koordinasyon ng mga proseso. Ngunit sa kabilang banda, walang gumagarantiya na hindi na ito kailangang gawin pa rin. Hindi palaging ganap na pinapalitan ng MapReduce o iba pang handa na mga balangkas ang ilang mga kaso na hindi maipapatupad gamit ito. Kasama ang MapReduce mismo at isang grupo ng iba pang mga proyekto ng Apache, sila, sa katunayan, ay ipinamamahagi din ng mga aplikasyon. At para mapadali ang pagsusulat, sumulat sila ng ZooKeeper.
Tulad ng lahat ng mga application na nauugnay sa Hadoop, ito ay binuo ng Yahoo! Isa na rin itong opisyal na application ng Apache. Hindi ito kasing aktibong binuo gaya ng HBase. Kung pupunta ka sa JIRA HBase, pagkatapos ay araw-araw mayroong isang bungkos ng mga ulat ng bug, isang grupo ng mga panukala upang i-optimize ang isang bagay, ibig sabihin, ang buhay sa proyekto ay patuloy na nangyayari. At ang ZooKeeper, sa isang banda, ay medyo simpleng produkto, at sa kabilang banda, tinitiyak nito ang pagiging maaasahan nito. At ito ay medyo madaling gamitin, kaya naman naging pamantayan ito sa mga aplikasyon sa loob ng Hadoop ecosystem. Kaya naisip ko na magiging kapaki-pakinabang na suriin ito upang maunawaan kung paano ito gumagana at kung paano ito gamitin.

Ito ay isang larawan mula sa ilang lecture namin. Maaari nating sabihin na ito ay orthogonal sa lahat ng ating isinasaalang-alang sa ngayon. At lahat ng ipinahiwatig dito, sa isang antas o iba pa, ay gumagana sa ZooKeeper, ibig sabihin, ito ay isang serbisyo na gumagamit ng lahat ng mga produktong ito. Ang HDFS o ang MapReduce ay hindi sumulat ng kanilang sariling mga katulad na serbisyo na partikular na gagana para sa kanila. Alinsunod dito, ginagamit ang ZooKeeper. At pinapasimple nito ang pag-unlad at ilang bagay na nauugnay sa mga error.

Saan nanggaling ang lahat ng ito? Mukhang naglunsad kami ng dalawang application nang magkatulad sa iba't ibang mga computer, ikinonekta ang mga ito sa isang string o sa isang mesh, at lahat ay gumagana. Ngunit ang problema ay ang Network ay hindi mapagkakatiwalaan, at kung na-sniff mo ang trapiko o tiningnan kung ano ang nangyayari doon sa isang mababang antas, kung paano nakikipag-ugnayan ang mga kliyente sa Network, madalas mong makikita na ang ilang mga packet ay nawala o ipinadala muli. Ito ay hindi para sa wala na ang mga protocol ng TCP ay naimbento, na nagbibigay-daan sa iyong magtatag ng isang tiyak na session at ginagarantiyahan ang paghahatid ng mga mensahe. Ngunit sa anumang kaso, kahit na ang TCP ay hindi palaging makakapagligtas sa iyo. May timeout ang lahat. Ang network ay maaaring bumagsak nang ilang sandali. Baka kumurap lang. At lahat ng ito ay humahantong sa katotohanan na hindi ka makakaasa sa pagiging maaasahan ng Network. Ito ang pangunahing pagkakaiba sa pagsusulat ng mga parallel na application na tumatakbo sa isang computer o sa isang supercomputer, kung saan walang Network, kung saan mayroong mas maaasahang data exchange bus sa memorya. At ito ay isang pangunahing pagkakaiba.
Sa iba pang mga bagay, kapag gumagamit ng Network, palaging may tiyak na latency. Ang disk ay mayroon din nito, ngunit ang Network ay may higit pa nito. Ang latency ay ilang oras ng pagkaantala, na maaaring maliit o medyo makabuluhan.
Nagbabago ang topology ng network. Ano ang topology - ito ang paglalagay ng aming kagamitan sa network. May mga data center, may mga rack na nakatayo doon, may mga kandila. Ang lahat ng ito ay maaaring ikonekta muli, ilipat, atbp. Ang lahat ng ito ay kailangan ding isaalang-alang. Nagbabago ang mga pangalan ng IP, nagbabago ang rutang dinadaanan ng aming trapiko. Kailangan din itong isaalang-alang.
Ang network ay maaari ding magbago sa mga tuntunin ng kagamitan. Mula sa pagsasanay, maaari kong sabihin na ang aming mga network engineer ay talagang gustong mag-update ng isang bagay sa mga kandila. Biglang may lumabas na bagong firmware at hindi sila partikular na interesado sa ilang Hadoop cluster. May sarili silang trabaho. Para sa kanila, ang pangunahing bagay ay gumagana ang Network. Alinsunod dito, gusto nilang mag-upload muli ng isang bagay doon, mag-flash sa kanilang hardware, at pana-panahon ding nagbabago ang hardware. Ang lahat ng ito sa paanuman ay kailangang isaalang-alang. Ang lahat ng ito ay nakakaapekto sa aming ipinamahagi na aplikasyon.
Karaniwan ang mga taong nagsimulang magtrabaho sa malalaking halaga ng data para sa ilang kadahilanan ay naniniwala na ang Internet ay walang limitasyon. Kung mayroong isang file ng ilang terabytes doon, maaari mo itong dalhin sa iyong server o computer at buksan ito gamit pusa at manood. May isa pang error kalakasan tingnan ang mga tala. Huwag kailanman gawin ito dahil ito ay masama. Dahil sinusubukan ni Vim na i-buffer ang lahat, i-load ang lahat sa memorya, lalo na kapag nagsimula kaming lumipat sa log na ito at naghahanap ng isang bagay. Ito ay mga bagay na nakalimutan, ngunit nagkakahalaga ng pagsasaalang-alang.

Mas madaling magsulat ng isang program na tumatakbo sa isang computer na may isang processor.
Kapag lumago ang aming system, gusto naming iparallelize ang lahat ng ito, at iparallelize ito hindi lamang sa isang computer, kundi pati na rin sa isang cluster. Ang tanong ay lumitaw: paano i-coordinate ang bagay na ito? Maaaring hindi man lang nakikipag-ugnayan ang aming mga application sa isa't isa, ngunit nagpatakbo kami ng ilang proseso nang magkatulad sa ilang mga server. At paano masusubaybayan na ang lahat ay maayos para sa kanila? Halimbawa, nagpapadala sila ng isang bagay sa Internet. Dapat silang sumulat tungkol sa kanilang estado sa isang lugar, halimbawa, sa ilang uri ng database o log, pagkatapos ay pagsama-samahin ang log na ito at pagkatapos ay pag-aralan ito sa isang lugar. Dagdag pa, kailangan nating isaalang-alang na ang proseso ay gumagana at gumagana, biglang may lumitaw na error dito o nag-crash ito, kung gayon gaano kabilis natin malalaman ang tungkol dito?
Malinaw na ang lahat ng ito ay mabilis na masusubaybayan. Maganda rin ito, ngunit ang pagsubaybay ay isang limitadong bagay na nagbibigay-daan sa iyong subaybayan ang ilang bagay sa pinakamataas na antas.
Kapag gusto nating magsimulang makipag-ugnayan ang ating mga proseso sa isa't isa, halimbawa, upang magpadala sa isa't isa ng ilang data, pagkatapos ay lumitaw din ang tanong - paano ito mangyayari? Magkakaroon ba ng ilang uri ng kondisyon ng lahi, mapapatungan ba nila ang isa't isa, tama ba ang pagdating ng data, may mawawala ba sa daan? Kailangan nating bumuo ng ilang uri ng protocol, atbp.
Ang koordinasyon ng lahat ng mga prosesong ito ay hindi isang maliit na bagay. At pinipilit nito ang developer na bumaba sa mas mababang antas, at magsulat ng mga system mula sa simula, o hindi mula sa simula, ngunit hindi ito gaanong simple.
Kung makabuo ka ng isang cryptographic algorithm o kahit na ipatupad ito, pagkatapos ay itapon ito kaagad, dahil malamang na hindi ito gagana para sa iyo. Malamang na naglalaman ito ng isang grupo ng mga error na nakalimutan mong ibigay. Huwag kailanman gamitin ito para sa anumang seryosong bagay dahil malamang na hindi ito matatag. Dahil ang lahat ng mga algorithm na umiiral ay nasubok ng panahon sa napakahabang panahon. Ito ay binubugbog ng komunidad. Ito ay isang hiwalay na paksa. At ito ay pareho dito. Kung posible na huwag ipatupad ang ilang uri ng pag-synchronize ng proseso sa iyong sarili, mas mahusay na huwag gawin ito, dahil ito ay medyo kumplikado at humahantong sa iyo sa nanginginig na landas ng patuloy na paghahanap ng mga error.
Ngayon ay pinag-uusapan natin ang tungkol sa ZooKeeper. Sa isang banda, ito ay isang balangkas, sa kabilang banda, ito ay isang serbisyo na nagpapadali sa buhay para sa developer at pinapasimple ang pagpapatupad ng lohika at koordinasyon ng aming mga proseso hangga't maaari.

Tandaan natin kung ano ang maaaring hitsura ng isang karaniwang ipinamamahaging sistema. Ito ang napag-usapan natin - HDFS, HBase. Mayroong isang Master na proseso na namamahala sa mga manggagawa at mga proseso ng alipin. Siya ang may pananagutan sa pag-coordinate at pamamahagi ng mga gawain, pagsisimula muli ng mga manggagawa, paglulunsad ng mga bago, at pamamahagi ng load.

Ang isang mas advanced na bagay ay ang Coordination Service, ibig sabihin, ilipat ang gawain ng koordinasyon mismo sa isang hiwalay na proseso, kasama ang pagpapatakbo ng ilang uri ng backup o stanby Master nang magkatulad, dahil maaaring mabigo ang Master. At kung bumagsak ang Guro, hindi gagana ang ating sistema. Nagpapatakbo kami ng backup. Ang ilang mga estado na ang Master ay kailangang kopyahin sa backup. Maaari din itong ipagkatiwala sa Coordination Service. Ngunit sa diagram na ito, ang Master mismo ang may pananagutan sa pag-coordinate ng mga manggagawa dito ang serbisyo ay nag-coordinate ng mga aktibidad sa pagtitiklop ng data.

Ang isang mas advanced na opsyon ay kapag ang lahat ng koordinasyon ay pinangangasiwaan ng aming serbisyo, gaya ng karaniwang ginagawa. Inaako niya ang responsibilidad para tiyaking gumagana ang lahat. At kung ang isang bagay ay hindi gumagana, alamin namin ang tungkol dito at subukang lutasin ang sitwasyong ito. Sa anumang kaso, naiwan tayo sa isang Master na kahit papaano ay nakikipag-ugnayan sa mga alipin at maaaring magpadala ng data, impormasyon, mga mensahe, atbp. sa pamamagitan ng ilang serbisyo.

Mayroong isang mas advanced na pamamaraan, kapag wala tayong Master, ang lahat ng mga node ay master alipin, naiiba sa kanilang pag-uugali. Ngunit kailangan pa rin nilang makipag-ugnayan sa isa't isa, kaya may natitira pang serbisyo para i-coordinate ang mga pagkilos na ito. Marahil, si Cassandra, na gumagana sa prinsipyong ito, ay umaangkop sa pamamaraang ito.
Mahirap sabihin kung alin sa mga scheme na ito ang mas gumagana. Ang bawat isa ay may sariling kalamangan at kahinaan.

At hindi kailangang matakot sa ilang mga bagay sa Guro, dahil, tulad ng ipinapakita ng kasanayan, hindi siya masyadong madaling kapitan sa patuloy na paglilingkod. Ang pangunahing bagay dito ay ang pumili ng tamang solusyon para sa pagho-host ng serbisyong ito sa isang hiwalay na makapangyarihang node, upang magkaroon ito ng sapat na mapagkukunan, upang kung maaari, ang mga gumagamit ay walang access doon, upang hindi nila sinasadyang patayin ang prosesong ito. Ngunit sa parehong oras, sa gayong pamamaraan ay mas madaling pamahalaan ang mga manggagawa mula sa proseso ng Master, i.e. ang pamamaraan na ito ay mas simple mula sa punto ng view ng pagpapatupad.

At ang pamamaraan na ito (sa itaas) ay malamang na mas kumplikado, ngunit mas maaasahan.

Ang pangunahing problema ay bahagyang pagkabigo. Halimbawa, kapag nagpadala kami ng mensahe sa Network, may nangyaring aksidente, at hindi malalaman ng nagpadala ng mensahe kung natanggap ang kanyang mensahe at kung ano ang nangyari sa panig ng tatanggap, hindi malalaman kung naproseso nang tama ang mensahe , ibig sabihin, hindi siya makakatanggap ng anumang kumpirmasyon.
Alinsunod dito, dapat nating iproseso ang sitwasyong ito. At ang pinakasimpleng bagay ay ipadala muli ang mensaheng ito at maghintay hanggang makatanggap kami ng tugon. Sa kasong ito, hindi isinasaalang-alang kung nagbago ang estado ng tatanggap. Maaari kaming magpadala ng mensahe at magdagdag ng parehong data nang dalawang beses.
Nag-aalok ang ZooKeeper ng mga paraan upang harapin ang mga naturang pagtanggi, na nagpapadali din sa ating buhay.

Tulad ng nabanggit nang kaunti, ito ay katulad ng pagsusulat ng mga multi-threaded na programa, ngunit ang pangunahing pagkakaiba ay sa mga distributed application na binuo namin sa iba't ibang mga makina, ang tanging paraan upang makipag-usap ay ang Network. Mahalaga, ito ay isang shared-nothing architecture. Ang bawat proseso o serbisyo na tumatakbo sa isang makina ay may sariling memorya, sarili nitong disk, sarili nitong processor, na hindi nito ibinabahagi sa sinuman.
Kung sumulat tayo ng multi-threaded program sa isang computer, maaari nating gamitin ang shared memory upang makipagpalitan ng data. Mayroon kaming switch ng konteksto doon, maaaring lumipat ang mga proseso. Nakakaapekto ito sa pagganap. Sa isang banda, walang ganoong bagay sa programa sa isang kumpol, ngunit may mga problema sa Network.

Alinsunod dito, ang mga pangunahing problema na lumitaw kapag nagsusulat ng mga ipinamamahaging sistema ay pagsasaayos. Nagsusulat kami ng ilang uri ng aplikasyon. Kung ito ay simple, pagkatapos ay i-hardcode namin ang lahat ng uri ng mga numero sa code, ngunit ito ay hindi maginhawa, dahil kung magpasya kami na sa halip na isang timeout ng kalahating segundo gusto namin ng isang timeout ng isang segundo, pagkatapos ay kailangan naming i-recompile ang application at igulong muli ang lahat. Ito ay isang bagay kapag ito ay nasa isang makina, kapag maaari mo lamang itong i-restart, ngunit kapag mayroon kaming maraming mga makina, kailangan naming patuloy na kopyahin ang lahat. Dapat nating subukang gawing ma-configure ang application.
Dito pinag-uusapan natin ang tungkol sa static na pagsasaayos para sa mga proseso ng system. Ito ay hindi buo, marahil mula sa operating system point of view, maaaring ito ay isang static na configuration para sa aming mga proseso, ibig sabihin, ito ay isang configuration na hindi basta-basta maaaring kunin at i-update.
Mayroon ding isang dynamic na pagsasaayos. Ito ang mga parameter na gusto nating baguhin sa mabilisang paraan upang sila ay kunin doon.
Anong problema dito? Nag-update kami ng config, inilunsad ito, kaya ano? Ang problema ay maaaring sa isang banda ay inilunsad namin ang config, ngunit nakalimutan ang tungkol sa bagong bagay, ang config ay nanatili doon. Pangalawa, habang inilalabas namin, na-update ang configuration sa ilang lugar, ngunit hindi sa iba. At ang ilang proseso ng aming application na tumatakbo sa isang makina ay na-restart gamit ang isang bagong config, at sa isang lugar na may luma. Ito ay maaaring magresulta sa aming ipinamahagi na application na hindi naaayon mula sa isang pananaw sa pagsasaayos. Ang problemang ito ay karaniwan. Para sa isang dynamic na configuration, ito ay mas may kaugnayan dahil ito ay nagpapahiwatig na ito ay maaaring baguhin sa mabilisang.
Ang isa pang problema ay ang pagiging miyembro ng grupo. Palagi kaming may ilang hanay ng mga manggagawa, lagi naming gustong malaman kung sino sa kanila ang buhay, sino sa kanila ang patay. Kung mayroong Master, dapat niyang maunawaan kung aling mga manggagawa ang maaaring i-redirect sa mga kliyente upang magpatakbo sila ng mga kalkulasyon o magtrabaho kasama ang data, at kung alin ang hindi. Ang isang problema na patuloy na lumalabas ay kailangan nating malaman kung sino ang nagtatrabaho sa ating cluster.
Ang isa pang tipikal na problema ay ang halalan ng mga pinuno, kapag gusto nating malaman kung sino ang namumuno. Ang isang halimbawa ay ang pagtitiklop, kapag mayroon kaming ilang proseso na tumatanggap ng mga pagpapatakbo ng pagsulat at pagkatapos ay ginagaya ang mga ito sa iba pang mga proseso. Siya ang magiging pinuno, lahat ng iba ay susunod sa kanya, susunod sa kanya. Kinakailangan na pumili ng isang proseso upang ito ay hindi malabo para sa lahat, upang hindi lumabas na dalawang pinuno ang napili.
Mayroon ding mutually exclusive access. Ang problema dito ay mas kumplikado. Mayroong isang bagay bilang isang mutex, kapag sumulat ka ng mga multi-threaded na programa at nais ng access sa ilang mapagkukunan, halimbawa, isang memory cell, na limitado at isinasagawa ng isang thread lamang. Dito ang mapagkukunan ay maaaring isang bagay na mas abstract. At ang iba't ibang mga application mula sa iba't ibang mga node ng aming Network ay dapat lamang makatanggap ng eksklusibong pag-access sa isang ibinigay na mapagkukunan, at hindi para lahat ay maaaring baguhin ito o magsulat ng isang bagay doon. Ito ang tinatawag na mga kandado.
Pinapayagan ka ng ZooKeeper na lutasin ang lahat ng mga problemang ito sa isang antas o iba pa. At ipapakita ko sa mga halimbawa kung paano ito nagpapahintulot sa iyo na gawin ito.

Walang mga naka-block na primitive. Kapag nagsimula kaming gumamit ng isang bagay, ang primitive na ito ay hindi maghihintay para sa anumang kaganapan na mangyari. Malamang, ang bagay na ito ay gagana nang asynchronously, sa gayon ay nagpapahintulot sa mga proseso na hindi mag-hang habang naghihintay sila ng isang bagay. Ito ay isang napaka-kapaki-pakinabang na bagay.
Ang lahat ng mga kahilingan ng kliyente ay pinoproseso sa pagkakasunud-sunod ng pangkalahatang pila.
At may pagkakataon ang mga kliyente na makatanggap ng abiso tungkol sa mga pagbabago sa ilang estado, tungkol sa mga pagbabago sa data, bago makita ng kliyente ang binagong data mismo.

Ang ZooKeeper ay maaaring gumana sa dalawang mode. Ang una ay standalone, sa isang node. Ito ay maginhawa para sa pagsubok. Maaari rin itong gumana sa cluster mode, sa anumang bilang ng mga node. mga serverKung mayroon tayong 100-machine cluster, hindi nito kailangang tumakbo sa 100 makina. Sapat na ang maglaan ng ilang makina kung saan maaaring tumakbo ang ZooKeeper. At sumusunod ito sa prinsipyo ng high availability. Nag-iimbak ang ZooKeeper ng kumpletong kopya ng data sa bawat tumatakbong instance. Ipapaliwanag ko kung paano nito ginagawa ito mamaya. Hindi nito hinahati o hinahati ang data. Sa isang banda, isa itong disbentaha dahil hindi tayo maaaring mag-imbak ng marami, ngunit sa kabilang banda, hindi ito kailangan. Hindi ito idinisenyo para doon; hindi ito isang database.
Maaaring i-cache ang data sa panig ng kliyente. Ito ay isang karaniwang prinsipyo upang hindi namin maantala ang serbisyo at huwag i-load ito ng parehong mga kahilingan. Karaniwang alam ito ng isang matalinong kliyente at ini-cache ito.
Halimbawa, may nagbago dito. Mayroong ilang uri ng aplikasyon. Ang isang bagong pinuno ay nahalal, na responsable, halimbawa, para sa pagproseso ng mga operasyon sa pagsulat. At gusto naming kopyahin ang data. Ang isang solusyon ay ilagay ito sa isang loop. At palagi naming tinatanong ang aming serbisyo - may nagbago ba? Ang pangalawang pagpipilian ay mas mahusay. Isa itong mekanismo ng relo na nagbibigay-daan sa iyong abisuhan ang mga kliyente na may nagbago. Ito ay isang mas murang paraan sa mga tuntunin ng mga mapagkukunan at mas maginhawa para sa mga kliyente.

Ang kliyente ay ang user na gumagamit ng ZooKeeper.
Ang server ay ang proseso ng ZooKeeper mismo.
Ang Znode ay ang pangunahing bagay sa ZooKeeper. Ang lahat ng znode ay iniimbak sa memorya ng ZooKeeper at inayos sa anyo ng isang hierarchical diagram, sa anyo ng isang puno.
Mayroong dalawang uri ng operasyon. Ang una ay ang pag-update/pagsusulat, kapag binago ng ilang operasyon ang estado ng ating puno. Ang puno ay karaniwan.
At posibleng hindi nakumpleto ng kliyente ang isang kahilingan at nadiskonekta, ngunit makakapagtatag ng session kung saan ito nakikipag-ugnayan sa ZooKeeper.

Ang modelo ng data ng ZooKeeper ay kahawig ng isang file system. Mayroong isang karaniwang ugat at pagkatapos ay nagpunta kami na parang sa pamamagitan ng mga direktoryo na nagmumula sa ugat. At pagkatapos ay ang catalog ng unang antas, pangalawang antas. Ito ang lahat ng mga znode.
Ang bawat znode ay maaaring mag-imbak ng ilang data, karaniwang hindi masyadong malaki, halimbawa, 10 kilobytes. At ang bawat znode ay maaaring magkaroon ng isang tiyak na bilang ng mga bata.

Ang mga Znode ay may ilang uri. Maaari silang malikha. At kapag lumilikha ng isang znode, tinutukoy namin ang uri kung saan ito dapat nabibilang.
Mayroong dalawang uri. Ang una ay ang ephemeral flag. Nabubuhay si Znode sa loob ng isang session. Halimbawa, ang kliyente ay nagtatag ng isang sesyon. At hangga't ang sesyon na ito ay nabubuhay, ito ay iiral. Ito ay kinakailangan upang hindi makagawa ng isang bagay na hindi kailangan. Ito ay angkop din para sa mga sandali kung kailan mahalaga para sa amin na mag-imbak ng mga primitive ng data sa loob ng isang session.
Ang pangalawang uri ay sequential flag. Dinadagdagan nito ang counter sa daan patungo sa znode. Halimbawa, mayroon kaming direktoryo na may application 1_5. At noong ginawa namin ang unang node, nakatanggap ito ng p_1, ang pangalawa - p_2. At kapag tinawag namin ang pamamaraang ito sa bawat oras, ipinapasa namin ang buong landas, na nagpapahiwatig lamang ng bahagi ng landas, at ang numerong ito ay awtomatikong nadaragdagan dahil ipinapahiwatig namin ang uri ng node - sunud-sunod.
Regular na znode. Palagi siyang mabubuhay at may pangalang sinasabi namin sa kanya.

Ang isa pang kapaki-pakinabang na bagay ay ang bandila ng relo. Kung i-install namin ito, ang kliyente ay maaaring mag-subscribe sa ilang mga kaganapan para sa isang partikular na node. Ipapakita ko sa iyo sa ibang pagkakataon ang isang halimbawa kung paano ito ginagawa. Ang ZooKeeper mismo ay nag-aabiso sa kliyente na ang data sa node ay nagbago. Gayunpaman, hindi ginagarantiyahan ng mga notification na may dumating na ilang bagong data. Sinasabi lang nila na may nagbago, kaya kailangan mo pa ring ihambing ang data sa ibang pagkakataon sa magkakahiwalay na mga tawag.
At tulad ng sinabi ko na, ang pagkakasunud-sunod ng data ay tinutukoy ng kilobytes. Hindi na kailangang mag-imbak ng malalaking data ng teksto doon, dahil hindi ito isang database, ito ay isang server ng koordinasyon ng aksyon.

Hayaan ninyong ikuwento ko sa inyo nang kaunti ang tungkol sa mga sesyon. Kung mayroon tayong ilang server, maaari tayong lumipat mula sa isang server patungo sa isa pa nang walang anumang problema. tagapagsilbi, gamit ang session ID. Ito ay lubos na maginhawa.
Ang bawat session ay may ilang uri ng timeout. Ang isang session ay tinutukoy kung ang kliyente ay nagpapadala ng kahit ano sa server sa panahon ng session na iyon. Kung wala siyang naipadala sa panahon ng timeout, babagsak ang session, o maaaring isara ito mismo ng kliyente.

Wala itong ganoon karaming feature, ngunit maaari kang gumawa ng iba't ibang bagay sa API na ito. Ang tawag na nakita naming lumikha ay lumilikha ng isang znode at tumatagal ng tatlong parameter. Ito ang landas patungo sa znode, at dapat itong tukuyin nang buo mula sa ugat. At ito rin ang ilang data na gusto naming ilipat doon. At ang uri ng bandila. At pagkatapos ng paglikha ay ibinabalik nito ang landas sa znode.
Pangalawa, maaari mo itong tanggalin. Ang trick dito ay ang pangalawang parameter, bilang karagdagan sa landas patungo sa znode, ay maaaring tukuyin ang bersyon. Alinsunod dito, ang znode na iyon ay tatanggalin kung ang bersyon nito na inilipat namin ay katumbas ng isa na aktwal na umiiral.
Kung ayaw naming suriin ang bersyong ito, ipapasa lang namin ang argumentong "-1".

Pangatlo, sinusuri nito ang pagkakaroon ng isang znode. Nagbabalik ng true kung umiiral ang node, kung hindi man mali.
At pagkatapos ay lilitaw ang flag watch, na nagpapahintulot sa iyo na subaybayan ang node na ito.
Maaari mong itakda ang flag na ito kahit na sa isang hindi umiiral na node at makatanggap ng notification kapag lumitaw ito. Maaari rin itong maging kapaki-pakinabang.
Ang ilang higit pang mga hamon ay getData. Malinaw na makakatanggap kami ng data sa pamamagitan ng znode. Maaari mo ring gamitin ang flag watch. Sa kasong ito, hindi ito mai-install kung walang node. Samakatuwid, kailangan mong maunawaan na ito ay umiiral, at pagkatapos ay tumanggap ng data.

meron din SetData. Dito kami pumasa sa bersyon. At kung ipapasa natin ito, maa-update ang data sa znode ng isang partikular na bersyon.
Maaari mo ring tukuyin ang "-1" upang ibukod ang tseke na ito.
Ang isa pang kapaki-pakinabang na paraan ay getChildren. Makakakuha din tayo ng listahan ng lahat ng znode na kabilang dito. Masusubaybayan natin ito sa pamamagitan ng pagtatakda ng flag watch.
At pamamaraan i-sync nagbibigay-daan sa lahat ng mga pagbabago na maipadala nang sabay-sabay, sa gayon ay matiyak na ang mga ito ay nai-save at ang lahat ng data ay ganap na nabago.
Kung gumuhit kami ng mga pagkakatulad sa regular na programming, pagkatapos ay kapag gumamit ka ng mga pamamaraan tulad ng pagsulat, na sumulat ng isang bagay sa disk, at pagkatapos na ito ay magbalik ng tugon sa iyo, walang garantiya na naisulat mo ang data sa disk. At kahit na ang operating system ay tiwala na ang lahat ay nakasulat, may mga mekanismo sa disk mismo kung saan ang proseso ay dumadaan sa mga layer ng buffer, at pagkatapos lamang na ang data ay inilagay sa disk.

Karamihan sa mga asynchronous na tawag ay ginagamit. Nagbibigay-daan ito sa kliyente na magtrabaho nang magkatulad sa iba't ibang mga kahilingan. Maaari mong gamitin ang kasabay na diskarte, ngunit hindi gaanong produktibo.
Ang dalawang operasyong napag-usapan natin ay ang pag-update/pagsusulat, na nagbabago ng data. Ang mga ito ay lumikha, setData, i-sync, tanggalin. At mayroon nang read, getData, getChildren.

Ngayon ang ilang mga halimbawa kung paano ka makakagawa ng mga primitive para sa pagtatrabaho sa isang distributed system. Halimbawa, nauugnay sa pagsasaayos ng isang bagay. May lumitaw na bagong manggagawa. Idinagdag namin ang makina at sinimulan ang proseso. At mayroong sumusunod na tatlong tanong. Paano ito nagtatanong sa ZooKeeper para sa pagsasaayos? At kung gusto nating baguhin ang configuration, paano natin ito babaguhin? At pagkatapos naming palitan ito, paano nakuha ng mga manggagawang iyon?
Ginagawa itong medyo madali ng ZooKeeper. Halimbawa, nariyan ang ating znode tree. Mayroong isang node para sa aming aplikasyon dito, lumikha kami ng isang karagdagang node sa loob nito, na naglalaman ng data mula sa pagsasaayos. Ang mga ito ay maaaring o hindi maaaring magkahiwalay na mga parameter. Dahil maliit ang sukat, kadalasang maliit din ang sukat ng configuration, kaya medyo posible itong iimbak dito.
Ginagamit mo ang pamamaraan getData upang makuha ang configuration para sa manggagawa mula sa node. Itakda sa totoo. Kung sa ilang kadahilanan ay wala ang node na ito, aabisuhan kami tungkol dito kapag lumitaw ito, o kapag nagbago ito. Kung gusto nating malaman na may nagbago, itinakda natin ito sa totoo. At kung magbabago ang data sa node na ito, malalaman natin ang tungkol dito.
SetData. Itinakda namin ang data, itinakda ang "-1", ibig sabihin, hindi namin sinusuri ang bersyon, ipinapalagay namin na palagi kaming may isang pagsasaayos, hindi namin kailangang mag-imbak ng maraming mga pagsasaayos. Kung kailangan mong mag-imbak ng marami, kakailanganin mong magdagdag ng isa pang antas. Dito naniniwala kami na isa lang, kaya ang pinakabago lang ang ina-update namin, kaya hindi namin sinusuri ang bersyon. Sa sandaling ito, ang lahat ng kliyente na dati nang nag-subscribe ay makakatanggap ng notification na may nagbago sa node na ito. At pagkatapos nilang matanggap ito, kailangan din nilang humiling muli ng data. Ang abiso ay hindi nila natatanggap ang data mismo, ngunit abiso lamang ng mga pagbabago. Pagkatapos nito dapat silang humingi ng bagong data.

Ang pangalawang opsyon para sa paggamit ng primitive ay pagiging kasapi ng grupo. Mayroon kaming ipinamahagi na aplikasyon, mayroong isang grupo ng mga manggagawa at nais naming maunawaan na lahat sila ay nasa lugar. Samakatuwid, dapat nilang irehistro ang kanilang mga sarili na nagtatrabaho sila sa aming aplikasyon. At gusto rin naming malaman, alinman sa proseso ng Master o sa ibang lugar, tungkol sa lahat ng aktibong manggagawa na mayroon kami sa kasalukuyan.
Paano natin ito gagawin? Para sa application, lumikha kami ng node ng mga manggagawa at magdagdag ng isang sublevel doon gamit ang paraan ng paggawa. May error ako sa slide. Dito kailangan mo sunud-sunod tukuyin, pagkatapos ang lahat ng mga manggagawa ay isa-isang malilikha. At ang application, na humihiling ng lahat ng data tungkol sa mga anak ng node na ito, ay tumatanggap ng lahat ng aktibong manggagawa na umiiral.


Ito ay isang kakila-kilabot na pagpapatupad kung paano ito magagawa sa Java code. Magsimula tayo sa dulo, sa pangunahing pamamaraan. Ito ang aming klase, gawin natin ang pamamaraan nito. Bilang unang argumento na ginagamit namin ang host, kung saan kami kumokonekta, ibig sabihin, itinakda namin ito bilang argumento. At ang pangalawang argumento ay ang pangalan ng grupo.
Paano nangyayari ang koneksyon? Ito ay isang simpleng halimbawa ng API na ginagamit. Ang lahat ay medyo simple dito. Mayroong karaniwang klase na ZooKeeper. Ipinapasa namin ang mga host dito. At itakda ang timeout, halimbawa, sa 5 segundo. At mayroon kaming isang miyembro na tinatawag na connectedSignal. Mahalaga, lumikha kami ng isang grupo sa kahabaan ng ipinadalang landas. Hindi kami nagsusulat ng data doon, bagama't maaaring may nakasulat. At ang node dito ay may paulit-ulit na uri. Mahalaga, ito ay isang ordinaryong regular na node na iiral sa lahat ng oras. Dito ginagawa ang session. Ito ang pagpapatupad ng kliyente mismo. Magpapadala ang aming kliyente ng mga pana-panahong mensahe na nagsasaad na ang session ay buhay. At kapag tinapos na namin ang session, we call close and that’s it, bumabagsak ang session. Ito ay kung sakaling may mangyari sa atin, para malaman ito ng ZooKeeper at maputol ang session.

Paano i-lock ang isang mapagkukunan? Narito ang lahat ay medyo mas kumplikado. Mayroon kaming isang hanay ng mga manggagawa, mayroong ilang mapagkukunan na nais naming i-lock. Upang gawin ito, lumikha kami ng isang hiwalay na node, halimbawa, na tinatawag na lock1. Kung nagawa namin itong likhain, mayroon kaming lock dito. At kung hindi namin ito nagawa, susubukan ng manggagawa na kumuha ng getData mula rito, at dahil nalikha na ang node, maglalagay kami ng watcher dito at sa sandaling magbago ang estado ng node na ito, malalaman natin ang tungkol dito. At maaari naming subukan na magkaroon ng oras upang muling likhain ito. Kung inalis namin ang node na ito, inalis ang lock na ito, pagkatapos na hindi na namin kailanganin ang lock, aabandonahin namin ito, dahil ang node ay umiiral lamang sa loob ng session. Alinsunod dito, ito ay mawawala. At ang isa pang kliyente, sa loob ng balangkas ng isa pang sesyon, ay magagawang kunin ang lock sa node na ito, o sa halip, makakatanggap siya ng isang abiso na may nagbago at maaari niyang subukang gawin ito sa oras.

Isa pang halimbawa kung paano mo mapipili ang pangunahing pinuno. Ito ay medyo mas kumplikado, ngunit medyo simple din. Anong nangyayari dito? Mayroong pangunahing node na pinagsasama-sama ang lahat ng mga manggagawa. Sinusubukan naming kumuha ng data tungkol sa pinuno. Kung matagumpay itong nangyari, ibig sabihin, nakatanggap kami ng ilang data, pagkatapos ay magsisimulang sundin ng aming manggagawa ang pinunong ito. Naniniwala siya na mayroon nang pinuno.
Kung ang pinuno ay namatay para sa ilang kadahilanan, halimbawa, nahulog, pagkatapos ay sinubukan naming lumikha ng isang bagong pinuno. At kung magtagumpay tayo, ang ating manggagawa ang magiging pinuno. At kung ang isang tao sa sandaling ito ay nagawang lumikha ng isang bagong pinuno, pagkatapos ay susubukan naming maunawaan kung sino ito at pagkatapos ay sundin siya.
Dito umusbong ang tinatawag na herd effect, i.e. ang herd effect, dahil kapag namatay ang isang pinuno, ang nauuna sa oras ay magiging pinuno.

Kapag kumukuha ng isang mapagkukunan, maaari mong subukang gumamit ng isang bahagyang naiibang diskarte, na kung saan ay ang mga sumusunod. Halimbawa, gusto naming makakuha ng lock, ngunit walang hert effect. Ito ay binubuo sa katotohanan na ang aming application ay humihiling ng mga listahan ng lahat ng node id para sa isang umiiral nang node na may lock. At kung bago iyon ang node kung saan ginawa namin ang isang lock ay ang pinakamaliit sa set na natanggap namin, nangangahulugan ito na nakuha namin ang lock. Sinusuri namin na nakatanggap kami ng lock. Bilang tseke, magkakaroon ng kundisyon na ang id na natanggap namin noong gumagawa ng bagong lock ay minimal. At kung natanggap namin ito, pagkatapos ay magtatrabaho pa kami.
Kung mayroong partikular na id na mas maliit kaysa sa aming lock, maglalagay kami ng tagamasid sa kaganapang ito at maghintay ng abiso hanggang sa may magbago. Ibig sabihin, natanggap namin ang lock na ito. At hanggang sa ito ay bumagsak, hindi kami magiging minimum na id at hindi makakatanggap ng pinakamababang lock, at sa gayon ay makakapag-log in kami. At kung ang kundisyong ito ay hindi matugunan, pagkatapos ay pumunta kami kaagad dito at subukang kunin muli ang lock na ito, dahil maaaring may nagbago sa panahong ito.

Ano ang binubuo ng ZooKeeper? Mayroong 4 na pangunahing bagay. Ito ay mga proseso ng pagproseso - Kahilingan. At gayundin ang ZooKeeper Atomic Broadcast. Mayroong Commit Log kung saan ang lahat ng mga operasyon ay naitala. At ang In-memory Replicated DB mismo, i.e. ang database mismo kung saan naka-imbak ang buong punong ito.
Ito ay nagkakahalaga ng noting na ang lahat ng write operations ay dumadaan sa Request Processor. At ang mga read operation ay direktang pumunta sa In-memory database.

Ang database mismo ay ganap na kinopya. Ang lahat ng mga pagkakataon ng ZooKeeper ay nag-iimbak ng kumpletong kopya ng data.
Upang maibalik ang database pagkatapos ng pag-crash, mayroong isang Commit log. Ang karaniwang kasanayan ay bago mapunta ang data sa memorya, ito ay nakasulat doon upang kung ito ay nag-crash, ang log na ito ay maaaring i-play muli at ang estado ng system ay maibabalik. At ang mga pana-panahong snapshot ng database ay ginagamit din.

Ang ZooKeeper Atomic Broadcast ay isang bagay na ginagamit upang mapanatili ang kinokopyang data.
Ang ZAB ay panloob na pumipili ng isang pinuno mula sa punto ng view ng ZooKeeper node. Ang iba pang mga node ay nagiging kanyang mga tagasunod at umaasa ng ilang mga aksyon mula sa kanya. Kung nakatanggap sila ng mga entry, ipinapasa nila ang lahat sa pinuno. Nagsasagawa muna siya ng write operation at pagkatapos ay nagpadala ng mensahe tungkol sa kung ano ang nagbago sa kanyang mga tagasunod. Ito, sa katunayan, ay dapat na gumanap nang atomically, ibig sabihin, ang pag-record at pagsasahimpapawid na operasyon ng buong bagay ay dapat na gumanap nang atomically, sa gayon ginagarantiyahan ang pagkakapare-pareho ng data.
Pinoproseso lamang nito ang mga kahilingan sa pagsulat. Ang pangunahing gawain nito ay ang pagbabago ng operasyon sa isang transactional update. Ito ay isang espesyal na nabuong kahilingan.
At dito ito ay nagkakahalaga ng noting na ang idempotency ng mga update para sa parehong operasyon ay garantisadong. Ano ito? Ang bagay na ito, kung gagawin nang dalawang beses, ay magkakaroon ng parehong estado, ibig sabihin, ang kahilingan mismo ay hindi magbabago. At ito ay kailangang gawin upang sa kaso ng isang pag-crash, maaari mong i-restart ang operasyon, at sa gayon ay i-roll back ang mga pagbabago na bumagsak sa sandaling ito. Sa kasong ito, ang estado ng system ay magiging pareho, ibig sabihin, hindi dapat mangyari na ang isang serye ng pareho, halimbawa, mga proseso ng pag-update, ay humantong sa iba't ibang mga huling estado ng system.








Pinagmulan: www.habr.com
