
Shumë njerëz përballen me Elasticsearch. Por çfarë ndodh kur dëshiron të ruash log-e "në një masë të madhe" me ndihmën e tij? Ndonjëherë, si mund ta kalosh pa dhimbje dështimin e ndonjë qendre të të dhënave? Si duhet të jetë arkitektura dhe cilat janë pengesat që mund të hasësh?
Ne në Odnoklassniki vendosëm të zgjidhim çështjen e menaxhimit të log-eve me elasticsearch dhe tani po ndajmë me Habr përvojën tonë: për arkitekturën dhe pengesat.
UnĂ« jam Pyotr Zaitsev, punoj si administrator sistemi nĂ« Odnoklassniki. PĂ«rpara se tĂ« isha administrator, kam punuar me Manticore Search, Sphinx Search, Elasticsearch. Ndoshta, nĂ«se do tĂ« shfaqet ndonjĂ« âŠsearch tjetĂ«r, do tĂ« punoj edhe me tĂ«. Gjithashtu, marr pjesĂ« nĂ« disa projekte open-source nĂ« mĂ«nyrĂ« vullnetarizmi.
Kur erdha në Odnoklassniki, thashë me guxim në intervistën e punës se di të punoj me Elasticsearch. Pasi e mësova dhe bëra disa detyra të thjeshta, më dhanë një detyrë të madhe për reformimin e sistemit të menaxhimit të log-eve që ekzistonte në atë kohë.
Kërkesat
Kërkesat për sistemin u formuluan si më poshtë:
- Si frontend duhej të përdorej Graylog. Sepse në kompani tashmë kishte përvojë me këtë produkt, programuesit dhe testuesit e dinin, ishte i njohur dhe i lehtë për t'u përdorur.
- Vëllimi i të dhënave: në mesatare 50-80 mijë mesazhe në sekondë, por nëse diçka thyhet, trafiku nuk është i kufizuar, mund të jetë 2-3 milion rreshta në sekondë.
- Pas diskutimit të kërkesave me klientët për shpejtësinë e përpunimit të kërkesave në kërkim, ne kuptuam se modeli tipik i përdorimit të këtij sistemi është: njerëzit kërkojnë log-et e aplikacionit të tyre për dy ditët e fundit dhe nuk duan të presin më shumë se një sekondë për rezultatin e kërkesës së formuluar.
- Adminët Insistuan që sistemi të ishte i lehtë për t'u shkallëzuar në rast nevoje, pa kërkuar prej tyre një kuptim të thellë se si ishte ndërtuar.
- Përveç kësaj, në Odnoklassniki ekziston një traditë e shkëlqyer teknike: çdo shërbim që nisim duhet të përballojë dështimin e qendrës së të dhënave (papritur, pa planifikim dhe në çdo kohë).
- Gjithashtu, përveç kësaj, ka një traditë të shkëlqyer teknike në Odnoklassniki: çdo shërbim që ne nisem duhet të përballojë dështimin e qendrës së të dhënave (papritur, pa plan dhe në çdo kohë).
Kërkesat më të fundit për realizimin e këtij projekti na kanë kushtuar më së shumti, për të cilën do të flas më në detaje.
Mjedisi
Ne punojmë në katër qendra të të dhënave, ndërsa nodet e Elasticsearch mund të vendosen vetëm në tri (për disa arsye joteknike).
NĂ« kĂ«to katĂ«r qendra tĂ« tĂ« dhĂ«nave ndodhen rreth 18,000 burime tĂ« ndryshme tĂ« logĂ«ve â pajisje, kontejnerĂ«, makina virtuale.
Një veçori e rëndësishme: nisja e klasterit ndodh në kontejnerë jo në makina fizike, por në . Konejnerëve u garantohet 2 bërthama, të ngjashme me 2.0Ghz v4 me mundësi për të shfrytëzuar bërthamën tjetër, në rast se ato janë të papunuara.
Me fjalë të tjera:

