"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Iesaku izlasīt lekcijas "Hadoop. ZooKeeper" stenogrammu no sērijas "Metodes liela apjoma datu izplatītai apstrādei programmā Hadoop"

Kas ir ZooKeeper, tā vieta Hadoop ekosistēmā. NepatiesÄ«ba par izplatÄ«to skaitļoÅ”anu. Standarta sadalÄ«tās sistēmas diagramma. GrÅ«tÄ«bas koordinēt sadalÄ«tās sistēmas. Tipiskas koordinācijas problēmas. ZooKeeper dizaina principi. ZooKeeper datu modelis. znode karogi. Sesijas. Klienta API. PrimitÄ«vie (konfigurācija, dalÄ«ba grupā, vienkārÅ”as slēdzenes, lÄ«deru ievēlÄ“Å”ana, bloÄ·Ä“Å”ana bez bara efekta). ZooKeeper arhitektÅ«ra. ZooKeeper DB. ZAB. PieprasÄ«jumu apstrādātājs.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Šodien mēs runāsim par ZooKeeper. Šī lieta ir ļoti noderīga. Tam, tāpat kā jebkuram Apache Hadoop produktam, ir logotips. Tas attēlo vīrieti.

Pirms tam mēs galvenokārt runājām par to, kā tur var apstrādāt datus, kā tos uzglabāt, tas ir, kā tos kaut kā izmantot un kaut kā ar tiem strādāt. Un Å”odien es gribētu nedaudz runāt par izplatÄ«to lietojumprogrammu izveidi. Un ZooKeeper ir viena no tām lietām, kas ļauj vienkārÅ”ot Å”o lietu. Å is ir sava veida pakalpojums, kas paredzēts kaut kādai procesu mijiedarbÄ«bas koordinÄ“Å”anai sadalÄ«tajās sistēmās, izplatÄ«tajās lietojumprogrammās.

VajadzÄ«ba pēc Ŕādām aplikācijām ar katru dienu kļūst arvien lielāka, tas ir mÅ«su kurss. No vienas puses, MapReduce un Å”is gatavais ietvars ļauj izlÄ«dzināt Å”o sarežģītÄ«bu un atbrÄ«vot programmētāju no tādu primitÄ«vu rakstÄ«Å”anas kā mijiedarbÄ«ba un procesu koordinÄ“Å”ana. Taču, no otras puses, neviens negarantē, ka tas tik un tā nebÅ«s jādara. MapReduce vai citi gatavi ietvari ne vienmēr pilnÄ«bā aizvieto dažus gadÄ«jumus, kurus nevar ieviest, izmantojot Å”o. Ieskaitot paÅ”u MapReduce un virkni citu Apache projektu; patiesÄ«bā tās ir arÄ« izplatÄ«tas lietojumprogrammas. Un, lai atvieglotu rakstÄ«Å”anu, viņi uzrakstÄ«ja ZooKeeper.

Tāpat kā visas ar Hadoop saistÄ«tās lietojumprogrammas, to izstrādāja Yahoo! Tagad tā ir arÄ« oficiāla Apache lietojumprogramma. Tas nav tik aktÄ«vi izstrādāts kā HBase. Ja dodaties uz JIRA HBase, tad katru dienu ir kaudze kļūdu ziņojumu, kaudze priekÅ”likumu kaut ko optimizēt, t.i., dzÄ«ve projektā nepārtraukti rit. Un ZooKeeper, no vienas puses, ir salÄ«dzinoÅ”i vienkārÅ”s produkts, un, no otras puses, tas nodroÅ”ina tā uzticamÄ«bu. Un tas ir diezgan viegli lietojams, tāpēc tas ir kļuvis par standartu lietojumprogrammās Hadoop ekosistēmā. Tāpēc es domāju, ka bÅ«tu lietderÄ«gi to pārskatÄ«t, lai saprastu, kā tas darbojas un kā to izmantot.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Å Ä« ir bilde no kādas mÅ«su lekcijas. Mēs varam teikt, ka tas ir ortogonāls visam, ko mēs lÄ«dz Å”im esam apsvēruÅ”i. Un viss, kas Å”eit ir norādÄ«ts, vienā vai otrā pakāpē darbojas ar ZooKeeper, t.i., tas ir pakalpojums, kas izmanto visus Å”os produktus. Ne HDFS, ne MapReduce nerada savus lÄ«dzÄ«gus pakalpojumus, kas tiem Ä«paÅ”i derētu. AttiecÄ«gi tiek izmantots ZooKeeper. Un tas vienkārÅ”o izstrādi un dažas lietas, kas saistÄ«tas ar kļūdām.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

No kurienes tas viss nāk? Å Ä·iet, ka mēs paralēli palaižam divas lietojumprogrammas dažādos datoros, savienojām tās ar virkni vai sietu, un viss darbojas. Bet problēma ir tā, ka tÄ«kls nav uzticams, un, ja jÅ«s smirdējat trafiku vai paskatās, kas tur notiek zemā lÄ«menÄ«, kā klienti mijiedarbojas tÄ«klā, jÅ«s bieži varat redzēt, ka dažas paketes tiek pazaudētas vai nosÅ«tÄ«tas atkārtoti. Ne velti tika izgudroti TCP protokoli, kas ļauj izveidot noteiktu sesiju un garantēt ziņojumu piegādi. Bet jebkurā gadÄ«jumā pat TCP ne vienmēr var jÅ«s izglābt. Visam ir taimauts. TÄ«kls kādu laiku var vienkārÅ”i nokrist. Tas var tikai mirgot. Un tas viss noved pie tā, ka nevar paļauties uz tÄ«kla uzticamÄ«bu. Tā ir galvenā atŔķirÄ«ba no paralēlu programmu rakstÄ«Å”anas, kas darbojas vienā datorā vai vienā superdatorā, kur nav TÄ«kla, kur atmiņā ir uzticamāka datu apmaiņas kopne. Un tā ir bÅ«tiska atŔķirÄ«ba.

