Në prill, inxhinierët e Avito u mblodhën për një takim online me kryeprogramuesin e ClickHouse, Aleksej Milovidov, dhe Kirillin Shvakov, një programues Golang nga kompania Integros. Diskutuan si përdorim sistemin e menaxhimit të bazave të dhënash dhe cilat sfida hasim.
Si rezultat i këtij takimi, ne përgatitëm një artikull me përgjigjet e ekspertëve për pyetje tona dhe të shikuesve në lidhje me backup-et, rikategoritjen e të dhënave, fjalorët e jashtëm, drivin Golang dhe përditësimin e versioneve të ClickHouse. Ky artikull mund të jetë i dobishëm për zhvilluesit që tashmë po punojnë aktivisht me DB-në e 'Yandex' dhe janë të interesuar për të tashmen dhe të ardhmen e saj. Për default, përgjigjet janë të Aleksej Milovidov, nëse nuk është specifikuar ndryshe.
Kujdes, përmbajtja është shumë e gjatë nën këtë titull. Shpresojmë se pyetjet do t'ju ndihmojnë të orientoheni.

Përmbajtja
Nëse nuk dëshironi të lexoni, mund të shikoni regjistrimin e takimeve. . Koha e kodit është në komentarin e parë nën videon.
ClickHouse vazhdimisht përditësohet, kurse të dhënat tona jo. Çfarë të bëjmë me këtë?
ClickHouse vazhdimisht përditësohet, por të dhënat tona që janë përpunuar me optimize final, nuk përditësohen dhe qëndrojnë në backup.
Supozoni se ndodhi një problem dhe të dhënat humbën. Ne vendosëm të rikuperohemi, dhe ndodhi që partitë e vjetra që ishin mbajtur në serverat e backup-it, shfaqin një diferencë të madhe me versionin aktual të ClickHouse. Çfarë të bëjmë në këtë situatë, dhe a është e mundur kjo?
Situata, në të cilën ju rikuperoni të dhënat nga një backup në një format të vjetër dhe në versionin e ri ato nuk lidhen, nuk është e mundur. Ne kujdesemi që formati i të dhënave në ClickHouse të mbetet gjithmonë i përputhshëm me të kaluarën. Kjo është shumë më e rëndësishme se përputhshmëria e veçorive, nëse ka ndryshuar sjellja e ndonjë funksioni të përdorur rrallë. Të dhënat që ruhen në disk, versioni i ri i ClickHouse gjithmonë duhet të jetë në gjendje t'i lexojë. Kjo është një ligj.
Cilat janë praktikat më të mira aktualisht për backup-et e të dhënave nga ClickHouse?
Si të bëjmë backup duke marrë parasysh se kemi operacione optimize final, një bazë të dhënash shumë të madhe në terabajt dhe të dhëna që përditësohen, le të themi, në tri ditët e fundit, dhe deri në atë kohë nuk ndodhin procedura me to?
Mund të krijojmë një zgjidhje tonë dhe të shkruajmë në bash: mbledh këto backup-e siç duhet. Ndoshta nuk ka nevojë të krijojmë asgjë dhe biçikleta është shpikur prej kohësh?
Së pari, për praktikat më të mira. Kolektivet e mi gjithmonë këshillojnë që në përgjigje të pyetjeve për backup-et të përmendin shërbimin 'Yandex.Cloud', ku kjo detyrë është zgjidhur tashmë. Pra, përdoreni atë nëse keni mundësi.
Nuk ka zgjidhje të plotë, të integruar për 100% në ClickHouse për backup. Ka disa përgatitje që mund të përdoren. Për të marrë një zgjidhje të plotë, do t'ju duhet të punoni pak manualisht ose të krijoni mbështjellje në formën e skripteve.
Do të filloj me zgjidhjet më të thjeshta dhe do të përfundoj me ato më të avancuara në varësi të volumin të dhënave dhe madhësisë së klasterit. Sa më i madh të jetë klasteri, aq më e komplikuar bëhet zgjidhja.
Nëse tabela me të dhëna zë vetëm disa gigabajt, mund të bëni backup kështu:
- Ruani definicionin e tabelave, dmth metadatat — show create table.
- Bëni një dump me ndihmën e klientit ClickHouse — select * nga tabela në skedarin. Në mënyrë standarde, do të merrni një skedar në formatin TabSeparated. Nëse dëshironi më efektivisht — mund të jetë në formatin Native.
Nëse volumi i të dhënave është më i madh, backup do të marrë më shumë kohë dhe shumë hapësirë. Kjo quhet backup logjik, ai nuk është i lidhur me formatin e të dhënave ClickHouse. Nëse ai ekziston, në rast ekstreme mund të merrni backup dhe ta ngarkoni në MySQL për rikuperim.
Për raste më të avancuara, ClickHouse ka mundësinë të krijojë snapshot partition në sistemin lokal të skedarëve. Kjo mundësi është e disponueshme në formën e një kërkese alter table freeze partition. Ose thjesht alter table freeze — ky është snapshot i tërë tabelës.
Snapshot-i do të krijohet në mënyrë konsistente për një tabelë në një shard, dmth nuk është e mundur të krijoni një snapshot konsistent për të gjithë klasterin në këtë mënyrë. Por për shumicën e detyrave, kjo nevojë nuk ekziston dhe është e mjaftueshme të ekzekutoni kërkesën në çdo shard dhe të merrni një snapshot konsistent. Ai krijohet në formën e hard links dhe prandaj nuk zë hapësirë shtesë. Më pas, këtë snapshot e kopjoni në serverin e backup-it ose në magazinën që përdorni për backup.
Rikuperimi i një backup të tillë është mjaft i lehtë. Së pari - krijoni tabelat sipas definicioneve të tabelave ekzistuese. Më pas, kopjoni snapshot-et e ruajtura të partitions në Directory-Detached për ato tabela dhe ekzekutoni kërkesën attach partition. Një zgjidhje e tillë është plotësisht e përshtatshme për volume të mëdha të të dhënave.
Ndonjëherë kërkohet diçka akoma më të sofistikuar — në rastet kur keni dhjetra ose madje qindra terabajt në çdo server dhe qindra serverë. Këtu ka një zgjidhje që e kam marrë nga kolegët në "Yandex.Metrica". Nuk do ta rekomandoja për secilin — lexoni dhe vendosni vetë nëse i përshtatet apo jo.
Së pari nevojitet të krijoni disa serverë me raftet e mëdha të diskëve. Më pas, në këto serverë, ngriheni disa serverë ClickHouse dhe i konfiguroni në mënyrë që të punojnë si një replikë për të njëjtat shards. Dhe më pas përdorni në këto serverë sistemin e skedarëve ose ndonjë mjet që lejon krijimin e snapshot-eve. Ka dy opsione. Opsioni i parë është snapshot-e LVM, opsioni i dytë është ZFS në Linux.
Pas kësaj, çdo ditë duhet të krijoni një snapshot, ai do të qëndrojë dhe do të zë ndonjë hapësirë. Natyrisht, nëse të dhënat ndryshojnë, me kalimin e kohës volumet e hapësirës do të rriten. Ky snapshot mund të nxirret në çdo moment dhe të rikuperoni të dhënat, është një zgjidhje e çuditshme. Plus, gjithashtu duhet të kufizoni këto replika në konfigurim, në mënyrë që ato të mos përpiqen të bëhen liderë.
A është e mundur të organizohet një vonesë e kontrolluar e kopjeve në grupe?
Këtë vit planifikoni të bëni valë në ClickHouse. A do të jetë e mundur të organizoni një vonesë të kontrolluar të replikave në to? Do të dëshironim që me ndihmën e saj të sigurohemi nga skenarët negativ me alter dhe ndryshime të tjera.
A është e mundur të bëni ndonjë rollback për ALTER? Për shembull, në një valë ekzistuese të themi që deri në këtë moment të aplikoni ndryshimet, dhe nga ky moment të ndaloni të aplikoni ndryshimet?
Nëse në klasterin tonë ka ardhur një komandë dhe e ka prishur atë, atëherë kemi një replika të kushtuar me një vonesë prej një ore, ku mund të themi, le të përdorim atë pikërisht tani, por dhjetë minutat e fundit të ndryshimeve atje nuk do t'i aplikojmë?
Së pari për vonesën e kontrolluar të replikave. Një kërkesë e tillë nga përdoruesit kishte dhe ne krijuam një çështje në GitHub me kërkesën: “Nëse dikush e ka nevojë, jepni like, jepni zemrën”. Askush nuk e vendosi, dhe çështja u mbyll. Megjithatë, tashmë mund të merrni një mundësi të tillë, duke konfiguruar ClickHouse. Megjithatë, vetëm duke filluar nga versioni 20.3.
ClickHouse përherë në sfond kryen bashkimin e të dhënave — merge. Kur bashkimi është kryer, një grup i caktuar i copave të të dhënave zëvendësohet me një copë më të madhe. Në këtë proces, copat e të dhënave që ishin më parë vazhdojnë të qëndrojnë në disk për një periudhë të caktuar.
Së pari, ato vazhdojnë të ruajnë deri sa ka kërkesa select që i përdorin, për të siguruar një funksionim jo-bllokues. Kërkesat select lexojnë qetësisht nga pjesët e vjetra.
Së dyti, ka gjithashtu një prag kohor – pjesët e vjetra të dhënash qëndrojnë në disk për tetë minuta. Këto tetë minuta mund të konfigurohen dhe të shndërrohen edhe në një ditë. Kjo do të kushtojë hapësirë në disk: në varësi të fluksit të të dhënave, mund të ndodhë që përditshmëria e të dhënave të mos dyfishohet, por të rritet deri në pesë herë më shumë. Megjithatë, ju mund të ndaloni serverin ClickHouse dhe të zgjidhni çdo problem të rëndë.
Tani lind pyetja, si e mbron kjo nga alteret. Këtu duhet të shikojmë më thellë, sepse në versionet e vjetra të ClickHouse, alteri funksiononte në një mënyrë që thjesht ndryshonte pjesët. Ka një pjesë të dhënash me disa skedarë, dhe ne bëjmë, për shembull, alter drop column. Atëherë ky kolonë fshihet fizikisht nga të gjitha pjesët.
Por duke filluar nga versioni 20.3, mekanizmi i altereve është ndryshuar plotësisht, dhe tani pjesët e dhënave janë gjithmonë imutabile. Ato nuk ndryshojnë fare – alteret tani funksionojnë pak si të bashkohen. Në vend që të ndryshojmë një pjesë në vend, ne krijojmë një të re. Në pjesën e re, skedarët që nuk janë ndryshuar bëhen hardlink, dhe nëse ne kemi fshirë ndonjë kolonë, ai thjesht do të mungojë në pjesën e re. Pjesa e vjetër do të fshihet automatikisht pas tetë minutash, dhe këtu mund të rregulloni cilësimet, të cilat u përmendën më lart.
E njëjta gjë vlen edhe për alteret e tipit të mutacioneve. Kur bëni alter delete ose alter update, ai nuk ndryshon një pjesë, por krijon një të re. Pastaj fshin të vjetrën.
Çfarë të bëjmë nëse struktura e tabelës ka ndryshuar?
Si të rimerrni një kopje rezervë, që ishte bërë me një skemë të vjetër? Dhe pyetja e dytë për rastin me snapshot-et dhe mjetet e sistemit të skedarëve. A është Btrfs në këtë rast i pranueshëm në vend të ZFS në Linux LVM?
Nëse krijoni attach partition particionet me strukturë tjetër, atëherë ClickHouse do t'ju thotë që nuk është e mundur. Zgjidhja është e tillë. E para – për të krijuar një tabelë të përkohshme të tipit MergeTree me strukturën e vjetër, të bashkangjiteni të dhënave përmes attach, të bëni një kërkesë alter. Pastaj mund të kopjoni ose transferoni këto të dhëna dhe të bëni attach përsëri, ose të përdorni kërkesën alter table move partition.
Tani pyetja e dytë – a mund të përdorni Btrfs. Së pari, nëse keni LVM, atëherë mjafton snapshot-t e LVM, dhe sistemi i skedarëve mund të jetë edhe ext4, kjo nuk ka rëndësi. Me Btrfs gjithçka varet nga përvoja juaj me përdorimin e saj. Kjo është një sistem skedarësh i pjekur, por ndodhin disa dyshime për mënyrën se si do të funksionojë në praktikë në një skenar të caktuar. Nuk do t'ju rekomandoja ta përdorni, nëse nuk e keni Btrfs në prodhim.
Cilat janë praktikat më të mira aktualisht për rikategoritjen e të dhënave?
Pyetja rreth ri-shardimit është komplekse dhe shumëdimensional. Këtu mund të përgjigjemi menjëherë në disa mënyra. Mund ta marrim nga njëra anë dhe të themi se në ClickHouse nuk ka mundësi të integruar për ri-shardim. Por kam frikë se kjo përgjigje nuk do t'i kënaqë askënd. Prandaj, mund të marrim një tjetër perspektivë dhe të themi se në ClickHouse ka shumë mënyra për ri-shardimin e të dhënave.
Nëse përfundohet hapësira në klaster ose ai nuk e menaxhon ngarkesën, ju shtoni serverë të rinj. Por këta serverë fillimisht janë bosh, nuk kanë të dhëna, nuk ka ngarkesë. Ju duhet të transferoni të dhënat që të shpërndahen në mënyrë të barabartë në klasterin e ri, të zgjeruar.
Mënyra e parë për ta bërë këtë është të kopjoni një pjesë të particioneve në serverët e rinj përmes kërkesës alter table fetch partition. Për shembull, nëse keni pasur parti për muajt, mund të merrni muajin e parë të vitit 2017 dhe ta kopjoni në serverin e ri, pastaj – muajin e tretë ta kopjoni në një server tjetër të ri. Dhe kështu vazhdoni derisa të jetë përmbushur një shpërndarje më të barabartë.
Transferimi mund të bëhet vetëm për ato parti që nuk ndryshojnë gjatë shk writing. Për partitë e reja, do t'ju duhet të çaktivizoni shkrimin, sepse transferimi i tyre nuk është atomik. Nëse jo, do të merrni dublikate ose mungesa në të dhëna. Megjithatë, kjo mënyrë është praktike dhe funksionon mjaft efektivisht. Partitë e kompresuara, të gatshme, transmetohen përmes rrjetit, domethënë të dhënat nuk kompresohen dhe ripërshtaten.
Kjo mënyrë ka një disavantazh, dhe varet nga skema e shardimit, nëse keni bërë parashikimin për këtë skemë të shardimit, cilat ishin çelësi i shardimit. Në shembullin tuaj për rastin e metrikave, çelësi i shardimit është hash i rrugës. Kur ekzekutoni një select në tabelën Distributed, ai shkon menjëherë në të gjitha shardet e klasterit dhe merr të dhënat prej aty.
Kjo do të thotë se në thelb nuk ka rëndësi se cilat të dhëna ndodhen në cilin shard. E rëndësishme është që të dhënat në një rrugë të caktuar të jenë në një shard, dhe se cili është ai, nuk ka rëndësi. Në këtë rast, transferimi i particioneve të gatshme është një zgjidhje e shkëlqyer, sepse gjatë kërkesave select gjithashtu - si para ashtu edhe pas riparimit të shardin, skema e të dhënave nuk ka rëndësi - do të merrni të dhëna të plota.
Por ka raste edhe më të komplikuara. Nga niveli i logjikës së aplikacionit, nëse keni parashikuar një skemë të veçantë sharding, që ky klient është i vendosur në një shard të caktuar, dhe kërkesa mund të dërgohet menjëherë atje, dhe jo në tabelën Distributed. Ose po përdorni një version mjaft të ri të ClickHouse dhe keni aktivizuar cilësimin optimize skip unused shards. Në këtë rast, gjatë kërkesës select, shprehja në seksionin where do të analizohet, dhe do të llogaritet se në cilat shards duhet të shkohet sipas skemës së sharding. Kjo funksionon me kushtin që të dhënat të jenë të organizuara në përputhje me këtë skemë sharding. Nëse i keni transferuar manualisht, përputhshmëria mund të ndryshojë.
Pra, ky është mënyra numër një. Dhe pres përgjigjen tuaj, nëse kjo mënyrë është e përshtatshme, ose shkojmë më tej.
Vladimir Kolobaev, administrator sistemi lead në Avito: Alexey, mënyra që përmendët nuk është shumë e përshtatshme kur duhet të shpërndajmë ngarkesën përfshirë edhe atë për lexim. Mund të marrim një particion që është mujor dhe mund ta transferojmë muajin e kaluar në një nodë tjetër, por kur të vijë kërkesa për këto të dhëna, do të ngarkojmë vetëm atë. Por do ishte më mirë të ngarkonim të gjithë klasterin, sepse në të kundërt, për një kohë të caktuar e gjithë ngarkesa për lexim do të përballohet nga dy shards.
Alexey Milovidov: Përgjigjja këtu është e çuditshme - po, keq, por ndoshta do të funksionojë. Shpjegoj si pikërisht. Duhet të shikoni skenarin e ngarkesës që vjen për të dhënat tuaja. Nëse këto janë të dhëna monitorimi, pothuajse me siguri mund të themi se shumica dërrmuese e kërkesave vijnë për të dhëna të freskëta.
Ju vendosët serverë të rinj, transferuat partitë e vjetra, por gjithashtu ndryshuat se si shkruhen të dhënat e freskëta. Dhe të dhënat e freskëta do të shpërndahen në të gjithë klasterin. Kështu që, tashmë pas pesë minutash, kërkesat për pesë minutat e fundit do të ngarkojnë në mënyrë të barabartë klasterin, pas një dite kërkesat për një ditë do të ngarkojnë klasterin në mënyrë të barabartë. Por, kërkesat për muajin e kaluar, fatkeqësisht, do të shkojnë vetëm në një pjesë të serverëve të klasterit.
Por shpesh ju nuk do të keni kërkesa pikërisht për shkurtin 2019. Për më shumë, nëse kërkesat janë për vitin 2019, do të jenë për të gjithë vitin 2019 - për një interval të gjerë kohor, dhe jo për një interval të vogël. Këto kërkesa gjithashtu mund të ngarkojnë klasterin në mënyrë të barabartë. Por në përgjithësi, vërejtja juaj është e saktë, se kjo është një zgjidhje ad hoc, e cila nuk shpërndahen të dhënat plotësisht në mënyrë të barabartë.
Kam disa pikë për të përfunduar pyetjen. Njëra prej tyre është se si të krijoni fillimisht një skemë sharding, që të ketë më pak dhimbje nga riparimi i shardin. Kjo nuk është e mundur gjithmonë.
Për shembull, keni të dhëna monitorimi. Të dhënat e monitorimit rriten për tri arsye. E para - akumulimi i të dhënave historike. E dyta - rritja e trafikut. Dhe e treta - rritja e numrit të gjërave që bien nën monitorim. Shfaqen mikroshërbime dhe metrika të reja që duhen ruajtur.
Mund të ketë që rritja më e madhe është e lidhur pikërisht me arsyen e tretë - kjo është rritja e përdorimit të monitorimit. Dhe në këtë rast, duhet të shikoni qëndron për ngarkesën, çfarë janë kërkesat kryesore për select. Kërkesat kryesore për select, me siguri do të vijnë për një nëngrup të caktuar të metrikave.
Për shembull, përdorimi i CPU në disa servera nga një shërbim të caktuar. Kështu, ka një nëngrup të çelësve, sipas të cilëve ju merrni këto të dhëna. Dhe vetë kërkesa për këto të dhëna, mendoj se do të jetë mjaft e thjeshtë dhe do të realizohet brenda disa milisekondash. Përdoret për shërbimet e monitorimit, për dashboardet. Shpresoj të kuptoj gjithçka saktë.
Vladimir Kolobaev: Çështja është se ne shpesh referohemi në të dhëna historike, sepse krahasojmë pozitat aktuale me atë historike në kohë reale. Dhe për ne është e rëndësishme të kemi akses të shpejtë në një volum të madh të të dhënave, dhe ClickHouse bën një punë të shkëlqyer me këtë.
Keni të drejta, shumicën e kërkesave për lexim i përjetojmë në ditën e fundit, ashtu si çdo sistem monitorimi. Por, ngarkesa për të dhënat historike është gjithashtu mjaft e madhe. Kjo është kryesisht për shkak të sistemit të alarmimit, i cili çdo thirty sekonda shkon dhe i thotë ClickHouse: "Më jep të dhënat për gjashtë javët e fundit. Tani më ndihmo të bëj një mesatare lëvizëse nga to, dhe le të krahasojmë vlerën aktuale me atë historike."
Doja të thosha se kemi një tabelë të vogël për këto kërkesa shumë të freskëta, ku ruajmë të dhënat për vetëm dy ditë, dhe kërkesat kryesore shkojnë atje. Të dhënat historike më të mëdha dërgohen vetëm në tabelën e madhe të sharduar.
Alexey Milovidov: Më vjen keq, për skenarin tuaj kjo zgjidhje duket se nuk është e aplikueshme, por do të flas për dy skema të këqija dhe të komplikuara të shardimit, të cilat nuk duhet t'i përdorni, por që janë përdorur në shërbimin e miqve të mi.
Ka një klaster kryesor me ngjarjet e "Yandex.Metrika". Ngjarjet janë shikimet e faqeve, klikimet dhe kalimet. Shumica e kërkesave shkojnë për një website të caktuar. Ju hapni shërbimin "Yandex.Metrika", keni një faqe — avito.ru, hyni në raport dhe bëhet një kërkesë për faqen tuaj.
Por ka edhe kërkesa të tjera — analitike dhe globale, të cilat i bëjnë analistët e brendshëm. Për informacion, analistët e brendshëm bëjnë kërkesa vetëm për shërbimet e "Yandex". Por megjithatë, shërbimet "Yandex" përbëjnë një pjesë të konsiderueshme të të dhënave. Këto janë kërkesa jo për numërat e caktuar, por për filtrime më të gjera.
Si të organizojmë të dhënat në një mënyrë që në mënyrë efikase të funksionojnë kërkesat për një numër të caktuar dhe kërkesat globale gjithashtu? Vështirësia është gjithashtu se numri i kërkesave në ClickHouse për klasterin "Metrika" është disa mijëra në sekondë. Ndërkohë, disa kërkesa komplekse, për shembull, një server ClickHouse nuk mund t'i përballojë disa mijëra kërkesa në sekondë.
Madhësia e klasterit është më shumë se six hundred serverë. Nëse thjesht mbështetemi mbi klasterin e shpërndarë dhe dërgojmë disa mijëra kërkesa atje, do të bëhet edhe më keq sesa dërgimi i tyre në një server të vetëm. Nga ana tjetër, ne heqim dorë nga ideja që të dhënat janë shpërndarë në mënyrë të barabartë dhe ne kërkojmë nga të gjithë serverët.
Ka një opsion diametralisht të kundërt. Imagjinoni se nëse ne do të shardonim të dhënat sipas faqeve, dhe kërkesa për një faqe do të shkojë në një shard. Tani klasteri është në gjendje të përballojë dhjetë mijë kërkesa në sekondë, por në një shard, një kërkesë do të punojë shumë ngadalë. Ajo nuk do të skadohet sipas kapacitetit. Sidomos nëse është faqja avito.ru. Nuk do të zbuloja asnjë sekret nëse do të thosha se Avito është një nga faqet më të vizituara në Runet. Dhe ta trajtosh atë në një shard do të ishte një çmenduri.
Kështu që skema e shardimit është organizuar në një mënyrë më të zgjuar. I gjithë klasteri është i ndarë në një numër të caktuar klasterkash, të cilat ne i quajmë shtresa. Brenda çdo klasterku janë disa dhjetra shardesh. Gjithsej kemi thirty-nine të tillë.
Si e gjithë kjo shkallëzohet? Numri i klasterkave nuk ndryshon - ashtu si ishin disa vite më parë thirty-nine, kështu ka mbetur. Por brenda secilit prej tyre, ne gradualisht rrisim numrin e shardëve përsa kohë që grumbullojmë të dhëna. Dhe skema e shardimit në tërësi është kjo - ndarja në këto klasterka ndodh sipas faqeve, dhe për të kuptuar se cila faqe është në cilin klaster, përdoret një bazë të dhënash të veçantë në MySQL. Një faqe — në një klaster. Dhe brenda tij shardimi ndodh sipas identifikuesve të vizitorëve.
Kur shkruajmë, i ndajmë sipas mbetjeve nga ndarja e identifikuesit të vizitorit. Por kur shtojmë një shard të ri, skema e shardimit ndryshon, ne vazhdojmë të ndajmë, por me mbetje nga ndarja në një numër tjetër. Kjo do të thotë se një vizitor tashmë ndodhet në disa serverë, dhe nuk mund të mbështetet në këtë. Kjo është bërë ekskluzivisht për të siguruar që të dhënat të comprimojnë më mirë. Dhe kur bëjmë kërkesa, ne i drejtohemi tabelës së shpërndarë, e cila shikon në klaster dhe i drejtohet dhjetëra serverëve. Kjo është një skemë e komplikuar.
Por tregimi im do të ishte i paplote nëse nuk do të thosha se nga kjo skemë ne jemi tërhequr. Në skemën e re, ne kemi ndryshuar gjithçka dhe kopjuar të gjitha të dhënat me ndihmën e clickhouse-copier.
Në skemën e re, të gjitha faqet ndahen në dy kategori - të mëdha dhe të vogla. Nuk e di se si është përzgjedhur pragun, por në fund rezultoi që faqet e mëdha regjistrohen në një kluster, ku ka 120 shards me nga tre replika në secilin - pra 360 servera. Dhe skema e sharding është e tillë që çdo kërkesë shkon menjëherë në të gjitha shards. Nëse tani hapni çdo faqe raporti për avito.ru në "Yandex.Metrika", kërkesa do të shkojë në 120 servera. Ka pak faqe të mëdha në Runet. Dhe kërkesat rezultojnë të jenë jo mijëra në sekondë, por ndoshta më pak se njëqind. Të gjitha këto procesohen qetë nga tabela Distributed, e cila përpunon ato me 120 servera.
Dhe klustri i dytë është për faqet e vogla. Këtu skema e sharding është sipas identifikuesit të faqes, dhe çdo kërkesë shkon saktësisht në një shard.
Në ClickHouse ka një utilitet quajtur clickhouse-copier. A mund të flisni për të?
Të them të drejtën, kjo zgjidhje është më e ngarkuar dhe disi më pak e efektshme. Avantazhi është se ajo shpërndan të dhënat plotësisht sipas skemës që do të specifikoni. Por disavantazhi i këtij utiliti është se nuk bën sharding të ri. Ajo kopjon të dhënat nga një skemë e klusterit në një tjetër skemë të klusterit.
Kjo do të thotë se për funksionimin e saj ju duhet të keni dy klusterë. Ata mund të jenë të vendosur në servera të njëjtë, por megjithatë, të dhënat nuk do të lëvizin inkrementalisht, por do të kopjohen.
Për shembull, ishte katër servera, tani janë tetë. Krijoni një tabelë të re Distributed në të gjithë serverat, tabela të reja lokale dhe filloni clickhouse-copierin, duke e caktuar skemën e punës, e cila duhet të lexojë atje, të pranojë skemën e re të sharding dhe të transferojë të dhënat atje. Dhe në serverat e vjetër do t'ju nevojitet hapësirë një herë dhe gjysmë më shumë sesa keni tani, sepse të dhënat e vjetra duhet të qëndrojnë atje, dhe përveç tyre do të vijë një pjesë nga ato të vjetra. Nëse keni menduar përpara se ju nevojitet sharding i ri dhe keni hapësirë, atëherë ky metodë do të përshtatet.
Si është e organizuar brenda clickhouse-copier? Ai e ndan tërë punën në një set detyrash për përpunimin e një partie të një tabele në një shard. Të gjitha këto detyra mund të ekzekutohen paralelisht, dhe clickhouse-copier mund të nisë në makina të ndryshme në disa instance, por ajo që bën për një parti është asgjë më shumë se insert select. Të dhënat lexohen, çcompressed, rigrupohen, pastaj kompresohen përsëri, shkruhen diku, ridistribuohen. Kjo është një zgjidhje më e rëndë.
Keni pasur një funksion pilot që quhej rikategorizim. Çfarë po ndodh me të?
Keni pasur gjithashtu një gjë pilot në vitin 2017, e cila quhej resharding. Madje ka një opsion në ClickHouse. Unë kuptoj se kjo nuk ka fluturuar. A mund të ndihmoni në shpjegimin se si ndodhi kjo? Duket se është shumë e rëndësishme.
E gjithë problemi është se kur nevojitet të reshardohet të dhënat, në vend kërkohet një sinkronizim shumë i komplikuar për ta bërë këtë në mënyrë atomike. Kur filluam të shikojmë se si është zbatuar kjo sinkronizim, iu bë e qartë se ka probleme thelbësore. Dhe këto probleme thelbësore nuk janë vetëm teorike, por gjithashtu filluan të shfaqen praktikisht në formën se mund të shpjegohet shumë thjesht - asgjë nuk funksionon.
A është e mundur të bashkohen të gjitha pjesët e të dhënave para se të zhvendosen në disqe të ngadalta?
Një pyetje për TTL me opsionin move to slow disk në kontekstin e mergerave. A ka ndonjë mënyrë, përveç nëpërmjet cron, për të bashkuar të gjitha pjesët në një përpara se të shpërndahen në disqet e ngadalta?
Përgjigja në pyetje, a është ndonjëherë e mundur të bashkohen të gjitha copat në një përpara se të transferohen - jo. Më duket se nuk ka nevojë. Nuk është e domosdoshme të bashkohen të gjitha pjesët në një, por thjesht të llogaritni se ato do të transferohen në disqet e ngadalta automatikisht.
Ne kemi dy kritere të rregullave të transferimit. E para - sipas mbushjes. Nëse në nivelin aktual të ruajtjes ka më pak se ndonjë përqindje hapësire të lirë, ne zgjedhim një copë dhe e transferojmë atë në ruajtje më të ngadaltë. Në të vërtetë, jo më të ngadalta, por të ardhshme - sipas konfigurimit tuaj.
Kriteri i dytë - sipas madhësisë. Ai ka të bëjë me transferimin e copave të mëdha. Ju mund të rregulloni pragun sipas hapësirës së lirë në diskun e shpejtë, dhe të dhënat do të transferohen automatikisht.
Si të kalojmë në versionet e reja të ClickHouse, nëse nuk ka mundësi të kontrollohet në mënyrë paraprake për pajtueshmërinë?
Ky temë diskutohen rregullisht duke pasur parasysh versione të ndryshme, dhe megjithatë. Sa i sigurt është të përmirësohemi nga versioni 19.11 në 19.16 dhe, për shembull, nga 19.16 në 20.3. Si është më mirë të kaloni në versione të reja, pa pasur mundësi të kontrolloni paraprakisht përputhshmërinë në një mjedis testimi?
Këtu ka disa "rregulla të arta". E para - . Ai është i madh, por ka pika të veçanta për ndryshimet që nuk janë të kthyeshme. Mos e konsideroni këto pika si një flamur të kuq. Zakonisht është për pak moskonsistenca të vogla që lidhen me ndonjë funksionalitet të veçantë që ndoshta nuk e përdorni.
E dyta — nëse nuk ka mundësi të kontrolloni kompatibilitetin në një sandkiste dhe dëshironi të përditësoni menjëherë në prodhim, rekomandimi është i tillë — mos e bëni këtë. Së pari krijoni një sandkiste dhe kontrolloni. Nëse nuk keni një mjedis testimi, atëherë ndoshta kompania juaj nuk është shumë e madhe dhe kështu që mund të kopjoni një pjesë të dhënash në laptopin tuaj dhe atje të siguroheni që gjithçka funksionon siç duhet. Mund të ngrini madje disa replika lokal në kompjuterin tuaj. Ose mund të ngrini një version të ri diku afër dhe të ngarkoni një pjesë të dhënash atje — pra të krijoni një mjedis testimi improvizuar.
Një tjetër rregull — mos bëni përditësim për një javë pas lëshimit të versionit për shkak të kapjen e defekteve në prodhim dhe riparime të shpejta që pasojnë. Le të zbulojmë numërimin e versioneve të ClickHouse, për të mos u konfuzuar.
Ekziston versioni 20.3.4. Numri 20 tregon vitin e lëshimit — 2020. Nga pikëpamja e asaj që ka brenda, kjo nuk ka asnjë rëndësi, kështu që nuk do t'i kushtojmë vëmendje. Më tej — 20.3. Numrin e dytë — në këtë rast 3 — e rrisim çdo herë kur lëshojmë një version me ndonjë funksionalitet të ri. Nëse dëshirojmë të shtojmë një mundësi në ClickHouse, ne jemi të detyruar ta rrisim këtë numër. Pra, me versionin 20.4, ClickHouse do të funksionojë edhe më mirë. Numri i tretë — 20.3.4. Këtu 4 është numri i lëshimeve të patch-eve, në të cilat nuk kemi shtuar mundësi të reja, por kemi rregulluar disa defekte. Dhe 4 do të thotë se e kemi bërë këtë katër herë.
Mos mendoni se është diçka e tmerrshme. Zakonisht përdoruesi mund të instalohet versionin më të ri dhe ai do të funksionojë pa asnjë problem me disponueshmërinë për një vit. Por imagjinoni, nëse në ndonjë funksion për përpunimin e bitmapëve, i cili është shtuar nga shokët tanë kinezë, kur dërgohen argumente të gabuara, serveri bllokohet. Ne jemi të detyruar ta rregullojmë këtë. Ne do të lëshojmë një version të ri patch dhe ClickHouse do të bëhet më stabil.
Nëse keni ClickHouse që funksionon në prodhim dhe del një version i ri ClickHouse me karakteristika shtesë — p.sh. 20.4.1 — në ditën e parë mos u ngutni ta vendosni në prodhim. Pse e nevojshme? Nëse ende nuk e përdorni ClickHouse, mund ta instaloni dhe, shumë të ngjarë, gjithçka do të shkojë mirë. Por nëse ClickHouse tashmë funksionon stabilisht, atëherë ndiqni patch-et dhe përditësimet — cilat probleme jemi duke rregulluar.
Kirill Shvakov: Dua të shtoj pak për mjediset e testimit. Të gjithë kanë frikë nga mjediset e testimit dhe ndonjëherë mendojnë se, nëse keni një klaster shumë të madh ClickHouse, atëherë mjedisi i testimit duhet të jetë jo më pak ose të paktën dhjetë herë më i vogël. Kjo fare nuk është e vërtetë.
Mund të them nga përvoja ime. Kam një projekt dhe aty është ClickHouse. Mjedisi ynë i testimit për të është një virtual që është për 20 euro në Hetzner, ku është e gjithë struktura e instaluar. Për ta bërë këtë, ne kemi automatizim të plotë në Ansible, kështu që në parim nuk ka ndonjë ndryshim se ku instaloni — në servera të metaleve ose thjesht në virtuale.
Çfarë mund të bëhet? Do të ishte mirë të bëhej në dokumentacionin e ClickHouse një shembull se si të ngritni një klaster të vogël — në Docker, në LXC, ndoshta të krijoni një playbook të Ansible, sepse njerëzit e ndryshëm kanë ndryshme shpërndarje. Kjo do ta thjeshtonte shumë. Kur merrni dhe ngrini një klaster në pesë minuta, është shumë më e lehtë të kuptoni diçka. Kjo është shumë më e rehatshme, sepse të vendosësh në versionin e prodhimit, të cilin nuk e ke kontrolluar — është një rrugë pa dalje. Ndonjëherë funksionon, ndonjëherë jo. Dhe prandaj shpresa për sukses është e keqe.
Maksim Kotyakov, inxhinier i lartë pas backend në Avito: Dua të shtoj pak për mjediset e testimit nga seria e problemeve të kompanive të mëdha. Ne kemi një klaster të plotë të pranuar ClickHouse, me skema të dhënash dhe konfigurime, një kopje të saktë të asaj që është në prodhim. Ky klaster është ngritur në konteinerë të mjaftueshëm me burime minimale. Ne shkruajmë atje një përqindje të dhënash nga prodhimi, për fat të mirë, ka mundësi të riprodhojmë në Kafka. Aty gjithçka është sinkronizuar dhe e skalabilizuar — si për kapacitetin ashtu edhe për rrjedhjen, dhe, në teorinë, në kushte të tjera të barabarta, duhet të sillen si prodhimi. E gjithë ajo që është potencialisht e rrezikshme fillimisht kalon në këtë skenë dhe disa ditë atje piqet deri sa të jetë gati. Por natyrisht, kjo zgjidhje është e shtrenjtë, e rëndë dhe me shpenzime jo të nullluara për mbështetje.
Alexey Milovidov: Do të flas për se çfarë përfaqëson mjedisi testues i miqve tanë nga «Yandex.Metrica». Një klaster pati mbi 600 serverë, tjetri mbi 360, dhe ka edhe një të tretë dhe disa klasterë të tjerë. Mjedisi testues për një prej tyre është thjesht dy shardë me dy replika në secilin. Pse dy shardë? Për të pasur më shumë se një. Po ashtu duhet të ketë replika. Thjesht një minimum që mund të përballosh.
Ky mjedis testues lejon të verifikohet funksionaliteti i kërkesave dhe nëse diçka nuk ka shkuar keq. Por shpesh problemi shfaqet nga një natyrë krejtësisht tjetër, kur gjithçka funksionon, por ka disa ndryshime të vogla me ngarkesën.
Mund t'ju jap një shembull. Vendosëm të instalojmë një version të ri të ClickHouse. Ai u vendos në mjedisin testues, u kaluan testet automatizuar në vetë «Yandex.Metrica», të cilat krahasojnë të dhënat në versionin e vjetër dhe në atë të ri, duke kaluar të gjithë procesin. Dhe natyrisht, testet pozitive të CI tonë. Ndryshe, nuk do ta kishim propozuar këtë version.
Gjithçka shkonte mrekullisht. Filluam të kalojmë në prodhim. Më vjen një mesazh që ngarkesa në grafika është rritur disa herë. Ne e kthejmë versionin mbrapa. Unë shikoj grafikën dhe shoh: ngarkesa në të vërtetë u rrit disa herë gjatë kalimit, dhe u ul përsëri kur kaluam. Pastaj filluam të kthejmë versionin. Edhe ngarkesa po ashtu u rrit dhe po ashtu ra përsëri. Pra përfundimi është se ngarkesa u rrit në lidhje me kalimin, nuk ka asgjë të çuditshme.
Më pas ishte e vështirë të bindja kolegët që të instalohej versioni i ri. I thashë: "Gjithçka është në rregull, kaloni përpara. Mbani gishtat e ndihmës, gjithçka do të funksionojë. Tani ngarkesa është rritur në grafik, por gjithçka është në rregull. Qëndroni të qetë". Në përgjithësi, kështu vepruam dhe të gjithë - versioni u vendos në prodhim. Por thuajse për çdo kalim shfaqen probleme të ngjashme.
Kill query duhet të ndalë kërkesat, por kjo nuk ndodh. Pse?
Më erdhi një përdorues, një analist, dhe krijoi një kërkesë të tillë që e bllokoi klasterin tim ClickHouse. Ndoshta një nodë ose tërë klasteri - në varësi nga se në cilën replikë ose shard ra kërkesa. Unë shoh se të gjitha burimet për CPU në atë server janë të mbushura, gjithçka është e kuqe. Ndërkohë ClickHouse vetë po përgjigjet në kërkesa. Dhe shkruaj: "Më trego, të lutem, listën e proceseve, cili kërkesë solli këtë çmenduri".
E gjej atë kërkesë dhe i shkruaj kill. Dhe shoh se nuk po ndodh asgjë. Serveri im është i mbushur, ClickHouse po më jep disa komanda, tregon se serveri është në gjendje të mirë, dhe gjithçka është në rregull. Por kam degradim në të gjitha kërkesat e përdoruesve, fillon degradimi në shkrimin në ClickHouse, dhe kill query im nuk funksionon. Pse? Mendova se kill query duhet të vrasë kërkesat, por kjo nuk po ndodh.
Tani do të ketë një përgjigje mjaft të çuditshme. Problemi është se kill query nuk vret kërkesat.
Kill query vendos një flamur të vogël nën emrin "dua që kjo kërkesë të zhduket". Ndërsa kërkesa, gjatë përpunimit të çdo bloku, kontrollon këtë flamur. Nëse është vendosur, kërkesa ndalon punën. Pra, në fakt, askush nuk vret kërkesën, ajo duhet ta kontrollojë vetë dhe të ndalet. Dhe kjo duhet të funksionojë në të gjitha rastet kur kërkesa është në procesin e përpunimit të blloqeve të dhënash. Ajo do të përpunojë blokun e ardhshëm të të dhënave, do të kontrollojë flamurin dhe do të ndalet.
Kjo nuk funksionon në rastet kur kërkesa është bllokuar në një operacion të caktuar. Megjithatë, ndoshta ky nuk është rasti juaj, për shkak se, sipas fjalëve tuaja, ajo po konsumon shumë burime të serverit. Ndoshta, kjo nuk funksionon në rastin e renditjes së jashtme dhe në disa detaje të tjera. Por në përgjithësi, kjo nuk duhet të ndodhë, është një bug. Dhe e vetmja që mund të këshilloj është të përditësoni ClickHouse.
Si të llogarit kohën e përgjigjes nën ngarkesë leximi?
Ka një tabelë, në të cilën ruhen agregatet sipas item - ndryshme numëruesish. Numri i rreshtave është afërsisht njëqind milion. A është e mundur të llogaritësh një kohë përgjigjeje të parashikueshme nëse i japim 1K RPS për 1K item?
Sipas kontekstit, flitet për ngarkesë leximi, sepse për shkrim nuk ka asnjë problem - mund të shtosh një mijë, njëqind mijë, madje edhe disa milion rreshta.
Kërkesat për lexim mund të jenë të ndryshme. Në select 1, ClickHouse mund të ekzekutojë disa dhjetëra mijëra kërkesa në sekondë, kështu që edhe kërkesat për një çelës do të kërkojnë disa burime. Dhe këto kërkesa pikë do të jenë më të komplikuara se në ndonjë bazë të dhënash tipike key-value, sepse për çdo lexim nevojitet të lexohet një bllok të dhënash sipas indeksit. Indeksi adreson jo çdo rekord, por çdo gamë. Kështu që do të duhet të lexoni tërë gamën - kjo është 8192 rreshta si parazgjedhje. Dhe do të duhet të çdëmtosh një bllok të dhënash të kompresuar prej 64 KB deri në 1 MB. Zakonisht, kërkesat e tilla pikë zgjatin disa milisekonda. Por kjo është një opsion shumë i thjeshtë.
Le të përpiqemi të bëjmë një aritmetikë të thjeshtë. Nëse shumëzojmë disa milisekonda me një mijë, marrim disa sekonda. Siç duket, mbajtja e një mijë kërkesave në sekondë nuk është e mundur, por në të vërtetë është, sepse kemi disa bërthamë procesori. Pra, në parim, 1000 RPS ClickHouse ndonjëherë mund ta mbajë, por për kërkesa të shkurtra, pikërisht ato pikë.
Nëse duhet të shkallëzoni klasterin ClickHouse për numrin e kërkesave të thjeshta, rekomandoj më e thjeshta - të rrisni numrin e replikeve dhe të dërgoni kërkesat në një replikë rastësore. Nëse një replikë tuaj mbajnë pesëqind kërkesa në sekondë, që është plotësisht realiste, atëherë tre replika do të mbajnë një mijë e pesëqind.
Ndonjëherë, natyrisht, mund të konfiguroni edhe ClickHouse për numrin maksimal të leximeve pikë. Çfarë nevojitet për këtë? E para - të reduktoni granularitetin e indeksit. Por, duhet ta ulni atë jo në njësi, por duke e llogaritur se numri i regjistrimeve në indeks do të jetë disa milion ose dhjetëra miliona në server. Nëse tabela ka njëqind milion rreshta, atëherë granulariteti mund të vendoset në 64.
Mund të zvogëloni madhësinë e bllokut të kompresuar. Për këtë, ka cilësime min compress block size, max compress block size. Mund të zvogëloni këto, të ricaktoni të dhënat, dhe atëherë kërkesat pikë do të jenë më të shpejta. Por prapëseprapë ClickHouse nuk është një bazë të dhënash key-value. Një numër i madh kërkesash të vogla është një antipattern ngarkese.
Kirill Shvakov: Do të jap një këshillë në rast se atje ka llogaritës të zakonshëm. Kjo është një situatë mjaft standarde, kur në ClickHouse ruhet një numërues. Kam një përdorues, ai vjen nga një vend i caktuar, një fushë tjetër, dhe duhet të rrisim diçka në mënyrë inkrementale. Merrni MySQL, bëni një çelës unik - në MySQL është çelës i dyfishtë, ndërsa në PostgreSQL është konflikt - dhe e shtoni me një plus. Kjo do të funksionojë shumë më mirë.
Kur keni pak të dhëna, nuk ka kuptim të përdorni ClickHouse veçanërisht. Ka baza të dhënash të zakonshme, dhe ato e kanë mirë këtë punë.
Çfarë të rregullojmë në ClickHouse, që më shumë të dhëna të jenë në cache?
Le të imagjinojmë një situatë - në servera ka 256 GB RAM, në rutinën e përditshme ClickHouse merr rreth 60-80 GB, dhe në pike - deri në 130. Çfarë mund të aktivizoni dhe rregulloni për të pasur më shumë të dhëna në cache dhe për pasojë më pak shfletime në disk?
Si zakonisht, cache i faqes së sistemit operativ e trajton mirë këtë detyrë. Nëse hapni thjesht topin, shikoni atje cached ose free - gjithashtu shkruhet se sa është cached - mund të vëreni se e gjithë memoria e lirë është përdorur për cache. Dhe këto të dhëna gjatë leximit do të lexohen jo nga disku, por nga RAM. Në këtë rast, mund të them se cache përdoret në mënyrë efikase, sepse po kompresohen të dhënat.
Megjithatë, nëse dëshironi të përshpejtoni disa kërkesa të thjeshta edhe më shumë, ka mundësi të activizoni brenda ClickHouse cache në të dhëna të papërdorura. Kjo quhet uncompressed cache. Në dosjen e konfigurimit config.xml vendosni madhësinë e cache të papërdoruara në vlerën që ju nevojitet - unë rekomandoj jo më shumë se gjysma e RAM të lirë, sepse pjesa tjetër do të shkojë për cache të faqes.
Për më tepër, ka dy cilësime në nivelin e kërkesës. Cilësimi i parë - use uncompressed cache — aktivizon përdorimin e saj. Rekomandohet të aktivizohet për të gjitha kërkesat, përveç atyre të rënda, të cilat mund të lexojnë të dhënat e plota dhe të shuajnë këtë cache. Dhe cilësimi i dytë është diçka si numri maksimal i rreshtave për përdorimin e cache. Ai automatikisht kufizon kërkesat e mëdha, kështu që ato të kalojnë qoftë dhe jashtë cache.
Si mund të konfiguroj storage_configuration për ruajtjen në RAM?
Në dokumentacionin e ri të ClickHouse kam lexuar një seksion lidhur . Në përshkrim ka një shembull me SSD të shpejtë.
Është interesante, si mund të konfiguroni të njëjtën gjë me memorie të nxehtë të vëllimit. Dhe një pyetje tjetër. Si funksionon select me një organizim të tillë të të dhënave, a do ta lexojë të gjithë setin apo vetëm atë që gjendet në disk, dhe a kompresohen këto të dhëna në memorie? Dhe si e kryen seksioni prewhere një organizim të tillë të të dhënave?
Kjo cilësim ndikon në ruajtjen e blloqeve të të dhënave, dhe formati i tyre asnjëherë nuk ndryshon.
Le të shqyrtojmë më në detaje.
Është e mundur të konfiguroni ruajtjen e të dhënave në RAM. Çdo gjë që konfigurohet për disk është rruga e tij. Ju krijoni një copë të tmpfs, e cila montohet në një rrugë të caktuar në sistemin e skedarëve. Caktoni këtë rrugë si rrugën për ruajtjen e të dhënave për pjesën më të nxehtë, aty fillojnë të hyjnë dhe të shkruhen copat e të dhënave, gjithçka është mirë.
Megjithatë, nuk e rekomandoj atë për shkak të besueshmërisë së ulët, megjithatë, nëse keni të paktën tre kopje në qendra të ndryshme të të dhënave, atëherë mund ta bëni. Në rastin e ndonjë problemi, të dhënat do të rikthehen. Imagjinoni se serveri papritur u fik dhe u ndez përsëri. Disa montimi është bërë sërish, por atje është boshllëk. Serveri ClickHouse, kur fillon, sheh se atij i mungojnë këto copa, ndonëse sipas metadatave të ZooKeeper ato duhet të jenë. Ai kontrollon në cilat kopje i ka ato, i kërkon dhe i shkarkon. Kështu të dhënat do të rikthehen.
Në këtë sens, ruajtja e të dhënave në RAM nuk ndryshon esencialisht nga ruajtja e tyre në disk, sepse kur shkruhen të dhënat në disk, ato gjithashtu fillimisht hyjnë në cache të faqeve dhe regjistrohen fizikisht me vonesë. Kjo varet nga varianti i montimit të sistemit të skedarëve. Por për çfarëdo rasti do të them se ClickHouse nuk bën fsync gjatë insertit.
Megjithatë, të dhënat në RAM ruhen në të njëjtin format si në disk. Kërkesa select në të njëjtën mënyrë zgjedh copat që duhet të lexohen, në copa zgjedh intervalet e nevojshme të të dhënave, dhe lexon ato. Dhe prewhere funksionon krejtësisht njësoj, pavarësisht nëse të dhënat ishin në RAM apo në disk.
Derisa sa unikë vlera janë efektive Low Cardinality?
Low Cardinality është ndërtuar në mënyrë të mençur. Ai krijon fjalorët e të dhënave, por ato janë lokale. Së pari, fjalorët janë për secilën copë, së dyti, edhe brenda një cope ata mund të jenë të ndryshëm për çdo interval. Kur numri i vlerave unike arrin një kufi — mendoj se një milion — fjalori thjesht shtyhet dhe krijohet një ri.
Përgjigja në përgjithësi: për çdo interval lokal — le të themi, për çdo ditë — diku deri në një milion vlera unike, Low Cardinality është efektiv. Pas kësaj do të ketë vetëm një fallback, ku do të përdoren shumë fjalorë të ndryshëm, dhe jo një. Ajo do të punojë pak a shumë si një kolonë e zakonshme e tipit string, ndoshta pak më pak efikase, por nuk do të ndodhin degrada të rënda të performancës.
Cilat janë praktikat më të mira për kërkimin me tekst të plotë në një tabelë me pesë miliardë rreshta?
Ka mundësi të ndryshme për përgjigje. E para — të thuash se ClickHouse nuk është një sistem për kërkimin e plotë të tekstit. Për këtë ka sisteme të specializuara për shembull, dhe . megjithatë, unë gjithnjë e më shpesh takohem me njerëz që thonë se po kalojnë nga Elasticsearch në ClickHouse.
Pse ndodh kjo? Ata e shpjegojnë këtë duke thënë se Elasticsearch nuk arrin të përballojë ngarkesat në disa volumet, filluar nga ndërtimi i indekseve. Indekset bëhen shumë voluminoze, dhe, nëse thjesht i transferoni të dhënat në ClickHouse, rezulton se ato ruhen në mënyrë shumë më efikase në volum. Në të njëjtën kohë, kërkesat kërkuese shpesh nuk ishin të tilla që duhej të gjeje një frazë në të gjithë volumet e të dhënave duke marrë parasysh morfologjinë, por ishin plotësisht të tjera. Për shembull, gjej në logët e disa orëve të fundit për një nënsekuencë të bajtëve.
Në këtë rast, ju krijoni një indeks në ClickHouse, ku fusha e parë do të jetë data me orën. Dhe eliminimi më i madh i të dhënave do të jetë saktësisht sipas intervalit të datave. Brenda intervalit të datave të zgjedhur, si rregull mund të bëhet një kërkim i plotë tekstual madje me metodën brute force duke përdorur like. Operator like në ClickHouse është operatori më efikas like që mund të gjeni. Nëse gjeni më të mirë — më tregoni.
Por prapë like është një skanim i plotë. Dhe skanimi i plotë mund të jetë i ngadalshëm jo vetëm sipas CPU-së, por edhe sipas diskut. Nëse ndodhtë që keni një terabajt të dhënave në ditë, dhe ju po kërkoni për një fjalë brenda një dite, do të duhet të skanoni një terabajt. Dhe ai sigurisht do të jetë në disqet e zakonshme të ngurtë, dhe përfundimisht ata do të ngarkohen në mënyrë që ju nuk do të mund të hyni në këtë server përmes SSH.
Në këtë rast, unë jam gati të ofroj një mashtrim tjetër të vogël. Ai është nga kategoria eksperimentale — ndoshta do të funksionojë, ndoshta jo. Në ClickHouse ka indekse për kërkimin e plotë në formën e filtrave Bloom trigram. Kolegu ynë nga kompania Arenadata e ka provuar këtë indeks, dhe shumë herë ata funksionojnë siç është menduar.
Për të përdorur saktë këto, është e nevojshme të kuptohet mirë se si funksionojnë: çfarë përfaqëson filtrimi Bloom trigram dhe si të zgjedhim madhësinë e tij. Mund të them se ato do t'ju ndihmojnë për kërkesa mbi fraza të rralla, nën-string-a që shpesh nuk gjenden në të dhëna. Në këtë rast, do të zgjidhen nën-rajonet sipas indekseve dhe do të lexohen më pak të dhëna.
Së fundmi, në ClickHouse janë shfaqur funksione edhe më të avancuara për kërkimin me tekst të plotë. Kjo është, së pari, kërkimi menjëherë i shumë nën-string-eve në një kalim, duke përfshirë variantet me ndjeshmëri ndaj rastit, pa ndjeshmëri ndaj rastit, me mbështetje për UTF-8 ose vetëm për ASCII. Zgjidhni atë që është më efektive për ju.
Është shfaqur gjithashtu kërkimi i disa shprehjeve të rregullta në një kalim. Nuk keni nevojë të shkruani X like një nën-string tjetër. Thjesht shkruani, dhe gjithçka ekzekutohet maksimalisht efektivisht.
E treta — tani ekziston kërkimi afatshkurtër për reg-exp dhe kërkimi afatshkurtër për nën-string-e. Nëse dikush shkruan një fjalë me gabim, ajo do të kërkohet sipas përputhjes maksimale.
Si është më mirë të organizohet aksesin në ClickHouse për një numër të madh përdoruesish?
Tregoni se si të organizoni më mirë aksesin për një numër të madh përdoruesish dhe analistësh. Si të formoni një radhë, të jepni përparësi kërkesave max concurrent queries, dhe cilat mjete të përdorni?
Nëse klusteri është mjaft i madh, një zgjidhje e mirë do të ishte të çoni dy servera të tjerë, të cilët do të shërbenin si pikë hyrje për analistët. Kështu, nuk do të lejoni analistët të hyjnë në shard-a konkret të klusterit, por thjesht të krijoni dy servera bosh, pa të dhëna, dhe atje të konfiguroni të drejtat e aksesit. Në këtë mënyrë, konfigurimet e përdoruesve gjatë kërkesave të shpërndara kalojnë në serverat e largët. Kështu që gjithçka e konfiguroni në këto dy servera, dhe konfigurimet kanë efekt në të gjithë klusterin.
Në parim, këta servera janë pa të dhëna, por sasia e memories RAM është mjaft e rëndësishme për ekzekutimin e kërkesave. Disku gjithashtu mund të përdoret për të dhëna temporale, nëse është aktivizuar agregimi i jashtëm ose renditja e jashtme.
Është e rëndësishme të shikoni në konfigurimet që lidhen me të gjitha limitet e mundshme. Nëse tani hyj në klusterin e "Yandex.Metrics" si analist dhe dërgoj një kërkesë select count from hits, atëherë menjëherë do të ma kthejnë një përjashtim që nuk mund ta ekzekutoj kërkesën. Numri maksimal i rreshtave që më lejohet të skanoj është njëqind miliard, ndërsa në total në kluster ka pesëdhjetë trilion në një tavëll. Ky është kufiri i parë.
Të themi se heq kufirin për numrin e rreshtave dhe ekzekutoj kërkesën përsëri. Pastaj do të shoh një përjashtim tjetër — është aktivizuar konfigurimi force index by date. Nuk mund ta ekzekutoj kërkesën, nëse nuk përcaktoj një diapazon datash. Nuk është e nevojshme të mërziteni që analistët do të përcaktojnë atë manualisht. Rast tipik — është shkruar një diapazon datash ku data e ngjarjes është mes javës. Pastaj thjesht nuk e kishin vendosur saktë hapje-hapje, dhe në vend të and dolën or — or URL match. Nëse nuk ka kufizim, do të fillojë të skanojë kolonën URL dhe do të shpenzojë një sasi të madhe burimesh.
Përveç kësaj, në ClickHouse ka dy konfigurime për prioritete. Për fat të keq, ato janë shumë primitive. Njëra quhet thjesht prioriteti. Nëse prioriteti ≠ 0, dhe kërkesa me ndonjë prioritet po ekzekutohet, por po ekzekutohet një kërkesë me prioritet më pak se, çka do të thotë prioritet më të lartë, atëherë kërkesa me vlerë prioriteti më të lartë, që do të thotë prioritet më të ulët, thjesht do të pezullohet dhe nuk do të punojë fare për atë kohë.
Kjo është një konfigurim shumë i egër, dhe nuk është i përshtatshëm për ato raste, kur në kluster ka një ngarkesë të vazhdueshme. Por nëse keni kërkesa të shkurtra, impulsive që janë të rëndësishme, dhe në shumicën e rasteve klusteri pushon, ky konfigurim do t'ju përshtatet.
Konfigurimi i ardhshëm i prioriteteve quhet OS thread priority. Ai thjesht vendos për të gjithë thread-et e ekzekutimit të kërkesës një vlerë nice për planifikuesin Linux. Funksionon si duhet, por ndonjëherë funksionon. Nëse vendosni vlerën më minimale të nice — kjo është më e madhe në madhësi, dhe do të thotë prioritet më të ulët — dhe për kërkesat me prioritet të lartë vendosni -19, atëherë CPU do të konsumojë kërkesa me prioritet të ulët rreth katër herë më pak sesa ato me prioritet të lartë.
Duhet gjithashtu të konfiguroni maksimalin e kohës së ekzekutimit të kërkesës — le të themi, pesë minuta. Shpejtësia minimale e ekzekutimit të kërkesës — kjo është më e mira. Kjo konfigurim ka ekzistuar prej një kohe të gjatë, dhe nevojitet, për të mos thënë se ClickHouse nuk ngadalëson, por për ta forcuar atë.
Imagjinoni se jeni duke konfiguruar: nëse një kërkesë përpunon më pak se një milion radhë në sekondë — kjo nuk duhet bërë. Kjo është një turp për emrin tonë të mirë, për bazën tonë të dhënash të mirë. Le ta ndalojmë këtë. Në të vërtetë ka dy cilësime. Njëra quhet shpejtësia minimale e ekzekutimit — në radhët në sekondë, ndërsa tjetra quhet koha e skadimit para kontrollit të shpejtësisë minimale të ekzekutimit — sipas parazgjedhjes pesëmbëdhjetë sekonda. Kështu që pesëmbëdhjetë sekonda janë të pranueshme, por pastaj, nëse është ngadalë, thjesht të hidhet një përjashtim — të ndalohet kërkesa.
Gjithashtu duhet të konfigurojmë kuotat. Në ClickHouse ka një funksionalitet të integruar për kuota, i cili llogarit konsumimin e burimeve. Por fatkeqësisht, jo burimeve fizike si CPU, disqe, por logjike — numri i kërkesave të përpunuara, radhët dhe bajtët e lexuar. Dhe mund të konfigurojmë, për shembull, maksimumi njëqind kërkesa në pesë minuta dhe një mijë kërkesa në orë.
Pse është kjo e rëndësishme? Sepse disa kërkesa analitike do të kryhen manualisht drejtpërdrejt nga klienti ClickHouse. Dhe gjithçka do të shkojë mirë. Por nëse keni analistë të avancuar në kompaninë tuaj, ata do të shkruajnë një skenar, dhe në skenar mund të ketë një gabim. Dhe ky gabim do të çojë në faktin që kërkesa do të ekzekutohet në një cikël të pafund. Atëherë duhet të mbrohemi nga kjo.
A është e mundur të jepen rezultatet e një kërkese në dhjetë klientë?
Kemi disa përdorues që pëlqejnë të vijnë me kërkesa shumë të mëdha në të njëjtën kohë. Kërkesa është e madhe, ekzekutohet në thelb shpejt, por për shkak se ka shumë kërkesa të tilla në të njëjtën kohë, bëhet shumë e vështirë. A mundet që një kërkesë e njëjtë, e cila është dërguar dhjetë herë radhazi, të ekzekutohet një herë, dhe rezultati të dorëzohet dhjetë klientëve?
Problemi është se në të vërtetë nuk kemi rezultate të caches ose caches të të dhënave ndërmjet. Ka një cache të faqes të sistemit operativ, i cili do të lejojë që të dhënat të mos lexohen nga disku përsëri, por fatkeqësisht, të dhënat do të kompresohen, deserializohen dhe do të përpunohen përsëri.
Do të dëshironim ndonjë mënyrë për ta shmangur këtë, ose duke cache të dhënat ndërmjet, ose duke ndërtuar kërkesa të ngjashme në një radhë dhe duke shtuar cache rezultatesh. Tani kemi një pull request në zhvillim, i cili shton cache të kërkesave, por vetëm për nënkërkesat në seksionet in dhe join — pra, zgjidhja nuk është e plotë.
Megjithatë, na ndodh një situatë e tillë gjithashtu. Sidomos shembulli kanonik — janë kërkesa me paginacion. Ka një raport, në të ka disa faqe, dhe bëhet një kërkesë limit 10. Pastaj e njëjta gjë, por limit 10,10. Më pas një faqe tjetër. Dhe pyesim: pse çdo herë llogarisim të gjitha këto? Por tani nuk ka zgjidhje, dhe nuk mund ta shmangim këtë.
Ka një zgjidhje alternative, e cila vendoset si sidecar pranë ClickHouse — .
Kirill Shvakov: Në ClickHouse Proxy ka një rregullator të integruar dhe një cache rezultatesh të integruar. Ka shumë konfigurime të bëra, sepse është zgjidhur një problem i ngjashëm. Proxy lejon të kufizohen kërkesat, duke i renditur ato në një radhë, dhe duke rregulluar sa kohë jeton cache i kërkesave. Nëse kërkesat janë vërtet të njëjta, Proxy do t'i shkëmbejë ato shumë herë, ndërsa do të bëjë kërkesë në ClickHouse vetëm një herë.
Nginx gjithashtu ka cache në versionin falas, dhe kjo do të funksionojë gjithashtu. Nginx ka edhe konfigurime që, nëse kërkesat kanë ardhur në të njëjtën kohë, ai do të ngadalësojë të tjerat derisa njëra të ekzekutohet. Por pikërisht në ClickHouse Proxy konfigurimi është bërë shumë më mirë. Ai është zhvilluar pikërisht për ClickHouse, pikërisht për këto kërkesa, kështu që përshtatet më mirë. Dhe gjithashtu instalimi është i thjeshtë.
Si të veprojmë me operacionet asinkrone dhe pamjet e materializuara?
Ka një problem të tillë, që operacionet me motorin e riprodhimit janë asinkrone — së pari regjistrohen të dhënat, pastaj ndodh përmbledhja e tyre. Nëse nën tavolinë jeton një tabelë materializimi me disa agregate, atëherë dublikat do të regjistrohen në të. Dhe nëse nuk ka ndonjë logjikë të komplikuar, të dhënat do të dublikatohen. Çfarë mund të bëjmë në lidhje me këtë?
Ka një zgjidhje të ndritshme — të implementoni një trigger për një klasë të caktuar materializimi gjatë operacioneve asinkrone të përmbledhjes. A ka ndonjë "plumb argjendi", plane për implementimin e funksionaliteteve të tilla?
Duhet të kuptojmë se si funksionon deduplifikimi. Ajo që do t'ju tregoj tani nuk i përket pyetjes, por për çdo rast ia vlen të shpresojmë.
Kur futni në një tabelë të replikimit ka deduplifikim të grupeve të futur. Nëse e futni përsëri të njëjtin grup, që përmban të njëjtin numër radhësh në të njëjtin rend, të dhënat do të deduplifikohen. Do të merrni "Ok" si përgjigje në insert, por në fakt do të regjistrohet një sasi e vetme të dhënash, dhe ajo nuk do të jetë e dubluar.
Kjo është e nevojshme për qartësi. Nëse gjatë futjes keni marrë "Ok", atëherë të dhënat tuaja janë futur. Nëse keni marrë një gabim nga ClickHouse, atëherë ato nuk janë futur dhe duhet të përsëritur futjen. Por nëse gjatë futjes lidhja është ndërprerë, atëherë nuk e dini nëse të dhënat janë futur apo jo. Mundësia e vetme është të përsërisni futjen sërish. Nëse të dhënat në të vërtetë janë futur dhe ju i futni përsëri, ka deduplifikim të blloqeve. Ai është i nevojshëm për të shmangur kopjet e tepërta.
Dhe është e rëndësishme gjithashtu si funksionon për pamjet materializuese. Nëse të dhënat janë deduplifikuar gjatë futjes në tabelën kryesore, ato nuk do të shkojnë as në pamjen materializuese.
Tani për pyetjen. Keni një situatë më të komplikuar, sepse po regjistroni kopjet e rreshtave të veçantë. Pra, nuk është një paketë e tërë që është e dyfishtë, por pikërisht rreshtat konkretë, dhe ato shkrihen në sfond. Në të vërtetë, të dhënat do të shkrihen në tabelën kryesore, ndërsa në pamjen materializuese do të shkojnë ato që nuk kanë kaluar procesin e shkrirë dhe gjatë bashkimeve nuk do të ndodhë asgjë me pamjet materializuese. Sepse pamja materializuese është asgjë tjetër veçse një trigger për insert. Me operacione të tjera, nuk ndodh asgjë shtesë.
Dhe këtu nuk mund të të gëzoj. Të vetëm do të kërkosh një zgjidhje të veçantë për këtë rast. Për shembull, a mund të bëhet gjithashtu zëvendësimi në pamjen materializuese dhe ndoshta mënyra e deduplifikimit do të funksionojë në të njëjtën mënyrë. Por, për fat të keq, jo gjithmonë. Nëse ajo është agreguese, atëherë nuk do të funksionojë.
Kirill Shvakov: Edhe ne kemi pasur një ndërlikim kur ishim në fillim. Kishte një problem që kishte shfaqje reklamesh, dhe kishte disa të dhëna që mund t'i tregonim në kohë reale — janë thjesht shfaqje. Ato janë rrallë herë të dyfishta, por nëse ndodhin, ne gjithsesi do t'i shkrijnë më vonë. Dhe kishte gjëra që nuk mund të dyfishoheshin — klikimet dhe të gjithë kjo histori. Por gjithashtu, do të donim t'i shfaqnim ato pothuajse menjëherë.
Si janë bërë pamjet materializuese? Kishte pamje, ku shkruhej drejtpërdrejt — po zhvillohet shkalla në të dhëna të papërpunuara dhe shkruhet në view-it. Atje, në një moment të caktuar, të dhënat nuk ishin shumë të sakta, ato kopjoheshin etj. Dhe ka një pjesë tjetër të tabelës, ku ato duken gjithashtu ashtu si pamjet materializuese, dmth. strukturën e tyre janë krejtësisht të njëjtë. Një herë në një kohë të caktuar, ne rregullojmë të dhënat, llogarisim të dhënat pa kopje, shkruajmë në ato tabela.
Ne jemi kaluar përmes API — me ClickHouse me duar këtë nuk do të funksionojë. Dhe API shikon: kur kam datën e fundit të shtimit në tabelë, ku të dhënat janë garantuar të jenë të sakta, dhe ai bën një kërkesë në një tabelë dhe në një tabelë tjetër. Nga njëra tabelë merr deri në një kohë të caktuar, dhe nga tjetra merr atë që ende nuk është llogaritur. Dhe kjo funksionon, por jo me mjetet e ClickHouse.
Nëse keni një API ndonjëherë — për analistë, për përdoruesit — atëherë në thelb, kjo është një mundësi. Ju gjithmonë llogarisni, gjithmonë ripërllogariteni. Kjo mund të bëhet një herë në ditë ose në ndonjë kohë tjetër. Ju vetë zgjidhni intervalin që nuk ju nevojitet dhe nuk është kritik.
Në ClickHouse ka shumë log-e. Si mund ta shoh gjithçka që ndodh me serverin, në moment?
Në ClickHouse ka një numër shumë të madh log-esh të ndryshme, dhe ky numër po rritet. Në versionet e reja, disa prej tyre janë aktivizuar edhe nga default, në versionet e vjetra ata duhet të aktivizohen gjatë përditësimit. Ende, ata po bëhen gjithnjë e më të shumtë. Do të doja të shihja në fund se çfarë po ndodh tani me serverin tim, ndoshta në ndonjë dashboard të përmbledhur.
A nuk keni ndonjë ekip ClickHouse, ose në ekipet e miqve tuaj, të cilët mbështesin ndonjë funksion të dashboard-eve të gatshme, të cilat do të shfaqin këto log-e në formën e një produkti të gatshëm? Në fund të fundit, vetëm të shikosh log-e në ClickHouse — është fantastike. Por do të ishte shumë e mrekullueshme nëse kjo do të ishte bërë tashmë në formën e një dashboard-i. Do të isha shumë i lumtur për këtë.
Ka dashboard-e, ndonëse ato nuk janë të standardizuara. Në kompaninë tonë, rreth 60 ekipe përdorin ClickHouse, dhe e çuditshme është se shumë prej tyre kanë dashboard-e që i kanë krijuar vetë, dhe ata janë paksa të ndryshëm. Disa ekipe përdorin instalimin e brendshëm të "Yandex.Cloud". Aty ka disa raporte të gatshme, megjithatë jo të gjitha të nevojshme. Të tjerët kanë të tyre.
Kollegët e mi në "Metri" kanë panelin e tyre në Grafana, ndërsa unë kam timin për klasterin e tyre. Atje shikoj gjëra si hit cache për cache-n e regjistrimeve. Dhe madje, gjëja është edhe më e komplikuar, pasi ne përdorim mjete të ndryshme. Panelin tim e kam krijuar me një mjet shumë të vjetër, i quajtur Graphite-web. Ai është krejtësisht i pamjekur. Dhe kështu unë vazhdoj ta përdor atë, megjithëse Grafana ndoshta do të ishte më e përshtatshme dhe më e bukur.
Gjëja bazike në panele është e njëjtë. Ato janë metrikat sistemore për klasterin: CPU, memorie, disk, rrjet. Të tjera përfshijnë numrin e kërkesave simultane, numrin e bashkimeve simultane, numrin e kërkesave në sekondë, numrin maksimal të fragmenteve për parti të tabelave MergeTree, vonesën e replikimit, madhësinë e radhës së replikimit, numrin e rreshtave të futur në sekondë, numrin e blloqeve të futur në sekondë. Këto janë gjithçka që nuk vjen nga log-ët, por nga metrikat.
Vladimir Kolobaev: Aleksei, do doja ta rregulloja pak. Ka Grafana. Grafana ka një datasource, që është ClickHouse. Kështu që unë mund të bëj kërkesa direkt në ClickHouse nga Grafana. Në ClickHouse ka një tabelë log-ësh, e cila është e njëjtë për të gjithë. Dua që në fund në Grafana të kem akses në këtë tabelë log-ësh dhe të shoh ato kërkesa që serveri im i bën. Do të ishte e shkëlqyer të kishim një panel të tillë.
Unë e kam riparuar vetë. Por më lind një pyetje - nëse gjithçka është standardizuar, dhe Grafana përdoret nga të gjithë, pse nuk ka një panel të tillë zyrtar në "Yandex"?
Kirill Shvakov: Në të vërtetë, datasource-i që lidhet me ClickHouse tani mbështetet nga Altinity. Dhe thjesht dua të jap një drejtim se ku të kërkoj dhe kë të nxis. Mund të pyesim ata, pasi "Yandex" krijon ClickHouse, jo historinë përreth tij. Altinity është kompania kryesore që tani po promovon ClickHouse. Ata nuk do ta braktisin atë, por do ta mbështesin. Sepse në parim, për të ngarkuar një panel në faqen e Grafana, nevojitet vetëm të regjistrohesh dhe ta ngarkosh - nuk ka probleme të veçanta.
Alexey Milovidov: Gjatë vitit të fundit, ClickHouse ka shtuar shumë mundësi për profilizimin e kërkesave. Ka metrika për çdo kërkesë për përdorimin e burimeve. Dhe shumë kohët e fundit është shtuar një profiler më i ulët për të parë ku cada kërkesë merr çdo milisekondë. Por për të shfrytëzuar këtë funksionalitet, më duhet të hap klientin e konsolës dhe të shkruaj kërkesën, që vazhdimisht e harroj. E kam ruajtur dikund dhe vazhdimisht harroj se ku.
Do doja që të kishte një mjet, ku shkruhet thjesht - këtu janë kërkesat e tua të rënda, të grupuara sipas klasave të kërkesave. Pressa mbi njëra, dhe do më thonin pse ajo është e rëndë. Tani nuk ka një zgjidhje të tillë. Dhe në të vërtetë është shumë e çuditshme që, kur njerëzit më pyesin: "A ka ndonjë panel të gatshëm për Grafana?", unë them: "Shkoni në faqen e Grafana, aty ka komuniteti 'Panele', dhe aty ka panel nga Dimka, ka panel nga Kostyana. Çfarë është kjo, nuk e di, unë vetë nuk kam përdorur."
Si të ndikojmë në bashkimet, për të mos e bërë serverin të bie në OOM?
Kam një tabelë, në të cilën ka vetëm një parti, ajo është ReplacingMergeTree. Kam shkruar të dhëna në të për katër vjet. Duhej të bëja një alter dhe të fshija disa të dhëna.
E bëra këtë, dhe gjatë përpunimit të kësaj kërkese u shqetësua e tërë memoria në të gjithë serverët e klasterit, dhe të gjithë serverët e klasterit u shpërthyen në OOM. Pastaj ata të gjithë së bashku u ngjitën, filluan të kryejnë bashkimin e kësaj operacioni të të dhënave dhe përsëri ranë në OOM. Më pas, ata u ringjallën dhe përsëri ranë. Dhe kjo gjë nuk përfundoi.
Pastaj doli se në të vërtetë kjo ishte një gabim, që ekipi e rregulloi. Kjo është shumë e shkëlqyer, faleminderit shumë. Por ndjenja mbeti. Dhe tani, kur mendoj për atë që duhet të bëj një bashkim në tabelë, më shfaqet një pyetje - pse nuk mund të ndikoj në këto bashkime në një farë mënyre? Për shembull, t'i kufizoj ata me sa memorie të nevojshme, ose në parim me numrin e tyre, që do të përpunojnë saktësisht këtë tabelë.
Kam një tabelë, e cila quhet "Metri", më përpunoni atë, ju lutem, në dy rrjedha. Mos e bëni të existente pesë ose dhjetë bashkime paralelisht, bëni për dy. Mendoj se për dy do të kem mjaft memorie, por për të dhjetë trafik ndoshta nuk do të ketë. Pse frigë mbetet? Sepse tabela rritet, dhe ndonjëherë do të përballem me një situatë ku përveç se për shkak të gabimit, për shkak që të dhënat do të ndryshojnë në një kaq sasi të madhe, që mund të mos kem mjaft memorie në server. Dhe atëherë serveri do të bjerë në OOM gjatë bashkimit. Përveç kësaj, unë mund të anuloj mutacionin, por bashkimet nuk i kam më në kontroll.
E dini, gjatë mërgjeve serveri nuk do të bien në OOM, sepse gjatë mërgimit përdoret sasia e RAM-it vetëm për një grup të vogël të dhënash. Pra, gjithçka do të shkojë mirë pavarësisht nga volumi i të dhënave.
Vladimir Kolobaev: Mirë. Këtu ka një moment, që pas rregullimit të defekteve, shkarkova një version të ri për veten time, dhe në një tavë tjetër, më të vogël, ku ka shumë parti, bëra një operacion të ngjashëm. Dhe gjatë procesit të mërgimit, u konsumuan rreth 100 GB RAM. Kishim 150 të zënë, 100 e mori, dhe mbeti një hapësirë prej 50 GB, kështu që nuk ra në OOM.
Çfarë më mbron tani nga rënia në OOM, nëse ai me të vërtetë konsumon rreth 100 GB RAM? Si të veproj në situatën, nëse papritur RAM-i për mërgimet mbaron?
Alexey Milovidov: Ka një problem të tillë, që konsumimi i RAM-it për mërgime nuk është i kufizuar. Problemi i dytë është se, nëse ndonjë mërgim është caktuar, ai duhet të ekzekutohet, sepse është regjistruar në logun e replikimit. Logu i replikimit është ajo që nevojitet për të sjellë replikën në një gjendje të qëndrueshme. Nëse nuk bëhen manovra manuale që do të tërheqin prapa atë log të replikimit, mërgimi do të duhet, një mënyrë apo një tjetër, të ekzekutohet.
Sigurisht, do të ishte e dobishme të kishe një kufizim në RAM, i cili "për çdo rast" mbron pikërisht nga OOM. Ai nuk do të ndihmonte për të përfunduar mërgimin, ai do të fillonte përsëri, do të arrinte në një prag të caktuar, do të jepte një përjashtim dhe pastaj do të fillonte sërish - nuk do të dilte asgjë e mirë prej këtij veprimi. Por në parim, do të ishte e dobishme të vendosej ky kufizim.
Si do të zhvillohet driver-i i Golang për ClickHouse?
Driver-i i Golang, i shkruar nga Kirill Shvakov, tani duket se mbështetet zyrtarisht nga ekipi i ClickHouse. Ai , tani është i madh dhe i vërtetë.
Një shënim i vogël. Ka një magazinë të shkëlqyer dhe të dashur që ka forma normale të rendit të pafund - kjo është Vertica. Ata gjithashtu kanë driver-in e tyre zyrtar python, i cili mbështetet nga zhvilluesit e Vertica. Disa herë ka ndodhur që versionet e magazinës dhe versionet e driver-it janë distancuar shumë, dhe driver-i në një moment ka ndaluar së funksionuari. Dhe një moment tjetër. Mbështetja për këtë driver zyrtar, më duket se administrohet nga sistemi "nipëll" - ti shkruan atyre një çështje, dhe ajo mbetet atje përjetësisht.
Kam dy pyetje. Tani driver-i i Golang të Kirillit është mënyra pothuajse default për të komunikuar nga Golang me ClickHouse. Me përjashtim të ndokujt që komunikon përmes ndërfaqes http, sepse ashtu i pëlqen. Si do të zhvillohet ky driver? A do të sinkronizohet me ndonjë ndryshim të rëndësishëm në magazinë? Dhe cila është procedura për shqyrtimin e çështjeve?
Kirill Shvakov: E para - si është e organizuar nga ana burokratike. Ky moment nuk është diskutuar, kështu që nuk kam çfarë të përgjigjem.
Për të përgjigjur në pyetjen për çështjet, është e nevojshme një histori e vogël e driver-it. Unë kam punuar në një kompani ku kishte shumë të dhëna. Ishte një rrotullues reklamesh me një numër të madh ngjarjesh që duhej të ruheshin ndokund. Në një moment doli ClickHouse. Ne i dërguam aty të dhënat dhe në fillim gjithçka ishte mirë, pastaj ClickHouse ra. Në atë moment vendosëm se nuk na nevojitej.
Pasi kaloi një vit, u rikthyem në idenë e përdorimit të ClickHouse, dhe na duhej të shkruanim të dhënat ndokund. Hyrja ishte e tillë - hardueri shumë i dobët, burime të pakta. Por gjithmonë kemi punuar kështu, dhe ndaj shikuam në drejtim të protokollit natyror.
Duke qenë se ne punonim në Go, ishte e qartë që na duhej një driver në Go. Unë e zhvillova atë praktikisht me kohë të plotë - kjo ishte detyra ime e punës. Deri në një moment, ne e përfunduam atë, dhe në parim askush nuk e priste që dikush përveç nesh do ta përdorte. Pastaj erdhi CloudFlare me të njëjtin problem, dhe për një periudhë, ne punuam shumë ngjashëm, sepse kishin të njëjtat detyra. Për më tepër, ne e bënim këtë në vetë ClickHouse, si dhe në driver.
Në një moment thjesht u ndala së punuari me ta, sepse aktiviteti im në lidhje me ClickHouse dhe puna ndërruan pak. Prandaj, çështjet nuk mbyllen. Herë pas here, njerëzit që ndonjëherë kanë diçka për vete, bënë komitete në depozitë. Atëherë shikoj pull request-in dhe ndonjëherë madje ndreq diçka vetë, por kjo ndodh rrallë.
Deshiroj të kthehem te driver-i. Disa vite më parë, kur filluam të gjithë këtë, ClickHouse ishte gjithashtu ndryshe dhe me mundësi të tjera. Tani ka kuptim se si ta rregullojmë driver-in që të funksionojë mirë. Nëse kjo ndodh, versioni 2 do të jetë në çdo rast jo kompatibil për shkak të kështjellave të akumuluara.
Si e organizo këtë punë, nuk e di. Edhe unë nuk kam shumë kohë. Nëse ndonjë njerëz do të zhvillonin driverin, mund t'i ndihmoj dhe t'u tregoj se çfarë të bëjnë. Por pjesëmarrja aktive e "Yandex" në zhvillimin e projektit deri tani nuk është diskutuar.
Alexey Milovidov: Në të vërtetë, për momentin nuk ka asnjë burokraci në lidhje me këta drivera. E vetmja gjë është se ata janë sjellë në një organizatë zyrtare, pra ky driver tani është njohur si një zgjidhje zyrtare për Go. Ekzistojnë edhe disa drivera të tjerë, por ato janë të veçanta.
Brenda nesh nuk ka asnjë zhvillim për këta drivera. Pyetja është: a do të mund të punësojmë një person të veçantë, jo për këtë driver specifik, por për zhvillimin e të gjitha driverëve të komunitetit, ose a do të mund të gjejmë ndonjë njeri nga jashtë.
Sikur të jashtmi nuk ngrihet pas ri-ngarkimit me opsionin lazy_load të aktivizuar. Çfarë të bëjmë?
Kemi aktivizuar opsionin lazy_load, dhe pas ri-ngarkimit të serverit, fjalori nuk ngrihet vetë. Ai ngrihet vetëm pasi përdoruesi të bëjë një kërkesë për këtë fjalor. Dhe gjatë kërkesës së parë, jepet një gabim. A mund të ngarkohet ndonjëherë automatikisht nga ClickHouse, ose duhet të kontrollojmë gjithmonë gatshmërinë e tij, që përdoruesit të mos marrin gabime?
Mund të kemi një version të vjetër të ClickHouse, prandaj fjalori nuk është ngarkuar automatikisht. A është e mundur?
Së pari, fjalorët mund të ngarkohen me forcë duke përdorur kërkesën system reload dictionaries. Së dyti, në lidhje me gabimin — nëse fjalori tashmë është ngarkuar, kërkesat do të punojnë mbi të dhënat që janë ngarkuar. Nëse fjalori ende nuk është ngarkuar, ai do të ngarkohet gjatë kërkesës.
Për fjalorët e rëndë, kjo nuk është shumë e përshtatshme. Për shembull, duhet të tërheqim një milion rreshta nga MySQL. Disa bëjnë një kërkesë të thjeshtë, por kjo kërkesë do të presë të gjithë ata një milion rreshta. Këtu ka dy zgjidhje. E para — fikni lazy_load. E dyta — kur serveri ngrihet, para se të ngarkohet, bëni system reload dictionary ose thjesht kryeni një kërkesë që përdor fjalorin. Atëherë fjalori do të ngarkohet. Duhet të kontrollojmë vetë disponueshmërinë e fjalorëve me opsionin lazy_load të aktivizuar, sepse ClickHouse nuk i ngre automatikisht.
Për pyetjen e fundit, përgjigja është — ose versioni është i vjetër, ose duhet të optimizohet.
Si të veprojmë me faktin se gjenerimi i fjalorëve të sistemit nuk ngarkon asnjë prej shumë fjalorëve, nëse ndonjëra prej tyre dështon?
Ka një tjetër pyetje në lidhje me system reload dictionaries. Ne kemi dy fjalorë — një nuk ngarkohet, tjetri ngarkohet. System reload dictionaries në këtë rast nuk ngarkon asnjë fjalor, dhe duhet të ngarkojmë përkatësisht një të veçantë sipas emrit të tij duke përdorur system reload dictionary. A është kjo e lidhur me versionin e ClickHouse?
Dua t'ju gëzoj. Ky veprim është ndërruar. Kështu që, nëse përditësoni ClickHouse, edhe kjo do të ndryshojë. Nëse nuk jeni të kënaqur me veprimin aktual system reload dictionaries, përditësoni dhe shpresojmë se do të ndryshojë në një mënyrë më të mirë.
A ka mundësi të konfiguroj kredencialet në konfigurimin e ClickHouse, por t'i mbaj ato të padukshme në raste gabimi?
Pyetja tjetër lidhet me gabimet që kanë të bëjnë me fjalorin, konkretisht me detajet. Ne kemi shkruar detajet e lidhjes në konfigurimin e ClickHouse për fjalorin, dhe në rast gabimi marrim këto detaje dhe fjalëkalimin në përgjigje.
Ne e zgjidhëm këtë gabim duke e nxjerrë informacionin në konfigurimin e driver-it ODBC. A ka ndonjë mënyrë për të konfiguruar detajet në konfigurimin e ClickHouse, por pa i ekspozuar ato në rast gabimesh?
Këtu zgjidhja është të specifikoni këto credentials në odbc.ini, dhe në vetë ClickHouse të tregoni vetëm emrin e burimit të të dhënave ODBC. Për burimet e tjera të fjalorëve, nuk do të ketë të njëjtën situatë — as për fjalorin me MySQL, as për të tjerët nuk duhet të shihni fjalëkalimin në një mesazh gabimi. Po për ODBC do të shikoj — nëse ka, thjesht duhet ta heqim atë.
Bonus: sfondet për Zoom nga takimet.
Duke klikuar në imazh, për lexuesit më të vendosur do të hapen fonde bonus me takimet. Shuarim zjarrin bashkë me maskotat e teknologjive Avito, bisedojmë me kolegët nga dhoma e sistem administratës ose klubi kompjuterik retro dhe realizojmë një daily nën urën me grafit.
Burimi: habr.com