Topologjia
Pamja e përgjithshme e zgjidhjes më është dukur fillimisht si më poshtë:
- 3-4 VIP qëndrojnë pas A-record-it të domenit Graylog, kjo është adresa ku dërgohen logët.
- çdo VIP është një balancues LVS.
- Pas tij, logët kalojnë në një grumbull Graylog, disa të dhëna janë në formatin GELF, disa në formatin syslog.
- Pastaj, të gjitha këto shkruhen në mënyrë të madhe në një grumbull të koordinatoreve Elasticsearch.
- Dhe ata, nga ana e tyre, dërgojnë kërkesa për shkruanie dhe lexim te nodet përkatëse.

Terminologjia
Ndoshta, jo të gjithë janë të njohur me terminologjinë, prandaj do të doja të ndalesha pak mbi të.
NĂ« Elasticsearch ka disa lloje nodash â master, coordinator, data node. Ka edhe dy lloje tĂ« tjera pĂ«r transformime tĂ« ndryshme tĂ« logĂ«ve dhe lidhjen mes klastereve tĂ« ndryshme, por ne kemi pĂ«rdorur vetĂ«m ato tĂ« pĂ«rmendura.
Master
Pingar çdo nod në klaster, mbështet hartën aktuale të klasterit dhe e shpërndan atë mes nodave, përpunon logjikën e ngjarjeve dhe merret me lloje të ndryshme të mirëmbajtjes në nivel klasteri.
Koordinatori
Kryen një detyrë të vetme: pranon kërkesat nga klientët për lexim ose shkruanie dhe organizon këtë trafik. Në rast se kërkesa është për shkruanie, është shumë e mundshme që ai të pyesë master-in se në cilin shard të indeksit përkatës ta vendosë atë dhe ta ridrejtojë kërkesën më tej.
Data node
Ruaj të dhënat, përpunon kërkesat e kërkimit që vijnë nga jashtë dhe operacione mbi shard-et e vendosura aty.
Graylog
Kjo është diçka si një përzierje Kibana me Logstash në ELK-stack. Graylog kombinon UI dhe procesin e përpunimit të skedarëve të logjeve. Nën kapak, në Graylog punojnë Kafka dhe Zookeeper, të cilat sigurojnë lidhshmërinë e Graylog si një klaster. Graylog mund të ruajë logjet (Kafka) për rastet kur Elasticsearch nuk është i arritshëm dhe të përsërisë kërkesat e dështuara për lexim dhe shkrim, duke grupuar dhe etiketuar logjet sipas rregullave të vendosura. Ashtu si Logstash, Graylog ka funksionalitetin për të modifikuar stringjet përpara se t'i shkruajë në Elasticsearch.
Për më tepër, në Graylog ka një zbulesë shërbimi të integruar, e cila lejon që, mbi bazën e një njësie të disponueshme Elasticsearch, të merret e gjithë karta e klasterit dhe ta filtrojë atë sipas një etikete të caktuar, duke e bërë të mundur dërgimin e kërkesave në konteinerë të caktuar.
Vishevisht kjo duket kështu:

Kjo është një screenshot nga një instancë specifike. Këtu ne ndërtojmë histogramin në bazë të kërkesës, duke shfaqur stringjet relevante.
Indeksi
Duke u kthyer në arkitekturën e sistemit, do të doja të ndalesha më në hollësi mbi se si ne ndërtuam modelin e indekseve, në mënyrë që gjithçka të funksionojë saktë.
Në skemën e përmendur më parë, ky është niveli më i ulët: Elasticsearch data nodes.
Indeksi Ă«shtĂ« njĂ« ent virtual i madh, qĂ« pĂ«rbĂ«het nga shardet e Elasticsearch. Ădo shard Ă«shtĂ« asgjĂ« tjetĂ«r, veçse njĂ« indeks Lucene. Dhe çdo indeks Lucene, nga ana e tij, pĂ«rbĂ«het nga njĂ« ose mĂ« shumĂ« segmente.

GjatĂ« projektimit, ne parashikuam se pĂ«r tĂ« pĂ«rmbushur kĂ«rkesĂ«n pĂ«r shpejtĂ«sinĂ« e leximit mbi njĂ« volum tĂ« madh tĂ« dhĂ«nash, na duheshin tĂ« âshpĂ«rndanimâ kĂ«to tĂ« dhĂ«na nĂ« mĂ«nyrĂ« tĂ« barabartĂ« nĂ« data nodes.
Kjo rezultoi në faktin se numri i shardeve për indeks (me replikat) duhet të jetë strikt njësoj me numrin e data nodes. Së pari, për të siguruar një faktor replikimi të barabartë me dy (pra mund të humbasim gjysmën e klasterit). Dhe, së dyti, për të përpunuar kërkesat për lexim dhe shkrim, si minimalisht, në gjysmën e klasterit.
Koha e ruajtjes fillimisht u përcaktua si 30 ditë.
Shpërndarja e shardëve mund të paraqitet grafike kështu:

E gjithë drejtkëndëshi i errët është indeksi. Kuadrati i kuq në të majtë është primary shard, i pari në indeks. Ndërsa kuadrati blu është replica shard. Ato ndodhen në data-centra të ndryshëm.
Kur ne shtojmë një shard tjetër, ai shkon në qendrën e të dhënave të tretë. Dhe, në fund, ne marrim këtë strukturë, e cila siguron mundësinë e humbjes së DC pa humbje të konsistencës së të dhënave:

Rrotacioni i indekseve, pra krijimi i një indeksi të ri dhe fshirja e indeksit më të vjetër, e bëmë të barabartë me 48 orë (sipër bazës së përdorimit të indeksit: për 48 orët e fundit kërkohet më shpesh).
Ky interval rrotacioni i indekseve është i lidhur me arsyet e mëposhtme:
Kur në një nodë të dhënash vjen një kërkesë kërkimi, nga pikëpamja e performancës është më e favorshme kur pyetet një shard, nëse dimensioni i tij është i krahasueshëm me madhësinë e hips së nodës. Kjo lejon mbajtjen e pjesës "të nxehtë" të indeksit në hip dhe qasjen ndaj saj me shpejtësi. Kur bëhen shumë "pjesë të nxehta", shpejtësia e kërkimit në indeks degradohet.
Kur një nodë fillon të ekzekutojë një kërkesë kërkimi në një shard, ajo ndan numrin e thredhjeve, të barabartë me numrin e bërthamave të hyper-threaded të makinës fizike. Nëse kërkesa e kërkimit prek një numër të madh shard-esh, atëherë numri i thredhjeve rritet në proporcjon. Kjo reflektohet negativisht në shpejtësinë e kërkimit dhe ndikon negativisht në indeksimin e të dhënave të reja.
Për të siguruar latency-n e nevojshme të kërkimit, ne vendosëm të përdorim SSD. Për procesimin e shpejtë të kërkesave, makinat në të cilat ishin vendosur këto konteinerë duhej të kishin të paktën 56 bërthama. Numri 56 është zgjedhur si një vlerë e kondicionuar e mjaftueshme, që përcakton numrin e thredhëve që do të gjenerojë Elasticsearch gjatë funksionimit. Në Elasticsearch, shumë parametra të thread pool varen drejtpërdrejt nga numri i bërthamave të disponueshme, që nga ana tjetër ndikon drejtpërdrejt në numrin e nevojshëm të nodave në klaster sipas parimit "më pak bërthama - më shumë nodë".
Si rezultat, na doli se, nĂ« mesatare, njĂ« shard ka rreth 20 gigabajt, dhe pĂ«r 1 indeks ka 360 shard-e. Prandaj, nĂ«se i rrotatojmĂ« çdo 48 orĂ«, do tĂ« kemi 15 prej tyre. Ădo indeks pĂ«rfshin tĂ« dhĂ«nat pĂ«r 2 ditĂ«.
Skemat e shkruajtjes dhe leximit të të dhënave
Le të shqyrtojmë se si regjistrohen të dhënat në këtë sistem.
Supozoni se nga Graylog na vjen një kërkesë në koordinator. Për shembull, duam të indeksojmë 2-3 mijë rreshta.
Kordinatori, pasi merr një kërkesë nga Graylog, pyet masterin: "Në kërkesën për indeksim, ne specifikisht kemi treguar indeksin, por nuk është e specifikuar se në cilin shard duhet të shkruajmë."
Masteri përgjigjet: "Shkruaj këtë informacion në shard numër 71", pas të cilit ajo dërgohet drejtpërdrejt në nodën përkatëse të të dhënave, ku ndodhet primary-shard numër 71.
Pas kësaj, logu i transaksioneve repliktohet në replica-shard, i cili ndodhet tashmë në një qendër të dhënash tjetër.