Cita starpā, izmantojot tīklu, vienmēr ir noteikts latentums. Diskam arī tas ir, bet tīklam tā ir vairāk. Latentums ir zināms aizkaves laiks, kas var būt mazs vai diezgan nozīmīgs.

TÄ«kla topoloÄ£ija mainās. Kas ir topoloÄ£ija - tas ir mÅ«su tÄ«kla aprÄ«kojuma izvietojums. Ir datu centri, ir plaukti, kas tur stāv, ir sveces. To visu var atkārtoti savienot, pārvietot utt. Tas viss arÄ« jāņem vērā. Mainās IP nosaukumi, mainās marÅ”ruts, caur kuru pārvietojas mÅ«su satiksme. Tas arÄ« ir jāņem vērā.

TÄ«kls var mainÄ«ties arÄ« aprÄ«kojuma ziņā. No prakses varu teikt, ka mÅ«su tÄ«kla inženieriem ļoti patÄ«k periodiski kaut ko atjaunināt uz svecēm. PēkŔņi parādÄ«jās jauna programmaparatÅ«ra, un viņus Ä«paÅ”i neinteresēja kāds Hadoop klasteris. Viņiem ir savs darbs. Viņiem galvenais, lai TÄ«kls strādā. AttiecÄ«gi viņi tur vēlas kaut ko atkārtoti augÅ”upielādēt, veikt aparatÅ«ras mirgoÅ”anu, un arÄ« aparatÅ«ra periodiski mainās. Tas viss kaut kā ir jāņem vērā. Tas viss ietekmē mÅ«su izplatÄ«to lietojumprogrammu.

Parasti cilvēki, kuri kaut kādu iemeslu dēļ sāk strādāt ar lielu datu apjomu, uzskata, ka internets ir neierobežots. Ja tur ir vairāku terabaitu fails, varat to nogādāt savā serverÄ« vai datorā un atvērt, izmantojot kaÄ·is un skatÄ«ties. Ir vēl viena kļūda spars paskaties uz baļķiem. Nekad nedariet to, jo tas ir slikti. Jo Vim mēģina visu buferēt, visu ielādēt atmiņā, it Ä«paÅ”i, kad sākam pārvietoties pa Å”o žurnālu un kaut ko meklēt. Tās ir lietas, kas ir aizmirstas, bet ir vērts padomāt.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

VienkārŔāk ir uzrakstīt vienu programmu, kas darbojas vienā datorā ar vienu procesoru.

Kad mÅ«su sistēma attÄ«stās, mēs vēlamies to visu paralēli un paralēli ne tikai datorā, bet arÄ« klasterÄ«. Rodas jautājums: kā saskaņot Å”o lietu? MÅ«su lietojumprogrammas, iespējams, pat nesadarbojas savā starpā, taču mēs veicām vairākus procesus paralēli vairākos serveros. Un kā uzraudzÄ«t, lai viņiem viss iet labi? Piemēram, viņi kaut ko sÅ«ta pa internetu. Viņiem kaut kur jāraksta par savu stāvokli, piemēram, kaut kādā datu bāzē vai žurnālā, tad Å”is žurnāls ir jāapkopo un pēc tam kaut kur jāanalizē. Turklāt jāņem vērā, ka process darbojās un darbojās, pēkŔņi tajā parādÄ«jās kāda kļūda vai avarēja, tad cik ātri mēs par to uzzināsim?

Skaidrs, ka to visu var ātri uzraudzīt. Tas arī ir labi, taču uzraudzība ir ierobežota lieta, kas ļauj pārraudzīt dažas lietas visaugstākajā līmenī.

Kad vēlamies, lai mÅ«su procesi sāk mijiedarboties viens ar otru, piemēram, sÅ«tÄ«t viens otram kādus datus, tad arÄ« rodas jautājums ā€“ kā tas notiks? Vai bÅ«s kaut kāds sacensÄ«bu stāvoklis, pārrakstÄ«s viens otru, vai pareizi ieradÄ«sies dati, vai pa ceļam kaut kas pazudÄ«s? Jāizstrādā kaut kāds protokols utt.

Visu Å”o procesu koordinÄ“Å”ana nav mazsvarÄ«ga lieta. Un tas liek izstrādātājam nolaisties vēl zemākā lÄ«menÄ« un rakstÄ«t sistēmas vai nu no nulles, vai ne gluži no nulles, taču tas nav tik vienkārÅ”i.

Ja jÅ«s izdomājat vai pat ievieÅ”at kriptogrāfijas algoritmu, tad nekavējoties izmetiet to, jo, visticamāk, tas jums nederēs. Visticamāk, tajā bÅ«s virkne kļūdu, kuras esat aizmirsis norādÄ«t. Nekad neizmantojiet to nekam nopietnam, jo ā€‹ā€‹tas, visticamāk, bÅ«s nestabils. Jo visi pastāvoÅ”ie algoritmi ir ļoti ilgi pārbaudÄ«ti laika gaitā. To sagrauj sabiedrÄ«ba. Å Ä« ir atseviŔķa tēma. Un Å”eit ir tas pats. Ja ir iespējams paÅ”am neieviest kaut kādu procesu sinhronizāciju, tad labāk to nedarÄ«t, jo tas ir diezgan sarežģīti un ved pa nestabilo nepārtrauktas kļūdu meklÄ“Å”anas ceļu.

