U travnju su se inženjeri Avita okupili na online sastanku s glavnim razvojnim inženjerom ClickHouse, Aleksejem Milovidovim, i Kirilom Shvakovim, Golang programerom iz tvrtke Integros. Raspravljali su o tome kako koristimo sustav za upravljanje bazama podataka i koje nam poteškoće nastaju.
Na temelju sastanka sastavili smo članak s odgovorima stručnjaka na naša i pitanja gledatelja o backupima, resharding podacima, vanjskim rječnicima, Golang drajveru i ažuriranju verzija ClickHouse. To može biti korisno za programere koji već aktivno rade s DB-om "Yandexa" i zanimaju se za njezinu sadašnjost i budućnost. Kao standard, odgovore daje Aleksej Milovidov, osim ako nije navedeno drugačije.
Opasnost, ispod je puno teksta. Nadamo se da će sadržaj s pitanjima pomoći da se bolje snađete.

Sadržaj
Ako ne želite čitati tekst, možete pogledati snimku okupljanja . Vremenske oznake su u prvom komentaru ispod videa.
ClickHouse se stalno ažurira, a naši podaci se ne ažuriraju. Što učiniti?
ClickHouse se stalno ažurira, a naši podaci, koji su bili optimizirani final, ne ažuriraju se i nalaze se u rezervnoj kopiji.
Pretpostavimo da imamo problem i podaci su izgubljeni. Odlčimo se oporaviti, a ispostavlja se da se stari particije, koje su pohranjene na serverima sigurnosnih kopija, znatno razlikuju od trenutačno korištene verzije ClickHouse. Što učiniti u toj situaciji i je li to moguće?
Situacija u kojoj ste obnovili podatke iz sigurnosne kopije u starom formatu, a na novoj verziji se ne povezuju, nije moguća. Pratimo da format podataka u ClickHouse uvijek ostane unazad kompatibilan. To je mnogo važnije od unazadne kompatibilnosti funkcionalnosti ako se ponašanje neke rijetko korištene funkcije promijeni. Podaci koji se pohranjuju na disku, nova verzija ClickHouse uvijek bi trebala moći čitati. To je zakon.
Koje su najbolje prakse u ovom trenutku za rezervno kopiranje podataka iz ClickHouse-a?
Kako praviti sigurnosne kopije uzimajući u obzir da imamo operacije optimizacije final, ogromnu bazu podataka na terabajte, i podatke koji se ažuriraju, recimo, u protekla tri dana, a zatim s njima ne prolazi nikakve procedure?
Možemo stvoriti vlastito rješenje i na Bash-u napisati: skupljajte ovakve i ovakve sigurnosne kopije. Možda nije potrebno ništa improvizirati, a bicikl je davno izmišljen?
Prvo o najboljim praksama. Moji kolege uvijek savjetuju u odgovoru na pitanja o sigurnosnim kopijama da se podsjeti na uslugu „Yandex.Cloud”, gdje je taj zadatak već riješen. Tako da je koristite ako imate mogućnosti.
Nema potpune solucije, koja je stopostotno integrirana u ClickHouse, za backup. Postoje neki predlošci koje možete koristiti. Da biste dobili potpunu soluciju, morat ćete se malo manualno potruditi ili napraviti omotnice u obliku skripti.
Počnem od najjednostavnijih rješenja i završavam s najnaprednijima ovisno o volumenu podataka i veličini klastera. Što je klaster veći — rješenje postaje složenije.
Ako tablica s podacima zauzima samo nekoliko gigabajta, backup se može napraviti ovako:
- Spremite definiciju tablica, odnosno metapodatke — show create table.
- Izvršite dump pomoću ClickHouse klijenta — select * from table u datoteku. Po defaultu, dobit ćete datoteku u TabSeparated formatu. Ako želite više učinkovitosti — možete u Native formatu.
Ako je volumen podataka veći, backup će trajati duže i zauzeti mnogo prostora. To se naziva logički backup, nije vezan uz format podataka ClickHouse. Ako ga imate, u ekstremnom slučaju možete uzeti backup i učitati ga u MySQL za oporavak.
Za naprednije slučajeve, ClickHouse ima mogućnost stvaranja snapshot-a particija u lokalnom datotečnom sustavu. Ova mogućnost dostupna je u obliku upita alter table freeze partition. Ili jednostavno alter table freeze — to je snapshot cijele tablice.
Snapshot će biti stvoren konzistentnim za jednu tablicu na jednom shardu, to jest, na ovaj način nije moguće stvoriti konzistentan snapshot cijelog klastera. No za većinu zadataka takva potreba ne postoji, i dovoljno je na svakom shardu izvršiti upit i dobiti konzistentan snapshot. Stvara se u obliku hardlinkova i stoga ne zauzima dodatni prostor. Nakon toga, ovaj snapshot prebacite na backup server ili u skladište koje koristite za backupe.
Obnavljanje takvog backupa je prilično jednostavno. Prvo — kreirate tablice prema postojećim definicijama tablica. Zatim kopirate spremljene snapshotove particija u Directory-Detached za podatkovne tablice i izvršite upit attach partition. Takvo rješenje je sasvim prikladno za najozbiljnije količine podataka.
Ponekad je potrebna nešto izvanrednije — u slučajevima kada imate desetke ili čak stotine terabajta na svakom serveru i stotine servera. Postoji rešenje koje sam ispratio od kolega iz 'Yandex.Metrike'. Ne bih preporučio svima — pročitajte i sami odlučite da li je to pravo rešenje za vas.
Prvo je potrebno kreirati nekoliko servera sa velikim skladištima. Zatim na tim serverima podići nekoliko ClickHouse servera i konfigurisati ih tako da rade kao još jedna replika za iste shardove. A zatim koristiti na tim serverima fajl sistem ili neki alat koji omogućava kreiranje snimaka. Postoje dve opcije. Prva opcija su LVM snimci, a druga opcija je ZFS na Linuxu.
Nakon toga treba svakodnevno kreirati snimak, koji će zauzimati određeno mesto. Naravno, ako se podaci menjaju, vremenom će se povećavati količina prostora. Taj snimak može se dohvatiti u bilo momentu i vratiti podatke, takvo je neobično rešenje. Pored toga, potrebno je ograničiti te replike u konfiguraciji da ne pokušavaju postati lideri.
Hoće li se moći organizirati kontrolirano kašnjenje replika u valovima?
Ove godine planirate realizovati valove u ClickHouse-u. Da li će biti moguće organizovati kontrolisano kašnjenje replika u njima? Želeli bismo da se ovim putem zaštitimo od negativnih scenarija s alternativama i drugim promenama.
Da li je moguće napraviti neke povratne akcije za alternative? Na primer, u postojećem valu uzeti i reći da do tog trenutka primenjujemo izmene, a od tog trenutka prestajemo primenjivati izmene?
Ako je naš klaster napadnut i uništen, imamo uslovnu repliku sa kašnjenjem od sat vremena, gde možemo reći da je upotrebimo za sada, ali poslednjih deset minuta izmena u njoj nećemo primenjivati?
Prvo, o kontrolisanom kašnjenju replika. Takav zahtev je dobijen od korisnika i kreirali smo issue na GitHub-u sa molbom: 'Ako je nekome to potrebno, lajkujte, stavite srce'. Niko nije lajkovao, pa je issue zatvoren. Ipak, već sada je moguće dobiti tu mogućnost podešavanjem ClickHouse-a. Istina, samo od verzije 20.3.
ClickHouse kontinuirano u pozadini izvršava spajanje podataka - merge. Kada je merge izvršen, određeni set dijelova podataka zamjenjuje se većim dijelom. I dalje, prethodni dijelovi podataka ostaju na disku određeno vrijeme.
Prvo, oni se čuvaju sve dok postoje select upiti koji ih koriste, kako bi se osigurala neblokirajuća operacija. Select upiti mogu sigurno čitati iz starih dijelova.
Drugo, postoji i vremenski prag - stari dijelovi podataka ostaju na disku osam minuta. Ove osam minuta se može prilagoditi čak i na cijeli dan. To će zauzeti prostor na disku: u zavisnosti od toka podataka, može se dogoditi da se podaci u posljednjem danu ne samo udvostruče, već i povećaju pet puta. Međutim, ako naiđete na ozbiljan problem, možete zaustaviti ClickHouse server i sve riješiti.
Sada se postavlja pitanje kako to štiti od altera. Tu trebamo malo dublje pogledati, jer je u stara izdanja ClickHouse alter radio tako da je jednostavno direktno mijenjao dijelove. Postoji dio podataka s određenim datotekama, i radimo, na primjer, alter drop column. Tada se ovaj stupac fizički uklanja iz svih dijelova.
Međutim, od verzije 20.3, mehanizam altera je potpuno promijenjen, i sada su dijelovi podataka uvijek nepromjenjivi. Oni se uopće ne mijenjaju - alteri sada funkcionišu otprilike kao merge. Umjesto da mijenjamo dio na mjestu, stvaramo novi. U novom dijelu, datoteke koje se nisu promijenile postaju hardlinkovi, a ako smo uklonili neki stupac, jednostavno neće biti prisutan u novom dijelu. Stari dio će po defaultu biti uklonjen nakon osam minuta, a ovde se mogu prilagoditi postavke pomenute ranije.
Isto važi i za altere tipa mutacija. Kada radite alter delete ili alter update, on ne mijenja dio, već stvara novi. A potom uklanja stari.
Što učiniti ako se struktura tablice promijenila?
Kako podići backup koji je napravljen s starom shemom? I drugo pitanje o slučaju sa snapshotovima i sredstvima datotečnog sistema. Da li je ovde Btrfs bolji izbor od ZFS na Linux LVM?
Ako radite attach partition Ako imate particije s drugom strukturom, ClickHouse će vam reći da to nije moguće. Rješenje je sljedeće. Prvo, morate stvoriti privremenu tablicu tipa MergeTree sa starom strukturom, priključiti podatke pomoću attach, zatim izvršiti alter upit. Nakon toga možete ili kopirati ili premjestiti te podatke i opet izvršiti attach, ili koristiti upit. alter table move partition.
Sada je drugo pitanje – možete li koristiti Btrfs. U početku, ako imate LVM, dovoljno je LVM snimanja, a datotečni sustav može biti ext4, to nije važno. Što se tiče Btrfs, sve ovisi o vašem iskustvu u njegovom korištenju. To je zreli datotečni sustav, ali i dalje postoje određene sumnje o tome kako će sve raditi u praksi u konkretnoj situaciji. Ne bih to preporučio ako nemate Btrfs u proizvodnji.
Koje su sada najbolje prakse u resharding podacima?
Pitanje o preplitanju je složeno i višeznačno. Ovde možemo odgovoriti odmah na nekoliko načina. Možemo pristupiti s jedne strane i reći da u ClickHouseu ne postoji ugrađena mogućnost preplitanja. Ali bojim se da taj odgovor neće zadovoljiti nikoga. Stoga možemo pristupiti s druge strane i reći da u ClickHouseu postoji mnogo načina za preplitanje podataka.
Ako se prostor na klasteru završava ili se ne nosi s opterećenjem, dodajete nove poslužitelje. No, ovi poslužitelji su neodređeni po defaultu, nemaju podatke, nemaju opterećenja. Morate premjestiti podatke kako bi se ravnomjerno rasporedili po novom, povećanom klasteru.
Prvi način na koji to možete učiniti je kopirati dio particija na nove poslužitelje pomoću upita. alter table fetch partition. Na primjer, ako ste imali particije po mjesecima, uzmite prvi mjesec 2017. godine i kopirajte na novi poslužitelj, zatim treći mjesec kopirajte na još neki novi poslužitelj. Tako radite dok ne postane više-manje ravnomjerno.
Premještaj se može izvršiti samo za one particije koje se ne mijenjaju prilikom upisivanja. Za svježe particije upisivanje će morati biti isključeno, jer njihov premještaj nije atomaran. Inače ćete dobiti duplicirane ili propuštene podatke. Ipak, ovaj način je praktičan i dovoljno efikasan. Preko mreže se šalju već spremne sažete particije, tj. podaci se ne prekompresiraju i ne rekodiraju.
Ova metoda ima jedan nedostatak, a to zavisi od sheme shardiranja, jeste li se oslanjali na tu shemu shardiranja i koji je vaš ključ shardiranja. U vašem primeru za slučaj sa metrima, ključ shardiranja je heš od putanje. Kada izvršavate SELECT u distribuiranoj tabeli, on ide odmah na sve shardove klastera i preuzima podatke odatle.
To znači da vam zapravo nije važno koji su podaci na kojem shardu. Najvažnije je da su podaci po jednoj putanji smešteni na jednom shardu, a koji je to konkretno, nije od velike važnosti. U ovom slučaju, premestiti gotove particije je savršeno, jer prilikom SELECT zahteva takođe — i pre re-shardiranja i posle, shema podataka nema veliku važnost — dobijate potpune podatke.
Ali ima slučajeva i složenijih. Ako na nivou logike aplikacije planirate posebnu shemu shardiranja, na primer, da je ovaj klijent smešten na određenom shardu, i upit može biti poslat direktno tamo, a ne u distribuiranu tabelu. Ili koristite dovoljno novu verziju ClickHouse-a i uključili ste opciju optimize skip unused shards. U tom slučaju, tokom SELECT zahteva, izraz u sekciji WHERE će biti analiziran, i biće izračunato na koje shardove je potrebno ići prema shemi shardiranja. Ovo funkcioniše pod uslovom da su podaci raspoređeni prema toj shemi shardiranja. Ako ste ih premeštali ručno, usklađenost se može promeniti.
Dakle, ovo je prva metoda. Čekam vaš odgovor, da li vam odgovara ova metoda, ili idemo dalje.
Vladimir Kolobajev, vodeći sistemski administratori u Avitu: Aleksej, način koji ste spomenuli ne odgovara dobro kada treba raspodeliti opterećenje uključujući i čitanje. Možemo uzeti mesečnu particiju i prethodni mesec prebaciti na drugu nodu, ali kada stigne zahtev za tim podacima, opterećićemo samo nju. A želeli bismo da opterećujemo ceo klaster, jer, u suprotnom, će neko vreme sve opterećenje na čitanje obrađivati dva shardova.
Aleksej Milovidov: Odgovor ovdje je čudan — da, loše je, ali možda će proći. Objasnit ću kako. Treba razmotriti scenarij opterećenja koji dolazi uz vaše podatke. Ako su to podaci o nadzoru, onda se gotovo sigurno može reći da ogromna većina zahtjeva dolazi po svježim podacima.
Postavili ste nove servere, premjestili stare particije, ali ste također promijenili način na koji se snimaju svježi podaci. Svježi podaci će biti raspoređeni po cijelom klasteru. Tako će već nakon pet minuta zahtjevi za posljednjih pet minuta ravnomjerno opterećivati klaster, a nakon jednog dana zahtjevi za dan će također ravnomjerno opterećivati klaster. Nažalost, zahtjevi za prethodni mjesec će ići samo na dio servera klastera.
Međutim, često nećete imati zahtjeve za veljaču 2019. godine. Vjerojatno, ako zahtjevi idu u 2019. godinu, to će biti za cijelu 2019. godinu — za veći vremenski interval, a ne za neki mali raspon. Takvi zahtjevi također mogu ravnomjerno opteretiti klaster. No, u cjelini, vaša primjedba je potpuno točna, da je to takvo ad hoc rješenje koje ne raspoređuje podatke potpuno ravnomjerno.
Imam još nekoliko točaka za odgovor na pitanje. Jedna od njih je kako isprva napraviti shemu shardiranja da bi prebacivanje shardova imalo manje bolova. To nije uvijek moguće.
Na primjer, imate podatke o nadzoru. Podaci o nadzoru rastu iz tri razloga. Prvi — akumulacija povijesnih podataka. Drugi — rast prometa. I treći — povećanje broja stvari koje podliježu nadzoru. Pojavljuju se nove mikroservise i metrike koje treba čuvati.
Možda je od njih najveći rast povezan upravo s trećim razlogom — to je povećana upotreba nadzora. U tom slučaju, treba razmotriti prirodu opterećenja, koje su glavne stvari koje se selektiraju. Glavni zahtjevi za selekciju vjerojatno će dolaziti iz nekog podskupa metrika.
Na primjer, korištenje CPU-a na nekim serverima od strane neke usluge. Ispada da postoji određen skup ključeva prema kojima dohvaćate te podatke. I sama upit za tim podacima, najvjerojatnije, dovoljno je jednostavna i izvodi se u desecima milisekundi. Koristi se za usluge praćenja, za nadzorne ploče. Nadam se da sam to točno shvatio.
Vladimir Kolobaev: Stvar je u tome da se vrlo često oslanjamo na povijesne podatke, jer u stvarnom vremenu uspoređujemo trenutačnu situaciju s povijesnom. I za nas je važno imati brz pristup velikim količinama podataka, a ClickHouse s tim odlično upravlja.
Apsolutno ste u pravu, većina upita za čitanje se događa tijekom posljednjeg dana, kao i u svakom sustavu praćenja. No s druge strane, opterećenje na povijesne podatke također je dovoljno veliko. Ono dolazi uglavnom iz sustava alertinga, koji svakih trideset sekundi traži od ClickHouse-a: "Daj mi podatke za posljednjih šest tjedana. A sada mi napravi neki pomični prosjek, i uporedimo trenutačnu vrijednost s povijesnom."
Želio bih reći da za takve vrlo svježe upite imamo još jedan mali tablicu, u kojoj čuvamo samo dva dana podataka, a glavni upiti idu u nju. U veliku shardiranu tablicu šaljemo samo velike povijesne upite.
Aleksej Milovidov: Nažalost, za vaš scenarij to se pokazuje teško primjenjivim, ali ću opisati dva loša i složena sheme shardiranja koja ne treba koristiti, ali se koriste u servisu mojih prijatelja.
Postoji glavni klaster sa događajima "Yandex.Metrika". Događaji su pregledi stranica, klikovi i prijelazi. Većina upita ide konkretnoj web stranici. Otvorite uslugu "Yandex.Metrika", imate web stranicu — avito.ru, ulazite u izvještaj, i dolazi upit prema vašoj web stranici.
No postoje i drugi upiti — analitički i globalni, koje rade interni analitičari. Za svaki slučaj ću naglasiti da unutarnji analitičari rade upite samo prema uslugama "YandeXa". Ipak, usluge "YandeXa" zauzimaju značajan dio svih podataka. To su upiti ne prema konkretnim brojačima, nego prema širem filtriranju.
Kako organizirati podatke tako da sve radi učinkovito po jednom brojilu, a da su istovremeno globalni zahtjevi zadovoljeni? Dodatna kompleksnost dolazi od činjenice da broj zahtjeva u ClickHouse klasteru 'Metričke' iznosi nekoliko tisuća u sekundi. Pri tome, kompleksni zahtjevi, primjerice, nekoliko tisuća u sekundi, jedan ClickHouse server ne može izdržati.
Veličina klastera je nešto više od šest stotina servera. Ako jednostavno postavimo distribuiranu tablicu iznad tog klastera i šaljemo nekoliko tisuća zahtjeva, situacija će biti još gora nego slati ih na jedan server. S druge strane, opcija s ravnomjerno raspoređenim podacima, gdje tražimo informacije sa svih servera, odmah otpada.
Postoji opcija koja je diametralno suprotna. Zamislite da ćemo podatke dijeliti prema stranicama, tako da će zahtjev za jednu stranicu ići na jedan shard. Sada će klaster moći podnijeti deset tisuća zahtjeva u sekundi, ali na jednom shardu neki jedan zahtjev će biti previše spor. On neće biti sposoban za skaliranje po propusnosti. Osobito kada je u pitanju stranica avito.ru. Neću otkriti tajnu ako kažem da je Avito jedna od najposjećenijih stranica u ruskom internetu. Obrada podataka na jednom shardu bila bi apsurdna.
Stoga je shema shardiranja dizajnirana na složeniji način. Cjeli klaster je podijeljen na određeni broj klasteraka koje nazivamo slojevima. Unutar svakog klasterka nalazi se od deset do nekoliko desetaka shardova. A ukupno postoji trideset devet takvih klasteraka.
Kako se sve to skalira? Broj klasteraka ostaje nepromijenjen - kao što je prije nekoliko godina bilo trideset devet, tako je i ostalo. Ali unutar svakog od njih postupno povećavamo broj shardova kako se podaci akumuliraju. I shema shardiranja u cjelini izgleda ovako - razbijanje na te klasterke ide prema web stranicama, a za razumijevanje koja stranica pripada kojem klasteru, koristi se posebna metabaza u MySQL-u. Jedna stranica - jedan klasterak. Unutar njega, shardiranje se odvija prema identifikatorima posjetitelja.
Prilikom zapisa, podijelili smo ih prema ostatku pri dijeljenju identifikatora posjetitelja. No, pri dodavanju novog sharda, shema šardiranja se mijenja; nastavljamo dijeliti, ali prema ostatku pri dijeljenju s drugim brojem. To znači da je jedan posjetitelj već raspoređen na nekoliko servera, i na to se ne možemo oslanjati. Ovo je učinjeno isključivo kako bi se podaci bolje komprimirali. A pri upitima idemo na Distributed tablicu, koja gleda na klaster i obraća se desecima servera. Takva je to glupa shema.
No, moja priča neće biti potpuna ako ne kažem da smo se od ove sheme odrekli. U novoj shemi sve smo promijenili i sve podatke prekopirali pomoću clickhouse-copier.
U novoj shemi svi sajtovi su podijeljeni u dvije kategorije - velike i male. Ne znam kako je odabran prag, ali na kraju se ispostavilo da se veliki sajtovi zapisuju na jedan klaster, gdje je 120 shardova s tri replikacije u svakom - to jest 360 servera. I shema šardiranja je takva da svaki upit ide odmah na sve shardove. Ako sada u "Yandex.Metrica" otvorite bilo koju stranicu izvještaja za avito.ru, upit će ići na 120 servera. Velikih sajtova u ruskom internetu je malo. I upita ispada ne tisuću u sekundi, nego čak manje od stotinu. Sve to mirno obrađuje Distributed tablica, koju svaki od njih obrađuje 120 servera.
A drugi klaster - za male sajtove. Ovdje je shema šardiranja po identifikatoru sajta, i svaki upit ide točno na jedan shard.
U ClickHouse postoji alat clickhouse-copier. Možete li ga objasniti?
Odmah ću reći da je ovo rješenje više glomazno i pomalo manje produktivno. Prednost je u tome što potpuno razmazuje podatke prema shemi koju navedete. Ali nedostatak alata je u tome što ne provodi prešardiranje. Kopira podatke iz jedne sheme klastera u drugu shemu klastera.
To znači da za njegov rad morate imati dva klastera. Mogu biti smješteni na istim serverima, ali, ipak, podaci se neće premještati inkrementalno, nego će biti kopirani.
Na primjer, bilo je četiri servera, a sada ih je osam. Kreirate novu Distributed tablicu na svim serverima, nove lokalne tablice i pokrećete clickhouse-copier, navodeći u njemu shemu rada, da on treba učitati podatke odatle, prihvatiti novu shemu šardiranja i prenijeti podatke na to mjesto. I trebat će vam na starim serverima prostora od jednog i pol puta više nego što sada imate, jer stari podaci moraju ostati na njima, a dodatno će doći polovina tih istih starih podataka. Ako ste unaprijed razmislili o tome da podatke treba prešardirati i imate prostora, onda je ovaj način prikladan.
Kako je unutar clickhouse-copier-a organiziran rad? On dijeli cijeli posao na set zadataka za obradu jedne particije jedne tablice na jednom shardu. Svi ovi zadaci mogu se izvršavati paralelno, a clickhouse-copier se može pokrenuti na različitim mašinama u nekoliko instanci, ali ono što on radi za jednu particiju nije ništa drugo nego insert select. Podaci se čitaju, dekomprimiraju, ponovo razdjeljuju, zatim ponovo komprimiraju, zapisuju negdje i sortiraju. Ovo je složenije rješenje.
Imali ste pilotsku stvar koja se zvala resharding. Što je s tim?
Imali ste još 2017. godine pilot projekt koji se zvao rešarding. Čak postoji opcija u ClickHouse-u. Tako razumijem, to nije zaživjelo. Možete li objasniti zašto je to tako? Izgleda da je to vrlo aktualno.
Cijeli problem je u tome da kada je potrebno prešardirati podatke na mjestu, potrebna je vrlo složena sinkronizacija da bi se to učinilo atomski. Kada smo počeli gledati na to kako je ta sinkronizacija strukturirana, postalo je jasno da postoje temeljni problemi. I ti temeljni problemi nisu samo teorijski, već su odmah počeli pokazivati krucijalne probleme u praksi, što se može objasniti vrlo jednostavno — ništa ne funkcioniše.
Može li se spojiti sve dijelove podataka zajedno prije premještanja na spore diskove?
Pitanje o TTL s opcijom move to slow disk u kontekstu merge-a. Postoji li način, osim putem cron-a, spojiti sve dijelove u jedan prije nego što ih premjestite na spore diskove?
Odgovor na pitanje, može li se automatski spojiti svi dijelovi u jedan prije njihovog premještanja — ne. Mislim da u tome nema potrebe. Nije nužno spojiti sve dijelove u jedan, već se jednostavno oslanjati na to da će se automatski premještati na spore diskove.
Imamo dva kriterija pravila premještanja. Prvi je prema popunjenosti. Ako na trenutnoj razini pohrane ima manje od određenog postotka slobodnog prostora, biramo jedan dio i premještamo ga na sporiju pohranu. Odnosno, ne sporiju, nego sljedeću - kako ste to postavili.
Drugi kriterij je prema veličini. On se odnosi na premještanje velikih dijelova. Možete prilagoditi prag slobodnog prostora na brzom disku, a podaci će se automatski premještati.
Kako migrirati na nove verzije ClickHouse-a ako nema mogućnosti unaprijed provjeriti kompatibilnost?
Ova tema se redovito raspravlja uzimajući u obzir različite verzije, a opet. Koliko je sigurno nadograditi s verzije 19.11 na 19.16 i, primjerice, s 19.16 na 20.3. Kako se najbolje preseliti na nove verzije, ne having mogućnost unaprijed provjeriti kompatibilnost u sandboxu?
Ovdje je nekoliko "zlatnih" pravila. Prvo - . Velik je, ali postoje posebne točke o nekompatibilnim promjenama. Ne treba ih smatrati crvenom zastavom. Obično su to sitne nekompatibilnosti povezane s određenom rubnom funkcionalnošću koja vjerojatno nije korištena.
Drugo - ako nema mogućnosti provjeriti kompatibilnost u sandboxu, a želite odmah nadograditi u produkciji, preporuka je - nemojte to raditi. Prvo stvorite sandbox i provjerite. Ako nema testnog okruženja, vjerojatno ste mala firma, a znači da možete kopirati dio podataka na svoj laptop i tom provjeriti da sve ispravno funkcionira. Možete čak pokrenuti nekoliko replika lokalno na svom računalu. Ili možete negdje u blizini podići novu verziju i prenijeti dio podataka - dakle, stvoriti improvizirano testno okruženje.
Još jedno pravilo - nemojte se nadograđivati tjedan dana nakon izlaska verzije zbog otkrivanja grešaka u produkciji i naknadnih brzih ispravaka. Razmotrimo numeraciju verzija ClickHouse, kako se ne bismo zbunili.
Ima verzija 20.3.4. Broj 20 označava godinu izdavanja — 2020. Što se tiče unutrašnjosti, to nema značaja, tako da se na to nećemo osvrnuti. Dalje — 20.3. Drugu cifru — u ovom slučaju 3 — povećavamo svaki put kada objavljujemo izdanje s nekom novom funkcionalnošću. Ako želimo dodati neku mogućnost u ClickHouse, moramo povećati ovaj broj. Dakle, u verziji 20.4 ClickHouse će raditi još bolje. Treća cifra — 20.3.4. Ovdje 4 predstavlja broj patch-izdanja u kojima nismo dodavali nove mogućnosti, ali smo ispravili neke greške. A 4 znači da smo to učinili četiri puta.
Ne treba misliti da je ovo nešto strašno. Obično korisnik može instalirati najnoviju verziju i ona će raditi bez problema sa uptime-om od godine dana. Ali zamislite da zbog neke funkcije za obradu bitmapa, koju su dodali naši kineski kolege, server padne prilikom proslijeđivanja pogrešnih argumenata. Moramo to ispraviti. Objavit ćemo novu patch-verziju, i ClickHouse će postati stabilniji.
Ako vama ClickHouse radi u produkciji, i izlazi nova verzija ClickHouse sa dodatnim funkcijama — na primjer, 20.4.1 — ne žurite s njenim postavljanjem u produkciju prvog dana. Zašto to uopće treba? Ako još ne koristite ClickHouse, možete ga instalirati, i vjerojatno će sve biti u redu. No, ako ClickHouse već stabilno radi, pratite patch-eve i ažuriranja — koje probleme ispravljamo.
Kirill Shvakov: Želim malo dopuniti o testnim okruženjima. Svi se jako boje testnih okruženja i nekako smatraju da, ako imate jako veliki ClickHouse klaster, testno okruženje mora biti najmanje isto tako veliko ili barem deset puta manje. To uopće nije tako.
Mogu reći na svom primjeru. Imam projekt, i tamo je ClickHouse. Naše testno okruženje baš za njega — to je mala virtuelka u Hetzneru za dvadeset eura, gdje je apsolutno sve razvučeno. Da bismo to radili, imamo potpunu automatizaciju u Ansibleu, i stoga u principu nema razlike gdje pokrenuti — na fizičkim serverima ili jednostavno razvući u virtuelkama.
Što se može učiniti? Bilo bi dobro dodati primjer u dokumentaciju ClickHouse o tome kako postaviti manji klaster – u Dockeru, LXC-u, a možda i izraditi Ansible playbook, jer različiti ljudi imaju različite implementacije. To bi uvelike pojednostavilo stvari. Kada možeš u pet minuta postaviti klaster, puno je lakše razumjeti što se događa. Tako je mnogo praktičnije, jer stavljanje u produkciju verzije koju nisi testirao – vodi u propast. Ponekad to uspije, a ponekad ne. Zato se nije dobro oslanjati na uspjeh.
Maksim Kotiakov, senior backend inženjer u Avitu: Dopunio bih malo o testnim okruženjima iz niza problema velikih kompanija. Imamo potpuno funkcionalan prihvatni klaster ClickHouse, koji je točna kopija podataka i konfiguracija onoga što je u produkciji. Ovaj klaster je postavljen u relativno starim kontejnerima s minimalnim resursima. Pišemo tamo određeni postotak od proizvodnih podataka, srećom imamo mogućnost repliciranja toka u Kafki. Sve je tamo sinkronizirano i skalirano – i prema snagama i prema toku, i, u teoriji, pod istim uvjetima, trebalo bi se ponašati prema metrikama kao produkcija. Sve potencijalno eksplozivno prvo ide na ovaj štand i nekoliko dana se naslanja do spremnosti. No, naravno, ovo rješenje je skupo, teško i sa značajnim troškovima održavanja.
Aleksej Milovidov: Reći ću što predstavlja testno okruženje naših prijatelja iz «Yandex.Metrike». Jedan klaster imao je više od 600 servera, drugi 360, a postoji još treći i nekoliko klastera. Testno okruženje za jedan od njih jednostavno je dva shard-a s po dvije replike u svakom. Zašto dva shard-a? Da ne bude samo jedan. I replike također da postoje. Jednostavno određena minimalna količina koju si možeš priuštiti.
Ovo testno okruženje omogućava provjeru funkcionalnosti upita i zadatka da li je nešto veće puklo. No, često se problemi javljaju tipa posve drugačijeg, kada sve radi, ali postoje neka manja odstupanja s opterećenjem.
Dati ću primjer. Odlučili smo instalirati novu verziju ClickHouse-a. Ona je postavljena na testno okruženje, automatski testovi u samoj «Yandex.Metrike» su obavljeni, koji uspoređuju podatke iz stare i nove verzije, prolazeći cijeli proces. I, naravno, zeleni testovi našeg CI-a. Inače, ne bismo ni predložili ovu verziju.
Sve je odlično. Počinjemo s puštanjem u produkciju. Dobijam poruku da je opterećenje na grafovima poraslo nekoliko puta. Vraćamo verziju. Gledam u graf i vidim: opterećenje se zaista povećalo nekoliko puta tokom puštanja, a zatim se smanjilo kada je verzija puštena. Kasnije smo počeli vraćati verziju. I opterećenje se također povećalo i ponovno smanjilo. Dakle, zaključak je da je opterećenje poraslo zbog puštanja, ništa čudno.
Nakon toga je bilo teško uvjeriti kolege da uistinu instaliraju novu verziju. Kažem: „Sve je u redu, puštajte. Držite palčeve, sve će raditi. Sada je opterećenje poraslo na grafovima, ali sve je okej. Držite se.” U svakom slučaju, tako smo uradili, i svi — verzija je puštena u produkciju. No, gotovo pri svakom puštanju javljaju se slični problemi.
Kill query bi trebao ubijati upite, ali to ne radi. Zašto?
Došao mi je korisnik, neki analitičar, i stvorio neku upitnicu koja je srušila moj ClickHouse klaster. Neku nodu ili cijeli klaster — ovisno o tome u koju je replikaciju ili shard upit otišao. Vidim da su svi resursi po CPU na ovom serveru na maksimumu, sve je crveno. I sam ClickHouse odgovara na upite. Pišem: „Pokaži mi, molim te, popis procesa, koji je upit izazvao ovu ludost.”
Pronalazim taj upit i pišem mu kill. I vidim da se ništa ne događa. Moj server je na maksimumu, ClickHouse dalje daje neke komande, pokazuje da je server živ, i sve je u redu. Ali imam degradaciju u svim korisničkim upitima, počinje degradacija po zapisima u ClickHouse, i moj kill query ne djeluje. Zašto? Mislio sam da kill query treba ubiti upite, a to se ne događa.
Sada će biti prilično čudan odgovor. Radi se o tome da kill query ne ubija upite.
Kill query postavlja malu oznaku pod nazivom „želim da ovaj upit bude ubijen”. A sam upit pri obradi svakog bloka gleda na tu oznaku. Ako je postavljena, upit prestaje raditi. I to bi trebalo raditi u svim slučajevima kada se upit nalazi u stanju obrade blokova podataka. Obradit će sljedeći blok podataka, provjeriti oznaku i stati.
To ne funkcionira u slučajevima kada je zahtjev blokiran za neku operaciju. Međutim, vjerojatno to nije vaš slučaj, jer, prema onome što kažete, koristi mnogo resursa poslužitelja. Moguće je da to ne radi u slučaju vanjske sortiranja i još nekoliko detalja. No, u cjelini to ne bi smjelo biti tako, to je greška. I jedina stvar koju mogu savjetovati je da ažurirate ClickHouse.
Kako izračunati vrijeme odgovora pri čitanoj opterećenosti?
Postoji tablica u kojoj se nalaze agregati po item – razni brojila. Broj redaka je otprilike stotinu milijuna. Može li se računati na predvidivo vrijeme odgovora ako sustav primi 1K RPS za 1K itema?
Sudeći prema kontekstu, ovdje se radi o čitanoj opterećenosti, jer za pisanje nema problema – možete umetati tisuću, sto tisuća, a ponekad i nekoliko milijuna redaka.
Čitajući zahtjevi mogu biti vrlo različiti. U select 1 ClickHouse može izvršiti nekoliko desetaka tisuća zahtjeva u sekundi, pa čak i zahtjevi po jednom ključu zahtijevaju određene resurse. Takvi precizni zahtjevi će biti složeniji nego u nekim key-value bazama podataka, jer je za svako čitanje potrebno pročitati blok podataka prema indeksu. Indeks adresira ne svaki zapis, nego svaki raspon. To znači da će biti potrebno pročitati cijeli raspon – to je 8192 reda po defaultu. I bit će potrebno dekomprimirati komprimirani blok podataka s 64 Kb na 1 Mb. Obično, takvi precizni zahtjevi traju od nekoliko milisekundi. No, ovo je najjednostavnija opcija.
Pogledajmo jednostavnu aritmetiku. Ako pomnožite nekoliko milisekundi s tisućom, dobit ćete nekoliko sekundi. Kao da nije moguće održati tisuću zahtjeva po sekundi, ali zapravo je moguće, jer imamo nekoliko procesorskih jezgri. Dakle, u principu, ClickHouse ponekad može održati 1000 RPS, ali na kratkim zahtjevima, upravo preciznim.
Ako trebate skalirati ClickHouse klaster prema broju jednostavnih zahtjeva, preporučujem najjednostavnije – povećati broj replika i slati zahtjeve na nasumičnu repliku. Ako jedna replika drži petsto zahtjeva u sekundi, što je potpuno realno, tada tri replike mogu držati tisuću pet stotina.
Ponekad, naravno, možete također podesiti ClickHouse na maksimalni broj točnih čitanja. Što je potrebno za to? Prvo - smanjiti granularnost indeksa. Pri tome treba smanjiti ne do jedinice, već na temelju izračuna da će broj zapisa u indeksu biti nekoliko milijuna ili desetaka milijuna na serveru. Ako u tablici ima stotinu milijuna redaka, kao granularnost možete postaviti 64.
Možete smanjiti veličinu komprimiranog bloka. Za to postoje postavke min compress block size, max compress block size. Možete ih smanjiti, prebaciti podatke, i tada će točni upiti biti brži. No, ClickHouse još uvijek nije key-value baza podataka. Velik broj malih upita - to je antipaterna opterećenja.
Kirill Shvakov: Dajem savjet za slučaj da postoje obični e-računi. To je prilično standardna situacija kada se u ClickHouse pohranjuje neki brojčanik. Imam korisnika, on je iz te i te zemlje, još jedno treće polje, i treba nešto inkrementalno povećati. Uzimajte MySQL, napravite jedinstveni ključ - u MySQL je to duplicate key, a u PostgreSQL je to conflict - i dodajte s plusom. To će raditi puno bolje.
Kada imate malo podataka, nema smisla posebno koristiti ClickHouse. Postoje obične baze podataka koje dobro obavljaju tu funkciju.
Što podesiti u ClickHouseu da više podataka bude u cacheu?
Zamislite situaciju - na serverima ima 256 GB RAM-a, u svakodnevnoj rutini ClickHouse uzima otprilike 60-80 GB, u vrhuncu - do 130. Što možete uključiti i podesiti da više podataka bude u cacheu i, prema tome, da bude manje odlazaka na disk?
Kao pravilo, page cache operativnog sistema dobro se nosi s tim zadatkom. Ako jednostavno otvorite resurs, pogledate tako da vidite cached ili free - također piše koliko je zakorišteno - možete primijetiti da je svaka slobodna memorija iskorištena za cache. I ovi podaci pri čitanju će se čitati ne s diska, već iz RAM-a. Pri tome mogu reći da se cache koristi učinkovito, jer se keširaju zapravo komprimirani podaci.
Ipak, ako želite još više ubrzati neke jednostavne upite, postoji mogućnost uključiti unutar ClickHousea cache u nekomprimiranim podacima. Ovo se naziva uncompressed cache. U konfiguracijskoj datoteci config.xml postavite size nekomprimirane cache memorije na željenu vrijednost — preporučujem ne više od polovice slobodne RAM memorije jer će ostatak otići za page cache.
Osim toga, postoje dvije postavke na razini upita. Prva postavka — use uncompressed cache — uključuje njegovu upotrebu. Preporučuje se da se uključi za sve upite, osim za teške koji mogu pročitati sve podatke i isprazniti ovu cache memoriju. A druga postavka — to je nešto poput maksimalnog broja redaka za korištenje cache memorije. Automatski ograničava velike upite tako da prolaze mimo cache-a.
Kako se može podesiti storage_configuration za pohranu u radnoj memoriji?
U novoj dokumentaciji ClickHouse-a pročitao sam odjeljak koji se odnosi . U opisu postoji primjer s brzim SSD-om.
Zanima me kako se može konfigurirati isto s volumenom hot memory. I još jedno pitanje. Kako radi select s takvom organizacijom podataka, hoće li čitati cijeli skup ili samo onaj koji leži na disku, i komprimiraju li se ti podaci u memoriji? I kako funkcionira sekcija prewhere s tom organizacijom podataka?
Ova postavka utječe na pohranu komada podataka, a njihov format se nikako ne mijenja.
Pogledajmo detaljnije.
Može se konfigurirati pohrana podataka u RAM-u. Sve što se konfigurira za disk — to je njegova putanja. Kreirate tmpfs particiju koja je montirana na nekoj putanji u datotečnom sustavu. Tu putanju označavate kao put za pohranu podataka za najtopliju particiju, kamo počinju stizati i pohranjivati se komadi podataka, sve je u redu.
No ne preporučujem to zbog niske pouzdanosti, iako, ako imate minimalno tri replike u različitim data centrima, to je moguće. Ako se nešto dogodi, podaci će biti obnovljeni. Zamislite da se server iznenada isključi i ponovno uključi. Particija se ponovno montira, ali je prazna. ClickHouse server pri pokretanju vidi da mu nedostaju ti komadi, iako, prema metapodacima ZooKeeper-a, oni bi trebali biti tu. Provjerava na kojima replikama postoje, traži ih i preuzima. Na taj način podaci će biti obnovljeni.
U tom smislu pohrana podataka u radnoj memoriji se principijelno ne razlikuje od njihove pohrane na disku, jer prilikom zapisivanja podataka na disk oni prvo ulaze u page cache i fizički se zapisavaju odgođeno. To zavisi od opcije montiranja datotečnog sistema. Ipak, da napomenem, ClickHouse ne koristi fsync prilikom unosa.
Podaci u radnoj memoriji se čuvaju u potpuno istom formatu kao i na disku. Upit select na isti način bira dio podataka koji treba čitati, odabire potrebne raspona podataka u dijelovima i čita ih. Istovremeno, prewhere funkcija radi apsolutno isto, bez obzira na to da li su podaci bili u radnoj memoriji ili na disku.
Do koje je količine jedinstvenih vrijednosti Low Cardinality učinkovit?
Low Cardinality je pametno konstruiran. On sastavlja lokalne rječnike podataka. Prvo, rječnici su jedinstveni za svaki dio, a drugo, čak i unutar jednog dijela, oni mogu biti različiti za svaki raspon. Kada broj jedinstvenih vrijednosti dostigne prag — mislim da je to jedan milion — rječnik se jednostavno odlaže, i kreira se novi.
Odgovor u cjelini: za svaki lokalni raspon — recimo, za svaki dan — negdje do milion jedinstvenih vrijednosti, Low Cardinality je efikasan. Nakon toga nastaje fallback, gdje se koristi mnogo različitih rječnika, umjesto jednog. Radit će otprilike kao obična kolona tipa string, možda malo manje efikasno, ali ozbiljna degradacija performansi neće doći.
Koje su najbolje prakse za full-text pretraživanje u tablici od pet milijardi redaka?
Postoje različiti načini odgovora. Prvi bi bio reći da ClickHouse nije sistem za pretraživanje punog teksta. Za to postoje specijalizovani sistemi, na primjer, i . Ipak, sve češće srećem ljude koji govore da prelaze sa Elasticsearch-a na ClickHouse.
Zašto se ovo dešava? Objašnjavaju to time da Elasticsearch ne može da se nosi sa opterećenjem na određenim količinama podataka, počevši od konstrukcije indeksa. Indeksi postaju previše obimni, i ako se samo prebace podaci u ClickHouse, ispada da se oni čuvaju nekoliko puta efikasnije po volumenu. Pritom, upiti za pretraživanje često nisu bili takvi da treba pronaći neku frazu uzimajući u obzir morfologiju u ukupnom skupu podataka, već su potpuno drugačiji. Na primer, pronaći u logovima za poslednjih nekoliko sati neku podslijednost bajtova.
U tom slučaju, u ClickHouseu kreirate indeks, gdje će prvo polje biti datum s vremenom. Najveće filtriranje podataka će biti upravo prema rasponu datuma. Unutar odabranog raspona datuma, obično se može provesti pretraživanje punim tekstom čak i brute-force metodom uz pomoć klauzule like. Operator like u ClickHouseu je najefikasniji operator like koji možete pronaći. Ako pronađete bolji, javite mi.
No, like je još uvijek full scan. A full scan može biti spor ne samo zbog CPU-a, već i zbog diska. Ako imate jedan terabajt podataka dnevno, i tijekom dana tražite neku riječ, morat ćete skenirati terabajt. A sigurno je na običnim tvrdim diskovima, i na kraju će biti opterećeni tako da se na taj server nećete moći spojiti putem SSH-a.
U tom slučaju spreman sam ponuditi još jedan mali trik. To je iz kategorije eksperimentalnih - možda će uspjeti, a možda i ne. U ClickHouseu postoje indeksi punog teksta u obliku trigramnih Bloom filtara. Naši kolege iz tvrtke Arenadata već su isprobali te indekse, i često funkcioniraju upravo onako kako su namijenjeni.
Kako biste ih ispravno koristili, trebate dobro razumjeti kako oni točno funkcioniraju: što predstavlja trigramni Bloom filtar i kako odabrati njegovu veličinu. Mogu reći da će pomoći za upite o rijetkim frazama, podstringovima koji se rijetko pojavljuju u podacima. U tom slučaju, indeksi će odabrati podraspone, i bit će pročitano manje podataka.
Nedavno su u ClickHouseu uvedene još naprednije funkcije za pretraživanje punog teksta. To su, prije svega, pretraživanja odmah više podstringova u jednom prolazu, uključujući opcije s obzirom na velika i mala slova, bez obzira na velika i mala slova, s podrškom za UTF-8 ili samo za ASCII. Odaberite onu koja vam je najefikasnija.
Uvedeno je također pretraživanje više regularnih izraza u jednom prolazu. Nije potrebno pisati X like jedan podstring or X like drugi podstring. Odmah napišete, i sve se izvršava maksimalno efikasno.
Treće - sada postoji približno pretraživanje regexova i približno pretraživanje podstringova. Ako je netko napisao riječ s greškom, tražit će se prema maksimalnom podudaranju.
Kako bolje organizirati pristup u ClickHouse za veliki broj korisnika?
Objasnite kako najbolje organizirati pristup za veliko broj korisnika i analitičara. Kako formirati red, prioritiatiirati zahtjeve max concurrent queries, i kojim alatima?
Ako je klaster dovoljno velik, dobro rješenje bi bilo podići još dva servera koja će postati ulazna točka za analitičare. Drugim riječima, ne propuštati analitičare na konkretne shardove klastera, već jednostavno stvoriti dva prazna servera, bez podataka, i na njima postaviti prava pristupa. Pri tome, postavke korisnika prilikom distribuiranih zahtjeva se prenose na udaljene servere. Dakle, postavljate sve na ovim dvama serverima i postavke imaju učinak na cijeli klaster.
U principu, ovi serveri su bez podataka, ali količina radne memorije na njima je veoma važna za izvršenje zahtjeva. Disk se također može koristiti za privremene podatke, ako je uključena vanjska agregacija ili vanjsko sortiranje.
Važno je pogledati postavke koje su povezane sa svim mogućim ograničenjima. Ako sada uđem u klaster 'Yandex.Metrike' kao analitičar i postavim zahtjev select count from hits, odmah ću dobiti iznimku da ne mogu izvršiti zahtjev. Maksimalan broj redaka koje mogu skenirati je sto milijardi, a ukupno ih u klasteru ima cinquante trilijuna u jednoj tablici. To je prvo ograničenje.
Pretpostavimo da uklonim ograničenje po broju redaka i ponovo izvršim zahtjev. Tada ću vidjeti sljedeću iznimku - uključena je postavka force index by date. Ne mogu izvršiti zahtjev ako ne navedem opseg datuma. Ne treba se oslanjati na to da će analitičari to ručno odrediti. Tipičan slučaj - opisan je opseg datuma where event date between tjedan. A onda se samo na krivom mjestu stavila zagrada, i umjesto and dobio se or — or URL match. Ako nema ograničenja, početi će skenirati stupac URL i potrošiti jednostavno tonu resursa.
Osim toga, u ClickHouseu postoje dvije postavke prioriteta. Nažalost, one su vrlo primitivne. Jedna se jednostavno zove priority. Ako je priority ≠ 0 i izvršavaju se zahtjevi s nekim prioritetom, ali pritom se izvršava zahtjev s prioritetom koji ima manju vrijednost, što znači viši prioritet, tada se zahtjev s višom prioritetnom vrijednošću, što označava niži prioritet, jednostavno suspendira i neće raditi u tom vremenu.
Ovo je vrlo gruba postavka i nije prikladna za slučajeve kada je na klasteru stalno opterećenje. Ali ako imate kratke, impulsivne zahtjeve koji su važni, a klaster uglavnom miruje, takva će postavka odgovarati.
Sljedeća postavka prioriteta zove se OS thread priority. Ona jednostavno postavlja za sve niti izvršenja zahtjeva vrijednost nice za Linux scheduler. Funkcionira prosječno, ali ipak radi. Ako se postavi minimalna vrijednost nice – ona je najveća po veličini, što znači najniži prioritet – a za zahtjeve s visokim prioritetom postavi -19, tada će CPU trošiti nizkoprioritetne zahtjeve otprilike četiri puta manje nego visoko prioritetne.
Također je potrebno postaviti maksimalno vrijeme izvršenja zahtjeva – recimo, pet minuta. Minimalna brzina izvršenja zahtjeva – to je najvažnije. Ova postavka postoji već dugo i potrebna je ne samo za tvrdnju da ClickHouse ne usporava, već da to forsira.
Zamislite, postavljate: ako neki zahtjev obrađuje manje od milijun redaka u sekundi – to se ne može dozvoliti. To sramoti naše dobro ime, našu dobru bazu podataka. Hajdemo to jednostavno zabraniti. U stvari, postoji dvije postavke. Jedna se zove min execution speed – u redcima u sekundi, a druga se zove timeout before checking min execution speed – prema zadanim postavkama petnaest sekundi. Dakle, petnaest sekundi je u redu, a zatim, ako je sporo, jednostavno baciti iznimku – prekinuti zahtjev.
Također je potrebno postaviti kvote. U ClickHouse postoji ugrađena mogućnost kvota koja broji potrošnju resursa. Ali, nažalost, ne fizičkih resursa poput CPU-a, diskova, već logičkih – broj obrađenih zahtjeva, redaka i pročitanih bajtova. I možete postaviti, na primjer, maksimalno sto zahtjeva tijekom pet minuta i tisuću zahtjeva na sat.
Zašto je to važno? Zato što će dio analitičkih upita biti izvršen ručno iz ClickHouse klijenta. I sve će biti u redu. No, ako u vašoj kompaniji rade napredni analitičari, oni će napisati skriptu, a u skripti može biti greška. I ta greška će dovesti do toga da će se upit izvršavati u beskonačnom ciklusu. Od toga se treba zaštititi.
Može li se dati rezultati jednog upita deset klijentima?
Imamo nekoliko korisnika koji vole dolaziti s vrlo velikim upitima u isto vrijeme. Upit je velik, generalno se izvršava brzo, ali zbog toga što ima puno takvih upita odjednom, postaje vrlo bolno. Može li se isti upit, koji stigne deset puta zaredom, izvršiti samo jednom, a rezultat dati deset korisnicima?
Problem je u tome što nemamo rezultata cachea ili međuspremnika podataka. Postoji page cache operacijskog sustava, koji će omogućiti da se podaci ne čitaju ponovo s diska, ali, nažalost, podaci će se i dalje morati dekompresirati, deserializirati i ponovo obrađivati.
Voljeli bismo to nekako izbjeći, bilo keširanjem međupodataka, ili organiziranjem sličnih upita u neku vrstu queue-a i dodavanjem keša rezultata. Trenutno imamo jedan pull request u razvoju koji dodaje keširanje upita, ali samo za pod-upite u sekciji in i join — dakle, rješenje nije potpuno.
Ipak, također se suočavamo s takvom situacijom. Posebno kanonički primjer su upiti s paginacijom. Ima izvještaj, u njemu ima nekoliko stranica, i ide upit limit 10. Potom isto to, ali limit 10,10. Zatim još sljedeća stranica. I postavlja se pitanje, zašto sve to svaki put računamo? No, sada nema rješenja, i to se ne može izbjeći.
Postoji alternativno rješenje, koje se stavlja uz ClickHouse - .
Kirill Shvakov: U ClickHouse Proxy postoji ugrađeni ograničivač brzine i ugrađeni keš rezultata. Tamo su napravljena mnoga podešavanja, jer se rješavao sličan zadatak. Proxy omogućava ograničavanje upita organiziranjem u queue, i postavljanje vremena trajanja keša upita. Ako su upiti zaista isti, Proxy će ih vraćati mnogo puta, a u ClickHouse će otići samo jednom.
U Nginxu postoji i keširanje u besplatnoj verziji, i to će raditi. Nginx čak ima postavke koje usporavaju druge zahtjeve dok jedan ne završi ako su zahtjevi stigli istovremeno. No, postavka u ClickHouse Proxy je mnogo bolja. Napravljena je posebno za ClickHouse i za ove zahtjeve, pa je stoga prikladnija. I lako se postavlja.
Što učiniti s asinkronim operacijama i materializovanim prikazima?
Postoji problem da su operacije s replaćing motorom asinkrone – prvo se podaci zapisuju, a zatim se događaju njihova kompresija. Ako ispod tablice postoji materializirana tablica s nekim agregatima, duplici će se zapisati u nju. I ako nema neke složene logike, podaci će biti duplicirani. Što se može s tim učiniti?
Postoji očigledno rješenje – implementirati okidač za određenu klasu materializiranih prikaza tijekom asinkrone operacije kompresije. Postoje li neke "srebrne kugle", planovi za implementaciju sličnih funkcionalnosti?
Treba se pozabaviti time kako radi deduplikacija. Ono o čemu ću sada govoriti ne odnosi se na pitanje, ali u svakom slučaju to treba imati na umu.
Kada se umetnu u repliciranu tablicu, postoji deduplikacija cijelih umetnutih blokova. Ako ponovo umetnete isti blok koji sadrži istu količinu istih redaka u istom redoslijedu, podaci se deduplikiraju. Dobit ćete “Ok” kao odgovor na umetanje, ali zapravo će biti zabilježen samo jedan paket podataka, i neće biti dupliciran.
To je potrebno radi jasnoće. Ako ste tijekom umetanja dobili “Ok”, to znači da su vaši podaci umetnuti. Ako ste dobili grešku od ClickHouse-a, to znači da nisu umetnuti i potrebno je ponoviti umetanje. No, ako se tijekom umetanja veza prekinula, ne znate jesu li podaci umetnuti ili ne. Jedina opcija je ponoviti umetanje. Ako su podaci zapravo bili umetnuti, a vi ih ponovo umetnete, postoji deduplikacija blokova. Ona je potrebna kako bi se izbjegli duplikati.
I važno je kako ona djeluje za materializirane prikaze. Ako su podaci bili deduplikovani prilikom umetanja u glavnu tablicu, tada u materializirani prikaz također neće otići.
Sada o pitanju. Imate složeniju situaciju jer bilježite duplikate pojedinih redova. To znači da nije cijela serija duplicirana, već konkretni redovi, koji se u pozadini smanjuju. Uistinu, podaci će se smanjiti u glavnoj tablici, a u materijalizirano predstavljanje će ići nesmanjeni, i tijekom spajanja neće se ništa dogoditi s materijaliziranim prikazima. Jer materijalizirani prikaz nije ništa drugo nego okidač za insert. Tijekom drugih operacija s njim se ne događa ništa dodatno.
Nažalost, ovdje vas ne mogu obradovati. Treba samo pronaći konkretno rješenje za ovaj slučaj. Na primjer, može li se u materijaliziranom prikazu također napraviti njegov zamjenski unos, i način deduplifikacije možda će raditi na sličan način. No, nažalost, ne uvijek. Ako je agregatni, onda to neće funkcionirati.
Kirill Shvakov: I mi smo, također, imali svojevrsno kostylestvo u to vrijeme. Postojao je problem jer imamo prikaze oglasa, i postoje određeni podaci koje možemo prikazivati u stvarnom vremenu — to su samo prikazi. Rijetko se dupliciraju, ali ako se to dogodi, ponovno ćemo ih smanjiti. I postojale su stvari koje nije bilo moguće duplicirati — klikovi i cijela ta priča. No, također smo ih željeli pokazati gotovo odmah.
Kako su napravljena materijalizirana predstavljanje? Postojala su predstavljanje, gdje se zapisuje izravno — ide upis u sirove podatke, i zapisuje se u prikaze. Tamo u određenom trenutku podaci nisu bili sasvim ispravni, dupliciraju se i tako dalje. A postoji druga polovica tablice, gdje izgledaju apsolutno isto kao materijalizirani prikazi, to jest, po strukturi su apsolutno identični. Jednom u određeno vrijeme ponovno izračunavamo podatke, doradimo podatke bez duplikata, pišemo u te tablice.
Kretali smo se putem API-ja — ručno to u ClickHouse-u neće funkcionirati. API gleda: kada imam datum posljednjeg dodavanja u tablicu, gdje su već zajamčeni ispravni, izračunati podaci, i on izvršava upit prema jednoj tablici i drugoj tablici. Iz jedne tablice odabire do određenog vremenskog razdoblja, a iz druge preuzima ono što još nije izračunato. I to radi, ali ne sredstvima jednog ClickHouse-a.
Ako imate neki API - za analitičare, za korisnike - onda u principu, to je opcija. Uvijek dodajete, uvijek izračunavate. To možete raditi jednom dnevno ili u neko drugo vrijeme. Sami birate raspon koji vam nije potreban i nije kritičan.
ClickHouse ima mnogo logova. Kako mogu vidjeti sve što se događa sa serverom u trenutku?
U ClickHouse-u postoji vrlo veliki broj različitih logova, a taj broj se povećava. U novim verzijama neki od njih su čak po defaultu uključeni, dok ih u starim verzijama treba uključivati prilikom ažuriranja. Ipak, njih je sve više i više. Želio bih na kraju vidjeti što se sada događa kod mene sa serverom, možda na nekom sažetom dashboardu.
Nemate li u svom timu ClickHouse, ili u timovima vaših prijatelja, koji podržavaju neki funkcionalnost gotovih dashboarda koji bi ove logove prikazivali u obliku već gotovog proizvoda? Na kraju, gledati logove u ClickHouse-u - to je super. Ali bilo bi stvarno odlično da to već bude pripremljeno u obliku dashboarda. Bio bih od toga oduševljen.
Dashboardi postoje, istina je da nisu standardizirani. U našoj kompaniji otprilike 60 timova koristi ClickHouse, i najčudnije je da mnogi od njih imaju dashboarde koje su sami napravili i koji su nešto drugačiji. Neki timovi koriste internu instalaciju „Yandex. Oblaka“. Tamo postoje neki gotovi izvještaji, iako ne svi potrebni. Drugi imaju svoje.
Moji kolege iz „Metrike“ imaju svoj dashboard u Grafana, a ja imam svoj po njihovom klasteru. Tamo gledam stvari poput cache hit za cache evidencija. Čak je i još složenije to što koristimo različite alate. Svoj dashboard sam pravio na vrlo starom alatu koji se zove Graphite-web. On je potpuno ružan. I tako ga koristim do danas, iako bi Grafana vjerojatno bila zgodnija i ljepša.
Osnovna stvar u nadzornim pločama je ista. To su sistemske metrike po klasteru: CPU, memorija, disk, mreža. Drugi su - broj simultanih upita, broj simultanih spajanja, broj upita u sekundi, maksimalni broj delova za particije tabela MergeTree, kašnjenje replikacije, veličina reda replikacije, broj umetnutih redova u sekundi, broj umetnutih blokova u sekundi. To je sve što dolazi ne iz logova, već iz metrika.
Vladimir Kolobaev: Aleksandre, želeo bih malo da korigujem. Postoji Grafana. Grafana ima izvor podataka, koji je ClickHouse. Dakle, mogu iz Grafane direktno slati upite u ClickHouse. U ClickHouse-u postoji tabela sa logovima, koja je svima ista. Želim da u rezultatima u Grafani upućujem na tu tabelu logova i vidim one upite koje šalje moj server. Bilo bi sjajno imati takvu nadzornu ploču.
Sam sam je napravio. Ali postavlja mi se pitanje - ako je sve standardizovano, i Grafanu koriste svi, zašto u "Yandexu" nema takve zvanične nadzorne ploče?
Kirill Shvakov: U stvari, izvor podataka koji ide ka ClickHouse-u sada podržava Altinity. I samo želim dati smernicu gde kopati i koga nagovarati. Može se pitati njih, jer "Yandex" zapravo pravi ClickHouse, a ne priče oko njega. Altinity je glavna kompanija koja trenutno promoviše ClickHouse. Oni ga neće napustiti, već će ga podržavati. Jer u principu, da biste postavili nadzornu ploču na Grafana sajt, potrebno je samo registrovati se i postaviti je - nema posebnih problema.
Aleksej Milovidov: U poslednjih godinu dana u ClickHouse-u je dodatno mnogo mogućnosti za profilisanje upita. Postoje metrike za svaki upit prema korišćenju resursa. A nedavno je dodat još niži profajler upita, kako bi se videlo gde upit troši svaku milisekundu. Ali kako bih iskoristio ovu funkcionalnost, moram otvoriti konzolnog klijenta i upisati upit koji neprestano zaboravljam. Negde sam ga sačuvao i neprestano zaboravljam gde tačno.
Želio bih da postoji alat koji jednostavno prikazuje — ovo su vaši teški upiti, grupirani prema klasama upita. Kada kliknem na neki, rekli bi mi da je on težak iz tog razloga. Trenutno takvo rješenje ne postoji. I stvarno je prilično čudno da kada me ljudi pitaju: „Recite, postoje li neki gotovi dashboardi za Grafanu?”, kažem: „Idite na stranicu Grafane, tamo je zajednica 'Dashboardi', tu postoji dashboard od Dimka, postoji dashboard od Kostyana. Što je to, ne znam, nisam ga sam koristio.”
Kako utjecati na mergeove kako server ne bi pao u OOM?
Imam tablicu u kojoj postoji samo jedna particija, ona je ReplacingMergeTree. U nju zapisujem podatke tijekom četiri godine. Trebao sam napraviti alter i obrisati neke podatke.
To sam učinio, i tijekom obrade tog upita potrošena je sva memorija na svim serverima klastera, a svi serveri klastera su zajednički otišli u OOM. Nakon toga su se svi zajedno ponovno pokrenuli, počeli izvoditi merge iste te operacije, tog bloka podataka, i ponovno su pali u OOM. Onda su se ponovo pokrenuli i ponovo pali. I ta stvar se nije zaustavljala.
Kasnije se ispostavilo da je to zapravo bug koji su dečki ispravili. To je super, hvala puno. Ali dojam je ostao. I sada, kada razmišljam o tome da trebam izvesti neki merge u tablici, postavljam pitanje — zašto ne mogu na neki način utjecati na te merge? Na primjer, ograničiti ih prema količini potrebne operativne memorije, ili u principu po njihovom broju koji će obraditi konkretno ova tablica.
Imam tablicu koja se zove 'Metričke', obradi mi je, molim te, s dva toka. Ne trebaš stvarati deset ili pet mergeova paralelno, radi to s dva. Mislim da će mi s dva biti dovoljno memorije, dok možda neće biti dovoljno za deset. Zašto strah ostaje? Zato što tablica raste, i jednog dana ću se suočiti s situacijom da će zbog velikog broja podataka možda jednostavno ponestati memorije na serveru. I tada će server pasti u OOM prilikom mergea. Pri tome mutaciju mogu poništiti, ali mergeove ne mogu.
Znate, kada se obavljaju mergeovi, server neće doći u OOM jer se pri mergeu koristi količina RAM-a samo za jedan mali opseg podataka. Tako da će sve biti u redu, bez obzira na količinu podataka.
Vladimir Kolobaev: Dobro. Ima jedan detalj, nakon što smo izvršili ispravku greške, preuzeo sam novu verziju i na drugoj, manjoj tablici, gdje ima mnogo particija, izvršio sličnu operaciju. Tijekom mergea na serveru je potrošeno otprilike 100 GB RAM-a. Imao sam 150 zauzeto, 100 je uzelo, a ostalo je bilo 50 GB, tako da nisam pao u OOM.
Što me trenutno štiti od pada u OOM, ako doista troši 100 GB RAM-a? Što učiniti u situaciji ako iznenada RAM pri mergeovima ponestane?
Aleksej Milovidov: Postoji problem da potrošnja RAM-a tijekom mergeova nije ograničena. Drugi problem je što, ako je neki merge bio zakazan, treba ga izvršiti jer je zabilježen u replikacijskom logu. Replikacijski log su oni postupci potrebni da se replikacija dovede u konzistentno stanje. Ako ne napravite ručne manipulacije koje će ovaj replikacijski log vratiti unatrag, merge će se morati izvršiti.
Naravno, bilo bi korisno imati ograničenje za RAM koje "za svaki slučaj" štiti od OOM. To neće pomoći da se merge izvrši, on će se ponovno pokrenuti, doći do nekog praga, izbaciti iznimku, a zatim se ponovno pokrenuti — ništa dobro iz toga neće proizaći. Ali u načelu, uvođenje tog ograničenja bi bilo korisno.
Kako će se odvijati razvoj Golang drajvera za ClickHouse?
Golang drajver koji je napisao Kirill Shvakov sada službeno podržava tim ClickHousea. On , sada je velik i stvaran.
Mala napomena. Postoji divno i svima omiljeno skladište normalnih formi beskonačnog reda – to je Vertica. Oni imaju i svoj službeni python drajver koji podržavaju programeri Vertice. Nekoliko puta se desilo da su se verzije skladišta i verzije drajvera značajno razdvojile, a drajver je u nekom trenutku prestao raditi. A druga stvar. Podrška ovom službenom drajveru, čini mi se, vodi se prema sistemu „nippl” – pišeš im issue, i on vječno visi.
Imam dva pitanja. Trenutno je Golang drajver Kirila – skoro podrazumijevani način komunikacije iz Golanga sa ClickHouse-om. Osim toga, neko još uvijek komunicira putem http interfejsa, jer mu se tako više sviđa. Kako će se odvijati razvoj ovog drajvera? Hoće li se sinhronizirati sa nekim breaking changes u samom skladištu? I koji je redoslijed razmatranja issue-a?
Kirill Shvakov: Prvo – kako je sve uređeno birokratski. Ova tema nije raspravljana, pa nemam odgovora.
Da bih odgovorio na pitanje o issue-u, potrebna je mala priča o drajveru. Radio sam u kompaniji koja je imala mnogo podataka. To je bila reklamna platforma s ogromnim brojem događaja koje je trebalo negdje skladištiti. U nekom trenutku se pojavio ClickHouse. Ubacili smo podatke unutra, i u prvih par mjeseci sve je bilo dobro, a onda je ClickHouse pao. Tada smo odlučili da nam to nije potrebno.
Nakon godine dana, vratili smo se ideji korištenja ClickHouse-a, i trebali smo nekako pisati podatke tamo. Uvodna situacija bila je takva – hardver je bio vrlo slab, resursa malo. Ali uvijek smo tako radili, pa smo se okrenuli ka nativnom protokolu.
Budući da smo radili na Go-u, bilo je jasno da nam je potreban drajver na Go-u. Radio sam na njemu gotovo punu radnu sedmicu – to je bio moj radni zadatak. Do nekog trenutka smo ga doveli do kraja, i u suštini niko nije pretpostavljao da će ga iko osim nas koristiti. Tada je došao CloudFlare sa istim problemom, i neko vrijeme smo radili s njima vrlo usklađeno, jer su imali iste zadatke. I to smo radili i u ClickHouse-u samom i u drajveru.
U jednom trenutku jednostavno sam prestao s tim jer se moja aktivnost u vezi s ClickHouseom i moj posao malo promijenili. Zato se problemi ne rješavaju. Povremeno drugi ljudi upisuju u repozitorij kada im nešto zatreba. Tada pogledam pull request i ponekad čak nešto i sam ispravim, ali to se događa rijetko.
Želim se vratiti vozaču. Prije nekoliko godina, kada je sve ovo počelo, ClickHouse je bio drugačiji i imao je druge mogućnosti. Sada imamo razumijevanje kako prepraviti vozač da bude dobar. Ako to prođe, verzija 2 će u svakom slučaju biti nekompatibilna zbog nakupljenih improvizacija.
Ne znam kako organizirati ovaj posao. Ni sam nemam previše vremena. Ako neki ljudi budu nadograđivali vozač, mogu im pomoći i objasniti što treba raditi. No aktivno sudjelovanje 'Yandexa' u razvoju projekta za sada se nije razgovaralo.
Aleksej Milovidov: Zapravo, nema nikakve birokracije u vezi s tim vozačima. Jedina stvar je da su oni preneseni u službenu organizaciju, što znači da je taj vozač proglašen službenim rješenjem prema zadanim postavkama za Go. Ima i drugih vozača, ali oni idu odvojeno.
Unutar nas nema nikakvog razvoja za te vozače. Pitanje je možemo li zaposliti posebnu osobu, ne za konkretno ovaj vozač, već za razvoj svih vozača iz zajednice, ili možemo pronaći nekoga izvana.
Vanjski rječnik se ne učitava nakon ponovnog pokretanja s uključenim postavkama lazy_load. Što učiniti?
Imamo uključenu postavku lazy_load, i nakon ponovnog pokretanja servera rječnik se automatski ne učitava. Učitava se samo kada korisnik pristupi tom rječniku. A pri prvom pristupu javlja grešku. Može li se nekako automatski putem ClickHousea učitavati rječnike, ili treba uvijek sami kontrolirati njihovu spremnost kako korisnici ne bi dobijali greške?
Možda imamo staru verziju ClickHousea, zato se rječnik automatski nije učitao. Može li to biti?
Prvo, rječnike se može prisilno učitati putem upita system reload dictionaries. Drugo, što se tiče greške — ako je rječnik već učitan, upiti će raditi na podacima koji su učitani. Ako rječnik još nije bio učitan, on će se učitati u trenutku upita.
Za teške rječnike to nije jako praktično. Na primjer, treba privući milijun redaka iz MySQL-a. Netko radi jednostavan select, ali taj select čekat će onih milijun redaka. Ovdje postoje dva rješenja. Prvo je isključiti lazy_load. Drugo je, kada se server pokrene, prije nego što ga opteretite, izvršiti system reload dictionary ili jednostavno izvršiti upit koji koristi rječnik. Tada će rječnik biti učitan. Morate sami kontrolirati dostupnost rječnika sa uključenim podešavanjem lazy_load, jer ga ClickHouse automatski ne povlači.
Na posljednje pitanje odgovor je – ili je verzija stara, ili se treba debagirati.
Kako postupiti kada sistem reload dictionaries ne učita nijedan od mnogih rječnika, ako barem jedan od njih padne s greškom?
Postoji još pitanje u vezi sa system reload dictionaries. Imamo dva rječnika – jedan se ne učitava, a drugi se učitava. System reload dictionaries u tom slučaju ne učitava nijedan rječnik, i mora se posebno učitati konkretan po njegovu nazivu pomoću system reload dictionary. Je li to također povezano s verzijom ClickHouse-a?
Želim vas obradovati. Ovo ponašanje se promijenilo. Znači, ako ažurirate ClickHouse, to će se također promijeniti. Ako vam trenutno ponašanje ne odgovara system reload dictionaries, ažurirajte se i nadamo se da će se promijeniti na bolje.
Postoji li način za konfiguriranje osobina u konfiguraciji ClickHouse, a da ih ne otkrivamo prilikom grešaka?
Sljedeće pitanje je o greškama vezanim za rječnik, a to su točno podaci. Učinili smo da podaci za povezivanje budu u konfiguraciji ClickHouse-a za rječnik, a kada dođe do greške, dobivamo te podatke i lozinku u odgovoru.
Ovu grešku smo riješili premještanjem podataka u konfiguraciju ODBC drajvera. Da li postoji neki način da se podaci konfiguriraju u konfiguraciji ClickHouse-a, ali da ne budu vidljivi prilikom grešaka?
Ovdje je rješenje doista – navesti te credentials u odbc.ini, a u samom ClickHouse-u navesti samo ODBC Data Source Name. Za ostale izvore rječnika to neće biti moguće – ni za rječnik s MySQL-om, ni za ostale ne biste trebali vidjeti lozinku prilikom poruke o grešci. Također ću provjeriti za ODBC – ako to postoji, jednostavno ću to ukloniti.
Bonus: pozadine za Zoom sa okupljanja
Klikom na sliku za najupornije čitatelje otvorit će se bonus pozadine s druženja. Gasimo požar zajedno s maskotama tehnologija Avita, konzultiramo se s kolegama iz sobe sistem administracije ili staromodnog računalnog kluba i održavamo dnevni sastanak ispod mosta uz grafite.
Izvor: habr.com