Nga Graylog, në kordinatorin vjen një kërkesë për kërkim. Kordinatorin e redirecton atë sipas indeksit, ndërsa Elasticsearch ndan kërkesat midis primary-shard dhe replica-shard në mënyrë round-robin.

Nodet, në numër prej 180, përgjigjen në mënyrë të paekuilibruar, dhe, ndërsa ato përgjigjen, kordinatorin mbledh informacionin që është "përshtatur" në të nga nodet më të shpejta të të dhënave. Pas kësaj, kur ose të gjithë informacioni ka ardhur, ose është arritur kufiri i kërkesës, i jep të gjitha drejtpërdrejt klientit.
E gjithë kjo sistem mesatarisht përpunon kërkesat për kërkim për 48 orët e fundit brenda 300-400ms, duke përjashtuar ato kërkesa që kanë leading wildcard.
"Lule" me Elasticsearch: Konfigurimi i Java-s.

Për të bërë që gjithçka të funksionojë siç e donim fillimisht, ne e kemi rregulluar për një kohë të gjatë një sërë gjërash në klaster.
Pjesa e parë e problemeve të zbuluara ishte e lidhur me mënyrën se si Java është e parakonfiguruar nga Elasticsearch.
Problemi i parë.
Ne vëzhguam një numër të madh njoftimesh se në nivelin Lucene, kur janë aktivizuar punët në sfond, bashkimet e segmenteve Lucene përfundojnë me gabim. Në log nuk dukej se ka patur OutOfMemoryError. Nga telemetria, ne pamë se hapi ishte i lirë, dhe nuk ishte e qartë se pse kjo operacion dështonte.
Doli se bashkimet e indekseve Lucene ndodhnin jashtë hapësirës së memories. Dhe kontejnerët ishin shumë ashpër të kufizuar në burimet e përdorura. Në këto burime hynte vetëm hapi (vlera heap.size ishte afërsisht e barabartë me RAM-in), dhe disa operacione off-heap dështonin me gabim alokimi, nëse për një arsye të ndonjë lloj nuk përputheshin në ato ~500MB që mbeteshin deri në limit.
Zgjidhja ishte mjaft triviale: ne rritëm sasinë e RAM-it të disponueshëm për kontejnerin, pas së cilës harrojmë për këto probleme që kemi pasur.
Problemi i dytë.
Pas 4-5 ditësh nga aktivizimi i klasterit, ne vëzhguam se nodet e të dhënave fillojnë të dalin periodikisht nga klasteri dhe të hyjnë në të pas 10-20 sekondash.
Kur na filluam të shqyrtonim, u sendeua se kjo memorie off-heap në Elasticsearch nuk kontrollohet pothuajse fare. Kur i dhamë kontejnerit më shumë memorie, morëm mundësinë të mbushnim direkt grupet e tamponëve me informacion të ndryshëm, dhe ajo u pastrua vetëm pasi kishte filluar GC eksplicit nga Elasticsearch.
Në disa raste, kjo operacion ndodhte mjaft ngadalë, dhe gjatë kësaj kohe klasteri kishte arritur ta shënonte këtë nod si të dalë. Ky problem është përshkruar mirë. .
Zgjidhja ishte si më poshtë: ne kufizuam Java-n që të përdorë pjesën më të madhe të memories jashtë heap për këto operacione. Ne e kufizuam deri në 16 gigabajt (-XX:MaxDirectMemorySize=16g), duke arritur që GC eksplicit të thirrej shumë më shpesh dhe të punonte shumë më shpejt, duke mos e destabilizuar kështu klasterin.
Problemi i tretë
Nëse mendoni se problemet me "nodet që lënë klasterin në momentin më të papritur" përfundojnë këtu, jeni në gabim.
Kur konfiguruam punën me indekset, ne vendosëm për mmapfs, për të në sharda të freskëta me segmentim të madh. Kjo ishte një gabim mjaft i rëndë, sepse me përdorimin e mmapfs, skedari mapohet në memorien operuese, dhe pastaj ne punojmë me skedarin e mapuar. Për këtë arsye, kur GC përpiqet të ndalë thread-et në aplikacion, ne shkojmë shumë ngadalë në safepoint, dhe në rrugen drejt tij, aplikacioni ndalet të përgjigjet ndaj kërkesave të masterit për të kuptuar nëse është akoma aktiv. Për pasojë, master-i mendon se nodi nuk është më në klaster. Pas rreth 5-10 sekondave, garbage collector punon, nodi rikthehet, futet përsëri në klaster dhe fillon inicializimin e shardave. Gjithë kjo shumë më shumë i ngjante "prodhimit që e merituam" dhe nuk ishte e përshtatshme për ndonjë gjë serioze.
Për të shpëtuar nga ky sjellje, ne së pari kaluam në standardin niofs, dhe më pas, kur migruam nga versionet pesë të Elastic në të gjashtat, provuam hybridfs, ku ky problem nuk u reproduktua. Më shumë për llojet e ruajtjes mund të lexoni. .
Problemi i katërt
Pastaj kishte një problem tjetër shumë interesante, të cilin e trajtuam për një kohë rekord. E kapëm atë për 2-3 muaj, sepse ishte krejtësisht e paqartë mënyra e saj.
NdonjĂ«herĂ« koordinuesit tanĂ« shkonin nĂ« Full GC, zakonisht diku pas drekĂ«s, dhe nga aty nuk ktheheshin mĂ«. GjatĂ« regjistrimit tĂ« vonesave tĂ« GC, kjo dukej kĂ«shtu: gjithçka shkonte mirĂ«, mirĂ«, mirĂ«, pastaj papritmas â dhe gjithçka bĂ«hej ndryshe.
Fillimisht menduam se kishim një përdorues të keq që po ekzekutonte një kërkesë, e cila po nxirrte koordinuesin nga funksionimi. Kemi regjistruar gjatë për kërkesat, duke u munduar të zbulojmë çfarë po ndodhte.
Në fund u zbulua se në momentin kur ndonjë përdorues po ekzekutonte një kërkesë të madhe dhe ajo i kalonte në një koordinues specifik Elasticsearch, disa nodet përgjigjeshin më ngadalë se të tjerët.
Dhe koha që koordinuesi priste përgjigjet nga të gjitha nodet, ai mblidhnin rezultate të dërguara nga nodet që kishin përfunduar. Për GC, kjo do të thotë se modeli i përdorimit të heap-it ndryshonte shumë shpejt. Dhe ai GC që ne përdorëm, nuk përballonte këtë detyrë.
I vetmi zgjidhje që gjetëm për të ndryshuar sjelljen e klasit në një situatë të tillë ishte migrimi në JDK13 dhe përdorimi i mbledhësit të mbetjeve Shenandoah. Kjo e zgjidhi problemin, koordinuesit tanë nuk ranë më.
Me këtë problemin me Java e mbyllëm dhe filluam problemet me kapacitetin.
«Frutat» me Elasticsearch: kapaciteti