Å odien mēs runājam par ZooKeeper. No vienas puses, tas ir ietvars, no otras puses, tas ir pakalpojums, kas atvieglo izstrādātāja dzÄ«vi un maksimāli vienkārÅ”o loÄ£ikas ievieÅ”anu un mÅ«su procesu koordināciju.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Atcerēsimies, kā varētu izskatÄ«ties standarta izplatÄ«tā sistēma. Tas ir tas, par ko mēs runājām - HDFS, HBase. Ir galvenais process, kas pārvalda strādnieku un vergu procesus. ViņŔ ir atbildÄ«gs par uzdevumu koordinÄ“Å”anu un sadali, darbinieku atsākÅ”anu, jaunu darbu uzsākÅ”anu un slodzes sadali.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Advancētāka lieta ir Koordinācijas dienests, tas ir, pārcelt paÅ”u koordinācijas uzdevumu uz atseviŔķu procesu, plus paralēli palaist kaut kādu rezerves jeb stanby Master, jo Master var neizdoties. Un, ja Skolotājs krÄ«t, tad mÅ«su sistēma nedarbosies. Mēs veicam dublÄ“Å”anu. Daži norāda, ka galvenais ir jāreplicē dublÄ“Å”anai. To var uzticēt arÄ« Koordinācijas dienestam. Bet Å”ajā diagrammā par strādnieku koordinÄ“Å”anu ir atbildÄ«gs pats Meistars, Å”eit dienests koordinē datu replikācijas darbÄ«bas.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Uzlabota iespēja ir tad, ja visu koordināciju veic mÅ«su dienests, kā tas parasti tiek darÄ«ts. ViņŔ uzņemas atbildÄ«bu par to, lai viss darbotos. Un, ja kaut kas nedarbojas, mēs par to uzzinām un mēģinām apiet Å”o situāciju. Jebkurā gadÄ«jumā mums paliek Meistars, kurÅ” kaut kādā veidā mijiedarbojas ar vergiem un caur kādu pakalpojumu var nosÅ«tÄ«t datus, informāciju, ziņas utt.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Ir vēl progresÄ«vāka shēma, kad mums nav Master, visi mezgli ir galvenie vergi, atŔķirÄ«gi savā uzvedÄ«bā. Bet viņiem joprojām ir jāsadarbojas vienam ar otru, tāpēc joprojām ir atlicis kāds dienests Å”o darbÄ«bu koordinÄ“Å”anai. DroÅ”i vien Cassandra, kas darbojas pēc Ŕī principa, atbilst Å”ai shēmai.

Ir grÅ«ti pateikt, kura no Ŕīm shēmām darbojas labāk. Katram savi plusi un mÄ«nusi.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Un no dažām lietām ar Skolotāju nav jābaidās, jo, kā rāda prakse, viņŔ nav tik uzņēmÄ«gs pret pastāvÄ«gu kalpoÅ”anu. Å eit galvenais ir izvēlēties pareizo risinājumu Ŕī pakalpojuma mitināŔanai atseviŔķā jaudÄ«gā mezglā, lai tam bÅ«tu pietiekami daudz resursu, lai pēc iespējas lietotājiem tur nebÅ«tu piekļuves, lai viņi nejauÅ”i nenogalinātu Å”o procesu. Bet tajā paŔā laikā Ŕādā shēmā ir daudz vieglāk vadÄ«t strādniekus no Master procesa, t.i., Ŕī shēma ir vienkārŔāka no ievieÅ”anas viedokļa.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Un Ŕī shēma (iepriekÅ”), iespējams, ir sarežģītāka, bet uzticamāka.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Galvenā problēma ir daļējas atteices. Piemēram, kad mēs nosÅ«tām ziņojumu pa tÄ«klu, notiek kāda veida negadÄ«jums, un tas, kurÅ” nosÅ«tÄ«ja ziņojumu, nezinās, vai viņa ziņojums ir saņemts un kas notika saņēmēja pusē, nezinās, vai ziņojums tika pareizi apstrādāts. , t.i., viņŔ nesaņems nekādu apstiprinājumu.

AttiecÄ«gi mums Ŕī situācija ir jāapstrādā. Un visvienkārŔākais ir atkārtoti nosÅ«tÄ«t Å”o ziņojumu un gaidÄ«t, lÄ«dz saņemsim atbildi. Å ajā gadÄ«jumā netiek ņemts vērā, vai ir mainÄ«jies uztvērēja stāvoklis. Mēs varam nosÅ«tÄ«t ziņojumu un pievienot tos paÅ”us datus divas reizes.

ZooKeeper piedāvā veidus, kā tikt galā ar Ŕādiem atteikumiem, kas arī atvieglo mūsu dzīvi.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Kā minēts nedaudz iepriekÅ”, tas ir lÄ«dzÄ«gs daudzpavedienu programmu rakstÄ«Å”anai, taču galvenā atŔķirÄ«ba ir tāda, ka izplatÄ«tajās lietojumprogrammās, kuras mēs veidojam uz dažādām iekārtām, vienÄ«gais saziņas veids ir tÄ«kls. BÅ«tÄ«bā Ŕī ir dalÄ«ta nekāda arhitektÅ«ra. Katram procesam vai pakalpojumam, kas darbojas vienā maŔīnā, ir sava atmiņa, savs disks, savs procesors, ko tas ne ar vienu nedala.

Ja vienā datorā rakstām daudzpavedienu programmu, tad datu apmaiņai varam izmantot koplietojamo atmiņu. Mums tur ir konteksta slēdzis, procesi var pārslēgties. Tas ietekmē veiktspēju. No vienas puses, klastera programmā tāda nav, taču ir problēmas ar tīklu.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

AttiecÄ«gi galvenās problēmas, kas rodas, rakstot sadalÄ«tās sistēmas, ir konfigurācija. Rakstam kaut kādu iesniegumu. Ja tas ir vienkārÅ”i, tad kodā iekodējam visādus skaitļus, taču tas ir neērti, jo, ja nolemjam, ka pussekundes taimauta vietā vēlamies vienas sekundes taimautu, tad ir jāpārkompilē aplikācija un izrullē visu vēlreiz. Viena lieta ir, ja tas ir vienā iekārtā, kad jÅ«s varat to vienkārÅ”i restartēt, bet, ja mums ir daudz iekārtu, mums ir pastāvÄ«gi jākopē viss. Mums jāmēģina padarÄ«t lietojumprogrammu konfigurējamu.

Å eit mēs runājam par sistēmas procesu statisko konfigurāciju. Tas nav pilnÄ«bā, varbÅ«t no operētājsistēmas viedokļa tā var bÅ«t mÅ«su procesu statiska konfigurācija, tas ir, Ŕī ir konfigurācija, kuru nevar vienkārÅ”i ņemt un atjaunināt.

Ir arī dinamiska konfigurācija. Tie ir parametri, kurus mēs vēlamies mainīt lidojuma laikā, lai tie tiktu tur uzņemti.

Kāda Å”eit ir problēma? Mēs atjauninājām konfigurāciju, izlaidām to, un ko tad? Problēma var bÅ«t tajā, ka no vienas puses mēs izrullējām konfigurāciju, bet aizmirsām par jauno lietu, konfigurācija palika tur. Otrkārt, kamēr mēs izlaidām, dažās vietās konfigurācija tika atjaunināta, bet citās ne. Un daži mÅ«su lietojumprogrammas procesi, kas darbojas vienā maŔīnā, tika restartēti ar jaunu konfigurāciju un kaut kur ar veco. Tā rezultātā mÅ«su izplatÄ«tā lietojumprogramma var bÅ«t nekonsekventa no konfigurācijas viedokļa. Å Ä« problēma ir izplatÄ«ta. Dinamiskajai konfigurācijai tas ir atbilstoŔāks, jo tas nozÄ«mē, ka to var mainÄ«t lidojuma laikā.

Vēl viena problēma ir dalÄ«ba grupā. Mums vienmēr ir kāds strādnieku kopums, mēs vienmēr gribam zināt, kurÅ” no viņiem ir dzÄ«vs, kurÅ” ir miris. Ja ir Meistars, tad viņam jāsaprot, kurus darbiniekus var novirzÄ«t pie klientiem, lai tie veiktu aprēķinus vai strādātu ar datiem, un kurus nevar. PastāvÄ«gi rodas problēma, ka mums ir jāzina, kas strādā mÅ«su klasterÄ«.

Vēl viena tipiska problēma ir lÄ«deru vēlÄ“Å”anas, kad mēs gribam zināt, kurÅ” ir atbildÄ«gs. Viens piemērs ir replikācija, kad mums ir kāds process, kas saņem rakstÄ«Å”anas darbÄ«bas un pēc tam atkārto tās citos procesos. ViņŔ bÅ«s vadÄ«tājs, visi pārējie viņam paklausÄ«s, sekos viņam. Jāizvēlas process, lai tas bÅ«tu visiem nepārprotams, lai neiznāk, ka tiek izvēlēti divi vadÄ«tāji.

Ir arÄ« savstarpēji izslēdzoÅ”a piekļuve. Å eit problēma ir sarežģītāka. Pastāv tāda lieta kā mutex, kad rakstāt daudzpavedienu programmas un vēlaties, lai piekļuve kādam resursam, piemēram, atmiņas Ŕūnai, tiktu ierobežota un tiktu veikta tikai ar vienu pavedienu. Å eit resurss varētu bÅ«t kaut kas abstraktāks. Un dažādām lietojumprogrammām no dažādiem mÅ«su tÄ«kla mezgliem vajadzētu saņemt tikai ekskluzÄ«vu piekļuvi konkrētam resursam, nevis tāpēc, lai ikviens varētu to mainÄ«t vai tur kaut ko ierakstÄ«t. Tās ir tā sauktās slēdzenes.

ZooKeeper ļauj vienā vai otrā pakāpē atrisināt visas Ŕīs problēmas. Un es parādÄ«Å”u ar piemēriem, kā tas ļauj jums to izdarÄ«t.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Nav bloķējoÅ”u primitÄ«vu. Kad mēs sākam kaut ko lietot, Å”is primitÄ«vs negaidÄ«s, kad notiks kāds notikums. Visticamāk, Ŕī lieta darbosies asinhroni, tādējādi ļaujot procesiem neaizkavēties, kamēr tie kaut ko gaida. Å Ä« ir ļoti noderÄ«ga lieta.

Visi klientu pieprasījumi tiek apstrādāti vispārējās rindas kārtībā.

Un klientiem ir iespēja saņemt paziņojumu par izmaiņām kādā stāvoklī, par izmaiņām datos, pirms klients pats redz mainītos datus.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