Problemet me kapacitetin nënkuptojnë se klasteri ynë funksionon me stabilitet, por në pikun e numrit të dokumenteve të indeksuara dhe gjatë manovrave, performanca është e pamjaftueshme.
Simptoma e parë e hasur: gjatë disa «eksplodimeve» në prodhim, kur gjenerohej papritur një numër shumë i madh logësh, në Graylog shpesh shfaqej gabimi i indeksimit es_rejected_execution.
Kjo ndodhte për shkak se thread_pool.write.queue në një nodë të dhënash, deri në momentin kur Elasticsearch është në gjendje të përpunojë kërkesën për indeksimin dhe të dërgojë informacionin në shardin në disk, sipas parazgjedhjes është në gjendje të ruajë vetëm 200 kërkesa. Dhe në për këtë Parametër thuhet shumë pak. Tregohet vetëm numri maksimal i thread-ëve dhe madhësia e parazgjedhur.
Sigurisht, ne shkuam ta rregullojmë këtë vlerë dhe zbuluam këtë: konkretisht në konfigurimin tonë, ruhet mjaft mirë deri në 300 kërkesa, ndërsa një vlerë më e madhe është e rrezikshme sepse ne sërish shkojmë në Full GC.
PĂ«r mĂ« tepĂ«r, duke qenĂ« se kĂ«to janĂ« grupe mesazhesh qĂ« vijnĂ« brenda njĂ« kĂ«rkese, ishte e nevojshme tĂ« rregullohej Graylog qĂ« tĂ« shkruante jo shpesh dhe me grupe tĂ« vogla, por me grupe tĂ« mĂ«dha ose çdo 3 sekonda, nĂ«se grupi ende nuk Ă«shtĂ« plot. NĂ« kĂ«tĂ« rast, informata qĂ« shkruajmĂ« nĂ« Elasticsearch bĂ«het e ĐŽĐŸŃŃŃĐżshme jo brenda dy sekondave, por brenda pesĂ« (çka na pĂ«rshtatet mjaft), por numri i ritrajeve qĂ« duhet tĂ« bĂ«jmĂ« pĂ«r tĂ« shtyrĂ« njĂ« grup tĂ« madh informacioni zvogĂ«lohet.
Kjo Ă«shtĂ« veçanĂ«risht e rĂ«ndĂ«sishme nĂ« ato momente kur ndodhi ndonjĂ« problem dhe gjĂ«ra tĂ« tilla pĂ«r tĂ« mos marrĂ« njĂ« Elastic tĂ« mbushur plot, dhe pas njĂ« kohe â node tĂ« pa funksionueshme pĂ«r shkak tĂ« mbushjes sĂ« buferĂ«ve tĂ« Graylog.
Për më tepër, kur ndodhnin këto shpërthime në prodhim, merrnim ankesa nga programuesit dhe testuesit: në momentin që u duhej shumë këto log-e, ato jepeshin shumë ngadalë.
Filluam të hetonim. Nga njëra anë, ishte e qartë se kërkesat e kërkimit dhe kërkesat për indeksim punonin, në thelb, në të njëjtat makina fizike, dhe në çdo rast do të kishte disa ulje.
Por kjo mund të evitohej pjesërisht për shkak se në versionet e gjashta të Elasticsearch doli një algoritëm që lejonte shpërndarjen e kërkesave midis data-node-ve përkatëse jo në një mënyrë të rastësishme round-robin (kontejneri që merret me indeksimin dhe mban primary-shard mund të jetë shumë i ngarkuar, nuk do të kishte mundësi të përgjigjej shpejt), por për të drejtuar këtë kërkesë në një kontejner më pak të ngarkuar me replica-shard, i cili do të përgjigjej ndjeshëm më shpejt. Në fjalë të tjera, arritëm në use_adaptive_replica_selection: true.
Pamja e leximit fillon të duket kështu:

Kalimi në këtë algoritëm lejoj të përmirësohej ndjeshëm koha e kërkimit në ato momente kur kishte një fluks të madh log-esh për të shkruar.
SĂ« fundmi, problemi kryesor ishte dalja pa dhimbje e datacenter-it.
ĂfarĂ« doja nga klasteri menjĂ«herĂ« pas humbjes sĂ« lidhjes me njĂ« DC:
- Nëse në datacenter-in e humbur ndodhet master aktual, ai do të rivotësohet dhe do të kalojë si rol në një node tjetër në një DC tjetër.
- Masteri do të përjashtojë shpejt nga klasteri të gjitha node-të e pa akses.
- Duke u bazë të atyre që kanë mbetur, ai do të kuptojë: në qendrën e të dhënave të humbura kemi pasur këto primary-shard, do t'i promovojë shpejt shard-et e replikuara në qendrat e mbetura të të dhënave, dhe indeksoni të dhënat do të vazhdojë.
- Si rezultat, kapaciteti i shkrimit dhe leximit të klasterit do të degradojë ngadalë, megjithatë në përgjithësi gjithçka do të funksionojë, ndonëse me ngadalësi, por me stabilitet.
Siç doli, ne doja diçka si kjo:

Dhe morëm këtë:

Si ndodhi kjo?
Në momentin e rënies së qendrës së të dhënave, pika jonë e ngushtë ishte masteri.
Pse?
E gjithĂ« çështja Ă«shtĂ« se nĂ« master ka njĂ« TaskBatcher, qĂ« Ă«shtĂ« pĂ«rgjegjĂ«s pĂ«r shpĂ«rndarjen e detyrave dhe aktiviteteve tĂ« caktuara nĂ« klaster. Ădo dalje e nodĂ«s, çdo promovim i shard-it nga replica nĂ« primary, çdo detyrĂ« pĂ«r tĂ« krijuar ndonjĂ« shard diku â gjithçka kalon fillimisht nĂ« TaskBatcher, ku pĂ«rpunohen njĂ« pas njĂ« dhe nĂ« njĂ« rrjedhĂ«.
Në momentin e daljes së një qendre të dhënash, dukej se të gjithë nodat e mbetura në qendrat e mbetura të dhënash besonin se ishte detyra e tyre t'i thonin masterit 'ne humbëm këto shard dhe këto data-node.'
Ndërsa node-t e mbetura dërgonin të gjithë këtë informacion te masteri aktual dhe përpiqeshin të prisnin konfirmimin se ai e kishte pranuar. Ata nuk prisnin këtë, pasi masteri merrte detyrat më shpejt se sa arrinte të përgjigjej. Nodat përsërisnin kërkesat pas skadimit, ndërsa masteri në atë kohë nuk përpiqej as të përgjigjej, por ishte plotësisht i zënë me detyrën e renditjes së kërkesave sipas prioriteteve.
Në formën e fundit, dukej se nodat e të dhënave po bombarduan masterin deri sa ai shkonte në full GC. Pas kësaj, roli i masterit kalonte në ndonjë nodë tjetër, me të cilën ndodhte krejtësisht e njëjta gjë, dhe përfundimisht klasteri shkatërrohej plotësisht.
Ne bëmë matje dhe deri në versionin 6.4.0, ku ky problem u zgjidh, ishte mjaft për të nxjerrë njëkohësisht vetëm 10 data-node nga 360 që të bllokonim plotësisht klasterin.
Kjo dukej në këtë mënyrë:

Pas versionit 6.4.0, ku ky defekt serioz u korrigjua, node-t e të dhënave nuk e vrisnin më masterin. Por ai nuk bëhej 'më i zgjuar' nga kjo. Saktësisht: kur ne nxjerrim 2, 3 ose 10 (çdo numër përveç një) data-node, masteri merr një mesazh të parë që thotë se nodi A doli dhe përpiqet të tregojë për këtë për nodin B, nodin C, nodin D.
Dhe në momentin aktual, kjo mund të luftohet vetëm duke vendosur një kohë të caktuar për tentativat për të treguar dikujt diçka, që është rreth 20-30 sekonda, dhe kështu të menaxhohet shpejtësia e daljes së qendrës së të dhënave nga klasteri.
Në parim, kjo përputhet me kërkesat që ishin fillimisht vendosur për produktin përfundimtar në kuadër të projektit, por nga pikëpamja e 'shkencës së pastër' kjo është një defekt. Ky, për të cilin, me të vërtetë, ishte rregulluar me sukses nga zhvilluesit në versionin 7.2.
Gjithashtu, kur një nod i dhënash dilte, rezultonte se përhapja e informacionit rreth daljes së saj ishte më e rëndësishme se të tregoheshin të gjithë klasterit se në të ishin këto primary-shard (për të promovuar replica-shard në një qendër tjetër të të dhënave në primary, dhe aty mund të shkruhej informacioni).
Prandaj, kur gjithçka 'ka shkuar', nodet e dalura nuk shënohen si stale menjëherë. Për rrjedhojë, ne jemi të detyruar të presim deri sa të kalojnë të gjitha pings për nodet e dalura dhe vetëm pas kësaj klasteri ynë fillon të tregojë se atje, atje dhe atje duhet të vazhdohet regjistrimi i informacionit. Më shumë detaje mund të lexoni për këtë. .
Më në fund, operacioni i daljes së qendrës së të dhënave sot zë rreth 5 minuta në orët e pikut. Për një makinë kaq të madhe dhe të ngadaltë, ky është një rezultat mjaft i mirë.
Më në fund, ne arritëm në zgjidhjen në vazhdim:
- Ne kemi 360 nodet e dhënash me disqe 700 gigabajt.
- 60 koordinatorë për të rregulluar trafikun në këto nodet e dhënash.
- 40 mastera, tĂ« cilat na kanĂ« mbetur si njĂ« trashĂ«gimi nga versionet para 6.4.0 â pĂ«r tĂ« pĂ«rballuar daljen e qendrĂ«s sĂ« tĂ« dhĂ«nave, ne ishim psikologjikisht tĂ« gatshĂ«m tĂ« humbnim disa makina, pĂ«r tĂ« garantuar qĂ« edhe nĂ« skenarin mĂ« tĂ« keq tĂ« kishim njĂ« kuorum masterash.
- Ădo pĂ«rpjekje pĂ«r tĂ« bashkuar role nĂ« njĂ« kontejner na hasi nĂ« faktin se herĂ«t a vonĂ« nodi thyhej nĂ«n ngarkesĂ«.
- Në të gjithë klasterin përdoret heap.size, i barabartë me 31 gigabajt: të gjitha përpjekjet për të zvogëluar madhësinë çoi në atë që në kërkesat e rënda të kërkimit me wildcard të paracaktuar ose vrasin disa nodet, ose thyen circuit breaker në vetë Elasticsearch.
- Përveç kësaj, për të siguruar performancën e kërkimit, ne përpiqeshim të mbajmë numrin e objekteve në klaster sa më minimal të jetë e mundur, për të përpunuar sa më pak ngjarje në vendin më të ngushtë që kemi arritur në master.
Në fund për monitorimin
Për të siguruar që gjithçka të funksionojë siç pritej, ne monitorojmë:
- Ădo data-node raporton nĂ« re se ajo ekziston dhe ka kĂ«to sharda tĂ« vendosur. Kur ne fikim diçka, klasteri raporton pas 2-3 sekondash se ne nĂ« qendrĂ«n A kemi fikur node 2, 3, dhe 4 â kjo do tĂ« thotĂ« se nĂ« qendrat e tjera tĂ« tĂ« dhĂ«nave, ne nuk mund tĂ« fikim ato nodes ku ka sharda tĂ« vetme.
- Duke njohur karakterin e sjelljes së master, ne monitorojmë me kujdes numrin e detyrave në pritje. Sepse edhe një detyrë e ngecur, nëse nuk është bërë timeout në kohë, teorikisht në një situatë emergjente mund të bëhet shkaku që nuk do të funksionojë, le të themi, promovimi i replica-shard në primary, duke shkaktuar ndalimin e indeksimit.
- Po ashtu, ne shikojmë me vëmendje vonesat e garbage collector, sepse kemi pasur vështirësi të mëdha me këtë gjatë optimizimit.
- Të rejektuarit sipas threadave, për të kuptuar paraprakisht ku ndodhet "ngushtica".
- Dhe metrikat standarde, si heap, RAM dhe I/O.
Kur ndërtojmë monitorimin, patjetër duhet të marrim parasysh veçoritë e Thread Pool në Elasticsearch. përshkruan mundësitë e konfigurimit dhe vlerat e paracaktuara për kërkimin, indeksimin, por e hesht plotësisht për thread_pool.management. Këto thread-e trajtojnë, për shembull, kërkesat e tipit _cat/shards dhe të tjera të ngjashme, që janë të dobishme për shkrimin e monitorimit. Sa më i madh të jetë klasteri, aq më shumë kërkesa të tilla kryhen brenda një njësie kohe, dhe thread_pool.management i përmendur më lart jo vetëm që nuk është përfaqësuar në dokumentacionin zyrtar, por ka edhe një limit të përcaktuar prej 5 thread-a, që shpenzohet shumë shpejt, pas së cilës monitorimi ndalon së funksionuari siç duhet.
ĂfarĂ« do doja tĂ« thosha pĂ«rfundimisht: ne arritĂ«m! Ne arritĂ«m t'u japim programuesve dhe zhvilluesve tanĂ« njĂ« mjet qĂ« pothuajse nĂ« çdo situatĂ« mund tĂ« ofrojĂ« shpejt dhe saktĂ« informacionin rreth asaj qĂ« po ndodh nĂ« prodhim.
Po, kjo u bë mjaft e komplikuar, por megjithatë, arritëm t'i përshtatim dëshirat tona në produktet ekzistuese që nuk e kishim nevojë t'i patch-ojmë ose t'i shkruajmë nga e para.

Burimi: habr.com