ZooKeeper var strādāt divos režīmos. Pirmais ir savrups, vienā mezglā. Tas ir ērti testÄ“Å”anai. Tas var darboties arÄ« klastera režīmā jebkurā serveru skaitā. Ja mums ir 100 maŔīnu klasteris, tad nav nepiecieÅ”ams, lai tas strādātu uz 100 maŔīnām. Pietiek atlasÄ«t vairākas maŔīnas, kurās var palaist ZooKeeper. Un tas atbilst augstas pieejamÄ«bas principam. Katrā darbÄ«gajā instancē ZooKeeper saglabā visu datu kopiju. Vēlāk es jums pastāstÄ«Å”u, kā viņŔ to dara. Tas nesadala datus un nesadala tos. No vienas puses, tas ir mÄ«nuss, ka mēs nevaram daudz uzglabāt, no otras puses, tas nav jādara. Tas nav paredzēts tam, tā nav datubāze.

Datus var saglabāt keÅ”atmiņā klienta pusē. Å is ir standarta princips, lai mēs nepārtrauktu pakalpojumu un neielādētu to ar vienādiem pieprasÄ«jumiem. Gudrs klients parasti par to zina un saglabā to keÅ”atmiņā.

Piemēram, pie mums kaut kas ir mainÄ«jies. Ir sava veida pielietojums. Tika ievēlēts jauns vadÄ«tājs, kurÅ” atbild, piemēram, par rakstÄ«Å”anas darbÄ«bu apstrādi. Un mēs vēlamies replicēt datus. Viens risinājums ir ievietot to cilpā. Un mēs pastāvÄ«gi apÅ”aubām mÅ«su pakalpojumu - vai kas ir mainÄ«jies? Otrais variants ir optimālāks. Å is ir pulksteņa mehānisms, kas ļauj informēt klientus, ka kaut kas ir mainÄ«jies. Å Ä« ir resursu ziņā lētāka un klientiem ērtāka metode.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Klients ir lietotājs, kurŔ izmanto ZooKeeper.

Serveris ir pats ZooKeeper process.

Znode ir galvenais ZooKeeper. Visas znodes tiek glabātas atmiņā ZooKeeper un ir sakārtotas hierarhiskas diagrammas veidā koka formā.

Ir divu veidu operācijas. Pirmais ir atjaunināŔana/rakstīŔana, kad kāda darbība maina mūsu koka stāvokli. Koks ir kopīgs.

Un ir iespējams, ka klients neizpilda vienu pieprasījumu un tiek atvienots, bet var izveidot sesiju, caur kuru tas mijiedarbojas ar ZooKeeper.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

ZooKeeper datu modelis atgādina failu sistēmu. Ir standarta sakne, un tad mēs gājām cauri direktorijiem, kas iet no saknes. Un tad pirmā līmeņa, otrā līmeņa katalogs. Tas viss ir znodes.

Katrs znode var uzglabāt dažus datus, parasti ne pārāk lielus, piemēram, 10 kilobaitus. Un katrā znode var būt noteikts bērnu skaits.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Znodes ir vairāku veidu. Tos var izveidot. Un, veidojot znode, mēs norādām veidu, kuram tai vajadzētu piederēt.

Ir divi veidi. Pirmais ir Ä«slaicÄ«gs karogs. Znode dzÄ«vo sesijas ietvaros. Piemēram, klients ir izveidojis sesiju. Un, kamēr Ŕī sesija ir dzÄ«va, tā pastāvēs. Tas ir nepiecieÅ”ams, lai neradÄ«tu kaut ko nevajadzÄ«gu. Tas ir piemērots arÄ« brīžiem, kad mums ir svarÄ«gi sesijas ietvaros saglabāt datu primitÄ«vus.

Otrais veids ir secÄ«gs karogs. Tas palielina skaitÄ«tāju ceļā uz znode. Piemēram, mums bija direktorijs ar lietojumprogrammu 1_5. Un, kad mēs izveidojām pirmo mezglu, tas saņēma p_1, otro - p_2. Un, katru reizi izsaucot Å”o metodi, mēs izejam visu ceļu, norādot tikai daļu no ceļa, un Å”is skaitlis tiek automātiski palielināts, jo mēs norādām mezgla veidu - secÄ«gi.

Regulāra znode. Viņa vienmēr dzīvos un viņai būs vārds, ko mēs viņai sakām.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Vēl viena noderÄ«ga lieta ir pulksteņa karogs. Ja mēs to instalējam, klients var abonēt dažus notikumus konkrētam mezglam. Es jums parādÄ«Å”u vēlāk ar piemēru, kā tas tiek darÄ«ts. ZooKeeper pats informē klientu, ka mezglā ir mainÄ«juÅ”ies dati. Tomēr paziņojumi negarantē, ka ir saņemti daži jauni dati. Viņi vienkārÅ”i saka, ka kaut kas ir mainÄ«jies, tāpēc jums joprojām ir jāsalÄ«dzina dati vēlāk ar atseviŔķiem zvaniem.

Un kā jau teicu, datu secību nosaka kilobaiti. Tur nav jāglabā lieli teksta dati, jo tā nav datu bāze, tas ir darbību koordinācijas serveris.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Es jums pastāstÄ«Å”u nedaudz par sesijām. Ja mums ir vairāki serveri, mēs varam pārredzami pāriet no servera uz serveri, izmantojot sesijas identifikatoru. Tas ir diezgan ērti.

Katrai sesijai ir sava veida taimauts. Sesiju nosaka, vai klients Ŕīs sesijas laikā kaut ko nosÅ«ta serverim. Ja viņŔ taimauta laikā neko nepārsÅ«tÄ«ja, sesija tiek pārtraukta vai klients var to aizvērt pats.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Tam nav tik daudz funkciju, taču ar Å”o API varat veikt dažādas darbÄ«bas. Å is zvans, ko mēs redzējām, izveido znode un aizņem trÄ«s parametrus. Å is ir ceļŔ uz znode, un tas ir jānorāda pilnÄ«bā no saknes. Un arÄ« Å”ie ir daži dati, kurus mēs vēlamies tur pārsÅ«tÄ«t. Un karoga veids. Un pēc izveides tas atgriež ceļu uz znode.

Otrkārt, varat to izdzēst. Å eit viltÄ«ba ir tāda, ka otrais parametrs, papildus ceļam uz znode, var norādÄ«t versiju. AttiecÄ«gi Å”is znode tiks dzēsts, ja tā versija, kuru mēs pārsÅ«tÄ«jām, ir lÄ«dzvērtÄ«ga tai, kas faktiski pastāv.

Ja mēs nevēlamies pārbaudÄ«t Å”o versiju, mēs vienkārÅ”i nododam argumentu "-1".

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

TreÅ”kārt, tā pārbauda znode esamÄ«bu. Atgriež True, ja mezgls pastāv, false pretējā gadÄ«jumā.

Un tad parādās karoga pulkstenis, kas ļauj uzraudzīt Ŕo mezglu.

Varat iestatÄ«t Å”o karogu pat neesoÅ”am mezglam un saņemt paziņojumu, kad tas parādās. Tas var bÅ«t arÄ« noderÄ«gi.

Ir vēl pāris izaicinājumi getData. Ir skaidrs, ka mēs varam saņemt datus caur znode. Varat arī izmantot karoga pulksteni. Šajā gadījumā tas netiks instalēts, ja nav mezgla. Tāpēc jums ir jāsaprot, ka tas pastāv, un pēc tam jāsaņem dati.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Ir arī SetData. Šeit mēs nododam versiju. Un, ja mēs to nodosim, dati par noteiktas versijas znode tiks atjaunināti.

Varat arÄ« norādÄ«t "-1", lai izslēgtu Å”o pārbaudi.

Vēl viena noderÄ«ga metode ir getChildren. Mēs varam arÄ« iegÅ«t visu tai piederoÅ”o znode sarakstu. Mēs to varam uzraudzÄ«t, iestatot karoga pulksteni.

Un metode sinhronizēt ļauj nosÅ«tÄ«t visas izmaiņas uzreiz, tādējādi nodroÅ”inot, ka tās tiek saglabātas un visi dati ir pilnÄ«bā izmainÄ«ti.

Ja mēs velkam analoÄ£ijas ar parasto programmÄ“Å”anu, tad, ja izmantojat tādas metodes kā rakstÄ«Å”ana, kas ieraksta kaut ko diskā un pēc tam atgriež jums atbildi, nav garantijas, ka esat ierakstÄ«jis datus diskā. Un pat tad, kad operētājsistēma ir pārliecināta, ka viss ir uzrakstÄ«ts, paŔā diskā ir mehānismi, kur process iet cauri buferu slāņiem, un tikai pēc tam dati tiek ievietoti diskā.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Pārsvarā tiek izmantoti asinhronie zvani. Tas ļauj klientam strādāt paralēli ar dažādiem pieprasījumiem. Varat izmantot sinhrono pieeju, taču tā ir mazāk produktīva.

Divas darbÄ«bas, par kurām mēs runājām, ir atjaunināŔana/rakstÄ«Å”ana, kas maina datus. Tie ir izveidot, setData, sinhronizēt, dzēst. Un lasÄ«Å”ana pastāv, getData, getChildren.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Tagad daži piemēri, kā jÅ«s varat izveidot primitÄ«vus darbam sadalÄ«tā sistēmā. Piemēram, kas saistÄ«ts ar kaut kā konfigurāciju. Ir parādÄ«jies jauns darbinieks. Mēs pievienojām maŔīnu un sākām procesu. Un ir Ŕādi trÄ«s jautājumi. Kā tas vaicā ZooKeeper konfigurācijai? Un, ja mēs vēlamies mainÄ«t konfigurāciju, kā mēs to mainām? Un pēc tam, kad mēs to mainÄ«jām, kā tie darbinieki, kas mums bija, to iegÅ«st?

ZooKeeper to padara salÄ«dzinoÅ”i vienkārÅ”u. Piemēram, ir mÅ«su znode koks. Å eit ir mÅ«su lietojumprogrammas mezgls, tajā izveidojam papildu mezglu, kurā ir dati no konfigurācijas. Tie var bÅ«t vai nebÅ«t atseviŔķi parametri. Tā kā izmērs ir mazs, arÄ« konfigurācijas izmērs parasti ir mazs, tāpēc to Å”eit ir iespējams uzglabāt.

JÅ«s izmantojat metodi getData lai no mezgla iegÅ«tu darbinieka konfigurāciju. IestatÄ«t uz patiesu. Ja kāda iemesla dēļ Å”is mezgls neeksistē, mēs par to informēsim, kad tas parādÄ«sies vai mainÄ«sies. Ja mēs vēlamies zināt, ka kaut kas ir mainÄ«jies, tad mēs to nosakām kā patiesÄ«bu. Un, ja dati Å”ajā mezglā mainÄ«sies, mēs par to uzzināsim.

SetData. Mēs iestatām datus, iestatām ā€œ-1ā€, t.i., mēs nepārbaudām versiju, mēs pieņemam, ka mums vienmēr ir viena konfigurācija, mums nav jāuzglabā daudzas konfigurācijas. Ja jums ir nepiecieÅ”ams uzglabāt daudz, jums bÅ«s jāpievieno vēl viens lÄ«menis. Å eit mēs uzskatām, ka ir tikai viens, tāpēc mēs atjauninām tikai jaunāko, tāpēc mēs nepārbaudām versiju. Å obrÄ«d visi klienti, kuri ir iepriekÅ” abonējuÅ”i, saņem paziņojumu, ka Å”ajā mezglā kaut kas ir mainÄ«jies. Un pēc tam, kad viņi tos ir saņēmuÅ”i, viņiem tie arÄ« jāpieprasa vēlreiz. Paziņojums ir tāds, ka viņi nesaņem paÅ”us datus, bet tikai paziņojumu par izmaiņām. Pēc tam viņiem ir jāpieprasa jauni dati.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Otra primitÄ«va izmantoÅ”anas iespēja ir dalÄ«ba grupā. Mums ir izplatÄ«ta aplikācija, ir bariņŔ strādnieku un gribam saprast, ka viņi visi ir savās vietās. Tāpēc viņiem ir jāreÄ£istrējas, ka viņi strādā mÅ«su pieteikumā. Un mēs arÄ« vēlamies uzzināt vai nu no Meistara procesa, vai kaut kur citur par visiem aktÄ«vajiem darbiniekiem, kas mums Å”obrÄ«d ir.

Kā mēs to darām? Lietojumprogrammai mēs izveidojam darbinieku mezglu un pievienojam tur apakÅ”lÄ«meni, izmantojot izveides metodi. Man ir kļūda slaidā. Å eit tev vajag sequential norādiet, tad visi darbinieki tiks izveidoti pa vienam. Un lietojumprogramma, pieprasot visus datus par Ŕī mezgla bērniem, saņem visus esoÅ”os aktÄ«vos darbiniekus.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Å Ä« ir tik Å”ausmÄ«ga ievieÅ”ana, kā to var izdarÄ«t Java kodā. Sāksim no beigām, ar galveno metodi. Å Ä« ir mÅ«su klase, izveidosim tās metodi. Kā pirmo argumentu mēs izmantojam host, kur mēs savienojam, t.i., mēs to iestatām kā argumentu. Un otrs arguments ir grupas nosaukums.

Kā notiek savienojums? Å is ir vienkārÅ”s izmantotās API piemērs. Å eit viss ir salÄ«dzinoÅ”i vienkārÅ”i. Ir standarta klases ZooKeeper. Mēs nododam tai saimniekus. Un iestatiet taimautu, piemēram, uz 5 sekundēm. Un mums ir dalÄ«bnieks ar nosaukumu connectSignal. BÅ«tÄ«bā mēs izveidojam grupu pa pārraidÄ«to ceļu. Mēs tur nerakstām datus, lai gan kaut ko varēja ierakstÄ«t. Un mezgls Å”eit ir noturÄ«ga tipa. BÅ«tÄ«bā tas ir parasts regulārs mezgls, kas pastāvēs visu laiku. Å eit tiek izveidota sesija. Tā ir paÅ”a klienta Ä«stenoÅ”ana. MÅ«su klients periodiski sÅ«tÄ«s ziņojumus, norādot, ka sesija ir dzÄ«va. Un, kad mēs beidzam sesiju, mēs piezvanām aizvērt, un viss, sesija izkrÄ«t. Tas ir gadÄ«jumā, ja mums kaut kas nokrÄ«t, lai ZooKeeper par to uzzinātu un pārtrauktu sesiju.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Kā bloķēt resursu? Å eit viss ir nedaudz sarežģītāk. Mums ir strādnieku kopums, ir kāds resurss, ko vēlamies bloķēt. Lai to izdarÄ«tu, mēs izveidojam atseviŔķu mezglu, piemēram, ar nosaukumu lock1. Ja varējām to izveidot, tad dabÅ«jām Å”eit slēdzeni. Un, ja mēs nevarējām to izveidot, tad darbinieks mēģina iegÅ«t getData no Å”ejienes, un, tā kā mezgls jau ir izveidots, mēs ievietojam Å”eit novērotāju un tajā brÄ«dÄ«, kad mainÄ«sies Ŕī mezgla stāvoklis, mēs par to uzzināsim. Un mēs varam mēģināt atrast laiku, lai to atjaunotu. Ja mēs paņēmām Å”o mezglu, paņēmām Å”o slēdzeni, tad pēc tam, kad slēdzene mums vairs nebÅ«s vajadzÄ«ga, mēs to atteiksim, jo ā€‹ā€‹mezgls pastāv tikai sesijas ietvaros. AttiecÄ«gi tas pazudÄ«s. Un cits klients, citas sesijas ietvaros, varēs paņemt Ŕī mezgla slēdzeni, pareizāk sakot, saņems paziņojumu, ka kaut kas ir mainÄ«jies un var mēģināt to izdarÄ«t laicÄ«gi.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Vēl viens piemērs tam, kā var izvēlēties galveno vadÄ«tāju. Tas ir nedaudz sarežģītāks, bet arÄ« salÄ«dzinoÅ”i vienkārÅ”s. Kas Å”eit notiek? Ir galvenais mezgls, kas apkopo visus darbiniekus. Mēs cenÅ”amies iegÅ«t datus par vadÄ«tāju. Ja tas notika veiksmÄ«gi, t.i., mēs saņēmām dažus datus, tad mÅ«su darbinieks sāk sekot Å”im vadÄ«tājam. ViņŔ uzskata, ka jau ir lÄ«deris.

Ja vadÄ«tājs kādu iemeslu dēļ nomira, piemēram, nokrita, tad cenÅ”amies izveidot jaunu vadÄ«tāju. Un, ja mums izdodas, tad mÅ«su strādnieks kļūst par vadÄ«tāju. Un, ja kādam Å”ajā brÄ«dÄ« izdevās izveidot jaunu vadÄ«tāju, tad cenÅ”amies saprast, kas tas ir, un tad viņam sekot.

Šeit rodas tā saucamais bara efekts, t.i., bara efekts, jo, vadonim nomirstot, par vadītāju kļūs tas, kurŔ laikā ir pirmais.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Tverot resursu, varat mēģināt izmantot nedaudz atŔķirÄ«gu pieeju, kas ir Ŕāda. Piemēram, mēs vēlamies iegÅ«t slēdzeni, bet bez herta efekta. Tas sastāvēs no tā, ka mÅ«su lietojumprogramma pieprasa visu mezglu ID sarakstus jau esoÅ”am mezglam ar bloÄ·Ä“Å”anu. Un, ja pirms tam mezgls, kuram mēs izveidojām slēdzeni, ir mazākais no komplekta, ko mēs saņēmām, tad tas nozÄ«mē, ka esam fiksējuÅ”i slēdzeni. Pārbaudām, vai esam saņēmuÅ”i slēdzeni. Pārbaudei bÅ«s nosacÄ«jums, ka id, ko saņēmām, veidojot jaunu slēdzeni, ir minimāls. Un, ja saņēmām, tad strādājam tālāk.

Ja ir noteikts id, kas ir mazāks par mÅ«su slēdzeni, tad Å”im notikumam ievietojam novērotāju un gaidām paziņojumu, lÄ«dz kaut kas mainÄ«sies. Tas ir, mēs saņēmām Å”o slēdzeni. Un kamēr tas nenokritÄ«s, mēs nekļūsim par minimālo id un nesaņemsim minimālo slēdzeni un lÄ«dz ar to varēsim ielogoties. Un, ja Å”is nosacÄ«jums nav izpildÄ«ts, tad uzreiz ejam uz Å”ejieni un mēģinām Å”o slēdzeni dabÅ«t vēlreiz, jo pa Å”o laiku varētu bÅ«t kaut kas mainÄ«jies.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

No kā sastāv ZooKeeper? Ir 4 galvenās lietas. Tie ir apstrādes procesi - Pieprasījums. Un arī ZooKeeper Atomic Broadcast. Ir saistību žurnāls, kurā tiek reģistrētas visas darbības. Un pati In-memory Replicated DB, t.i., pati datu bāze, kurā tiek glabāts viss koks.

Ir vērts atzÄ«mēt, ka visas rakstÄ«Å”anas darbÄ«bas tiek veiktas caur pieprasÄ«jumu procesoru. Un lasÄ«Å”anas darbÄ«bas nonāk tieÅ”i atmiņas datubāzē.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Pati datu bāze ir pilnībā replicēta. Visi ZooKeeper gadījumi saglabā pilnīgu datu kopiju.

Lai atjaunotu datubāzi pēc avārijas, tiek izveidots Commit žurnāls. Standarta prakse ir tāda, ka pirms datu nokļūŔanas atmiņā tie tiek ierakstÄ«ti tur, lai, ja tas avarē, Å”o žurnālu varētu atskaņot un atjaunot sistēmas stāvokli. Tiek izmantoti arÄ« periodiski datu bāzes momentuzņēmumi.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

ZooKeeper Atomic Broadcast ir lieta, ko izmanto replicētu datu uzturÄ“Å”anai.

ZAB iekŔēji izvēlas lÄ«deri no ZooKeeper mezgla viedokļa. Citi mezgli kļūst par viņas sekotājiem un sagaida no viņas dažas darbÄ«bas. Ja viņi saņem ierakstus, viņi tos visus pārsÅ«ta vadÄ«tājam. Vispirms viņŔ veic rakstÄ«Å”anas darbÄ«bu un pēc tam nosÅ«ta saviem sekotājiem ziņu par to, kas ir mainÄ«jies. Tas faktiski ir jāveic atomiski, t.i., visas lietas ierakstÄ«Å”anas un pārraidÄ«Å”anas darbÄ«ba jāveic atomiski, tādējādi garantējot datu konsekvenci.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatÄ«tai apstrādei Hadoop" Tas apstrādā tikai rakstÄ«Å”anas pieprasÄ«jumus. Tās galvenais uzdevums ir pārveidot darbÄ«bu par darÄ«jumu atjauninājumu. Å is ir Ä«paÅ”i Ä£enerēts pieprasÄ«jums.

Un Å”eit ir vērts atzÄ«mēt, ka tiek garantēta vienas un tās paÅ”as darbÄ«bas atjauninājumu idempotence. Kas tas ir? Å ai lietai, ja tā tiks izpildÄ«ta divas reizes, bÅ«s tāds pats stāvoklis, t.i., pats pieprasÄ«jums nemainÄ«sies. Un tas ir jādara, lai avārijas gadÄ«jumā jÅ«s varētu restartēt darbÄ«bu, tādējādi atceļot izmaiņas, kas Å”obrÄ«d ir izkrituÅ”as. Å ajā gadÄ«jumā sistēmas stāvoklis kļūs vienāds, t.i., nevajadzētu bÅ«t tā, ka virkne vienādu, piemēram, atjaunināŔanas procesu noveda pie dažādiem sistēmas gala stāvokļiem.

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

"Hadoop. ZooKeeper" no Mail.Ru Group Technostream sērijas "Metodes liela apjoma datu izplatītai apstrādei Hadoop"

Avots: www.habr.com

Pievieno komentāru