Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Ég legg til að þú lesir afrit af skýrslu seint 2019 eftir Alexander Valyalkin „Go optimizations in VictoriaMetrics“

VictoriaMetrics — hraðvirkt og skalanlegt DBMS til að geyma og vinna úr gögnum í formi tímaraðar (skráin myndar tíma og gildismengi sem samsvara þessum tíma, td fengin með reglubundinni könnun á stöðu skynjara eða söfnun á mæligildi).

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hér er hlekkur á myndbandið af þessari skýrslu - https://youtu.be/MZ5P21j_HLE

Glærur

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Segðu okkur frá sjálfum þér. Ég er Alexander Valyalkin. Hérna GitHub reikninginn minn. Ég hef brennandi áhuga á Go og hagræðingu afkasta. Ég skrifaði mikið af gagnlegum og ekki svo gagnlegum bókasöfnum. Þeir byrja á hvoru tveggja fast, eða með quick forskeyti.

Ég er núna að vinna að VictoriaMetrics. Hvað er það og hvað er ég að gera þarna? Ég mun fjalla um þetta í þessari kynningu.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Tildrög skýrslunnar eru eftirfarandi:

  • Fyrst mun ég segja þér hvað VictoriaMetrics er.
  • Þá skal ég segja þér hvaða tímaraðir eru.
  • Þá skal ég segja þér hvernig tímaraðargagnagrunnur virkar.
  • Næst mun ég segja þér frá gagnagrunnsarkitektúrnum: hvað hann samanstendur af.
  • Og þá skulum við halda áfram að hagræðingunum sem VictoriaMetrics hefur. Þetta er hagræðing fyrir öfuga vísitöluna og hagræðingu fyrir útfærslu bitasettsins í Go.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Veit einhver í áhorfendum hvað VictoriaMetrics er? Vá, margir vita nú þegar. Það eru góðar fréttir. Fyrir þá sem ekki vita þá er þetta tímaraðagagnagrunnur. Það er byggt á ClickHouse arkitektúrnum, á nokkrum smáatriðum um ClickHouse útfærsluna. Til dæmis, á eins og: MergeTree, samhliða útreikninga á öllum tiltækum örgjörvakjarna og hagræðingu afkasta með því að vinna á gagnakubba sem eru settir í skyndiminni örgjörva.

VictoriaMetrics veitir betri gagnaþjöppun en aðrir tímaraðir gagnagrunnar.

Það skalast lóðrétt - það er að segja að þú getur bætt við fleiri örgjörvum, meira vinnsluminni á einni tölvu. VictoriaMetrics mun nýta þessar tiltæku auðlindir með góðum árangri og mun bæta línulega framleiðni.

VictoriaMetrics mælir einnig lárétt - það er að segja, þú getur bætt viðbótarhnútum við VictoriaMetrics klasann og afköst hans munu aukast nánast línulega.

Eins og þú giskaðir á, er VictoriaMetrics fljótur gagnagrunnur, vegna þess að ég get ekki skrifað aðra. Og það er skrifað í Go, svo ég er að tala um það á þessum fundi.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hver veit hvað tímaröð er? Hann þekkir líka fullt af fólki. Tímaröð er röð af pörum (timestamp, значение), þar sem þessum pörum er raðað eftir tíma. Gildið er flottala – flot64.

Hver tímaröð er auðkennd með lykli. Í hverju samanstendur þessi lykill? Það samanstendur af ótómu setti af lykilgildapörum.

Hér er dæmi um tímaröð. Lykillinn að þessari röð er listi yfir pör: __name__="cpu_usage" er nafn mæligildisins, instance="my-server" - þetta er tölvan sem þessum mælikvarða er safnað á, datacenter="us-east" - þetta er gagnaverið þar sem þessi tölva er staðsett.

Við enduðum með tímaraðarheiti sem samanstendur af þremur lykilgildapörum. Þessi lykill samsvarar lista yfir pör (timestamp, value). t1, t3, t3, ..., tN - þetta eru tímastimplar, 10, 20, 12, ..., 15 — samsvarandi gildi. Þetta er örgjörvanotkun á tilteknum tíma fyrir tiltekna röð.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hvar er hægt að nota tímaraðir? Hefur einhver hugmynd?

  • Í DevOps geturðu mælt CPU, vinnsluminni, netkerfi, rps, fjölda villna osfrv.
  • IoT - við getum mælt hitastig, þrýsting, geohnit og eitthvað fleira.
  • Einnig fjármál - við getum fylgst með verðum fyrir alls kyns hlutabréf og gjaldmiðla.
  • Auk þess er hægt að nota tímaraðir við eftirlit með framleiðsluferlum í verksmiðjum. Við höfum notendur sem nota VictoriaMetrics til að fylgjast með vindmyllum, fyrir vélmenni.
  • Tímaraðir eru einnig gagnlegar til að safna upplýsingum frá skynjurum ýmissa tækja. Til dæmis fyrir vél; til að mæla loftþrýsting í dekkjum; til að mæla hraða, fjarlægð; til að mæla bensínnotkun o.fl.
  • Einnig er hægt að nota tímaraðir til að fylgjast með flugvélum. Hver flugvél er með svartan kassa sem safnar tímaröðum fyrir ýmsar breytur um heilsu flugvélarinnar. Tímaraðir eru einnig notaðar í geimferðaiðnaðinum.
  • Heilsugæsla er blóðþrýstingur, púls osfrv.

Það gætu verið fleiri forrit sem ég gleymdi, en ég vona að þú skiljir að tímaraðir eru virkir notaðar í nútímanum. Og magn notkunar þeirra eykst á hverju ári.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Af hverju þarftu tímaraðagagnagrunn? Af hverju geturðu ekki notað venjulegan venslagagnagrunn til að geyma tímaraðir?

Vegna þess að tímaraðir innihalda yfirleitt mikið magn upplýsinga, sem erfitt er að geyma og vinna úr í hefðbundnum gagnagrunnum. Því komu fram sérhæfðir gagnagrunnar fyrir tímaraðir. Þessar bækistöðvar geyma í raun punkta (timestamp, value) með tilgreindum lykli. Þeir bjóða upp á API til að lesa geymd gögn eftir lykli, eftir einu lykilgildi pari, eða eftir mörgum lykilgildapörum, eða með regexp. Til dæmis, þú vilt finna CPU álag allrar þjónustu þinnar í gagnaveri í Ameríku, þá þarftu að nota þessa gervifyrirspurn.

Tímaraðir gagnagrunnar bjóða venjulega upp á sérhæfð fyrirspurnamál vegna þess að SQL tímaraðir henta ekki mjög vel. Þó að það séu til gagnagrunnar sem styðja SQL, þá er það ekki mjög hentugur. Fyrirspurnartungumál eins og PromQL, InfluxQL, Flux, Q. Ég vona að einhver hafi heyrt að minnsta kosti eitt af þessum tungumálum. Margir hafa líklega heyrt um PromQL. Þetta er Prometheus fyrirspurnarmálið.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Svona lítur nútíma gagnagrunnsarkitektúr út með VictoriaMetrics sem dæmi.

Það samanstendur af tveimur hlutum. Þetta er geymsla fyrir öfuga vísitöluna og geymsla fyrir gildi tímaraða. Þessar geymslur eru aðskildar.

Þegar ný skrá kemur í gagnagrunninn förum við fyrst í öfuga vísitöluna til að finna tímaraðarauðkenni fyrir tiltekið mengi label=value fyrir tiltekið mæligildi. Við finnum þetta auðkenni og vistum gildið í gagnageymslunni.

Þegar beiðni kemur um að sækja gögn úr TSDB förum við fyrst í öfuga vísitöluna. Við skulum fá allt timeseries_ids met sem passa við þetta sett label=value. Og þá fáum við öll nauðsynleg gögn frá gagnageymslunni, verðtryggð af timeseries_ids.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við skulum skoða dæmi um hvernig gagnagrunnur tímaraðar vinnur úr valfyrirspurn sem berast.

  • Fyrst af öllu fær hún allt timeseries_ids frá öfugum vísitölu sem inniheldur tiltekin pör label=value, eða fullnægja tiltekinni reglulegri tjáningu.
  • Síðan sækir það alla gagnapunkta úr gagnageymslunni á tilteknu tímabili fyrir þá sem fundust timeseries_ids.
  • Eftir þetta framkvæmir gagnagrunnurinn nokkra útreikninga á þessum gagnapunktum, samkvæmt beiðni notanda. Og eftir það skilar það svarinu.

Í þessari kynningu mun ég segja þér frá fyrri hlutanum. Þetta er leit timeseries_ids með öfugum vísitölu. Hægt er að horfa á seinni hlutann og þriðja hlutann síðar Heimildir VictoriaMetrics, eða bíddu þar til ég útbý aðrar skýrslur :)

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við skulum halda áfram að öfugum vísitölunni. Margir kunna að halda að þetta sé einfalt. Hver veit hvað öfug vísitala er og hvernig hún virkar? Ó, ekki svo margir lengur. Við skulum reyna að skilja hvað það er.

Það er í rauninni einfalt. Þetta er einfaldlega orðabók sem kortleggur lykil að gildi. Hvað er lykill? Þetta par label=valuehvar label и value - þetta eru línur. Og gildin eru sett timeseries_ids, sem inniheldur tiltekið par label=value.

Inverted index gerir þér kleift að finna allt fljótt timeseries_ids, sem hafa gefið label=value.

Það gerir þér einnig kleift að finna fljótt timeseries_ids tímaröð fyrir nokkur pör label=value, eða fyrir pör label=regexp. Hvernig gerist þetta? Með því að finna gatnamót mengisins timeseries_ids fyrir hvert par label=value.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við skulum skoða ýmsar útfærslur á öfugum vísitölu. Við skulum byrja á einföldustu barnalegu útfærslunni. Hún lítur svona út.

Virka getMetricIDs fær lista yfir strengi. Hver lína inniheldur label=value. Þessi aðgerð skilar lista metricIDs.

Hvernig það virkar? Hér höfum við alþjóðlega breytu sem kallast invertedIndex. Þetta er venjuleg orðabók (map), sem mun kortleggja strenginn að sneiðum ints. Línan inniheldur label=value.

Virkni framkvæmd: fá metricIDs fyrir það fyrsta label=value, þá förum við í gegnum allt annað label=value, við skiljum það metricIDs fyrir þau. Og hringdu í aðgerðina intersectInts, sem fjallað verður um hér á eftir. Og þessi aðgerð skilar skurðpunkti þessara lista.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Eins og þú sérð er ekki mjög flókið að útfæra öfuga vísitölu. En þetta er barnaleg útfærsla. Hvaða ókosti hefur það? Helsti ókosturinn við barnalegu útfærsluna er að slík öfug vísitala er geymd í vinnsluminni. Eftir að hafa endurræst forritið týnum við þessari vísitölu. Það er engin vistun á þessari vísitölu á disk. Ólíklegt er að slík öfug vísitala henti gagnagrunni.

Annar gallinn er einnig tengdur minni. Hvolfi vísitalan verður að passa inn í vinnsluminni. Ef það fer yfir stærð vinnsluminni, þá munum við augljóslega fá - út af minnisvillu. Og forritið virkar ekki.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Þetta vandamál er hægt að leysa með tilbúnum lausnum eins og LevelDBEða RocksDB.

Í stuttu máli þurfum við gagnagrunn sem gerir okkur kleift að gera þrjár aðgerðir hratt.

  • Fyrsta aðgerðin er upptaka ключ-значение í þennan gagnagrunn. Hún gerir þetta mjög fljótt, hvar ключ-значение eru handahófskenndir strengir.
  • Önnur aðgerðin er fljótleg leit að gildi með tilteknum lykli.
  • Og þriðja aðgerðin er fljótleg leit að öllum gildum með tilteknu forskeyti.

LevelDB og RocksDB - þessir gagnagrunnar voru þróaðir af Google og Facebook. Fyrst kom LevelDB. Svo tóku strákarnir frá Facebook LevelDB og byrjuðu að bæta það, þeir gerðu RocksDB. Nú virka næstum allir innri gagnagrunnar á RocksDB inni á Facebook, þar á meðal þeir sem hafa verið fluttir yfir á RocksDB og MySQL. Þeir nefndu hann MyRocks.

Hægt er að útfæra öfuga vísitölu með því að nota LevelDB. Hvernig á að gera það? Við vistum sem lykil label=value. Og gildið er auðkenni tímaröðarinnar þar sem parið er til staðar label=value.

Ef við höfum margar tímaraðir með tilteknu pari label=value, þá verða margar raðir í þessum gagnagrunni með sama lykli og mismunandi timeseries_ids. Til að sækja lista yfir allt timeseries_ids, sem byrja á þessu label=prefix, gerum við sviðsskönnun sem þessi gagnagrunnur er fínstilltur fyrir. Það er, við veljum allar línur sem byrja á label=prefix og fá það sem þarf timeseries_ids.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hér er sýnishorn útfærslu á því hvernig það myndi líta út í Go. Við erum með öfuga vísitölu. Þetta er LevelDB.

Virknin er sú sama og fyrir barnalegu útfærsluna. Það endurtekur barnalegu útfærsluna nánast línu fyrir línu. Eina málið er að í stað þess að snúa sér að map við fáum aðgang að inverted index. Við fáum öll gildin fyrir það fyrsta label=value. Síðan förum við í gegnum öll pörin sem eftir eru label=value og fáðu samsvarandi sett af metricIDs fyrir þau. Þá finnum við gatnamótin.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Allt virðist vera í lagi, en það eru gallar við þessa lausn. VictoriaMetrics innleiddi upphaflega öfuga vísitölu byggða á LevelDB. En á endanum varð ég að gefast upp.

Hvers vegna? Vegna þess að LevelDB er hægari en barnaleg útfærsla. Í barnalegri útfærslu, gefinn tiltekinn lykil, sækjum við strax alla sneiðina metricIDs. Þetta er mjög hröð aðgerð - öll sneiðin er tilbúin til notkunar.

Í LevelDB, í hvert skipti sem fall er kallað GetValues þú þarft að fara í gegnum allar línur sem byrja á label=value. Og fáðu gildið fyrir hverja línu timeseries_ids. Af slíku timeseries_ids safna sneið af þessu timeseries_ids. Augljóslega er þetta miklu hægara en að fá aðgang að venjulegu korti með lykli.

Annar gallinn er sá að LevelDB er skrifað í C. Það er ekki mjög hratt að hringja í C aðgerðir frá Go. Það tekur hundruð nanósekúndna. Þetta er ekki mjög hratt, því miðað við venjulegt fallkall sem er skrifað í go, sem tekur 1-5 nanósekúndur, er munurinn á frammistöðu tugfaldur. Fyrir VictoriaMetrics var þetta banvænn galli :)

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Svo ég skrifaði mína eigin útfærslu á öfugu vísitölunni. Og hann kallaði á hana sameinast.

Mergeset er byggt á MergeTree gagnaskipulaginu. Þessi gagnauppbygging er fengin að láni frá ClickHouse. Augljóslega ætti samrunasett að vera fínstillt fyrir hraða leit timeseries_ids samkvæmt tilgreindum lykli. Mergeset er alfarið skrifað í Go. Þú getur séð VictoriaMetrics heimildir á GitHub. Útfærsla á sameiningu er í möppunni /lib/mergeset. Þú getur reynt að átta þig á hvað er í gangi þarna.

Samruna API er mjög svipað LevelDB og RocksDB. Það er, það gerir þér kleift að vista nýjar færslur þar og fljótt velja færslur með tilteknu forskeyti.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við munum tala um ókostina við sameiningu síðar. Nú skulum við tala um hvaða vandamál komu upp með VictoriaMetrics í framleiðslu við innleiðingu á hvolfi vísitölu.

Hvers vegna komu þeir upp?

Fyrsta ástæðan er há straumhraða. Þýtt á rússnesku er þetta tíð breyting á tímaröð. Þetta er þegar tímaröð lýkur og ný röð hefst, eða margar nýjar tímaraðir hefjast. Og þetta gerist oft.

Önnur ástæðan er mikill fjöldi tímaraða. Í upphafi, þegar vöktun var að ná vinsældum, var fjöldi tímaraða lítill. Til dæmis, fyrir hverja tölvu þarftu að fylgjast með örgjörva, minni, netkerfi og álagi disks. 4 tímaraðir á hverja tölvu. Segjum að þú sért með 100 tölvur og 400 tímaraðir. Þetta er mjög lítið.

Með tímanum komst fólk að því að það gæti mælt nákvæmari upplýsingar. Til dæmis, mældu ekki álagið á öllum örgjörvanum heldur sérstaklega á hvern örgjörvakjarna. Ef þú ert með 40 örgjörvakjarna, þá hefurðu 40 sinnum fleiri tímaraðir til að mæla álag á örgjörva.

En það er ekki allt. Hver örgjörvakjarni getur haft nokkur ástand, svo sem aðgerðalaus, þegar hann er aðgerðalaus. Og einnig vinna í notendarými, vinna í kjarnarými og öðrum ríkjum. Og hvert slíkt ástand er einnig hægt að mæla sem sérstaka tímaröð. Þetta eykur að auki fjölda raða um 7-8 sinnum.

Frá einum mælikvarða fengum við 40 x 8 = 320 mæligildi fyrir aðeins eina tölvu. Margfaldaðu með 100, við fáum 32 í stað 000.

Svo kom Kubernetes. Og það versnaði vegna þess að Kubernetes getur hýst margar mismunandi þjónustur. Hver þjónusta í Kubernetes samanstendur af mörgum belgjum. Og allt þetta þarf að fylgjast með. Að auki erum við með stöðuga dreifingu á nýjum útgáfum af þjónustu þinni. Fyrir hverja nýja útgáfu þarf að búa til nýjar tímaraðir. Fyrir vikið vex fjöldi tímaraða veldishraða og við stöndum frammi fyrir því vandamáli að fjöldi tímaraða, sem kallast hár-kardinalitet. VictoriaMetrics tekst á við það með góðum árangri miðað við aðra tímaraðar gagnagrunna.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Lítum nánar á háan straumhraða. Hvað veldur háum flutningshraða í framleiðslu? Vegna þess að sumar merkingar merkimiða og merkja eru stöðugt að breytast.

Tökum til dæmis Kubernetes, sem hefur hugmyndina deployment, þ.e. þegar ný útgáfa af forritinu þínu er sett út. Af einhverjum ástæðum ákváðu Kubernetes verktaki að bæta dreifingarauðkenninu við merkimiðann.

Til hvers leiddi þetta? Þar að auki, með hverri nýrri uppsetningu, eru allar gömlu tímaraðirnar rofnar og í stað þeirra byrja nýjar tímaraðir með nýju merkigildi deployment_id. Það geta verið hundruð þúsunda og jafnvel milljóna slíkra raða.

Það mikilvæga við þetta allt er að heildarfjöldi tímaraða vex, en fjöldi tímaraða sem eru virkir og taka á móti gögnum helst stöðugur. Þetta ástand er kallað hátt straumhraði.

Aðalvandamálið við háan straumhraða er að tryggja stöðugan leitarhraða fyrir allar tímaraðir fyrir tiltekið sett af merkjum á tilteknu tímabili. Venjulega er þetta tímabilið fyrir síðustu klukkustundina eða síðasta daginn.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hvernig á að leysa þetta vandamál? Hér er fyrsti kosturinn. Þetta er til að skipta öfugu vísitölunni í sjálfstæða hluta með tímanum. Það er að segja að nokkur tími líður, við klárum að vinna með núverandi snúningsvísitölu. Og búðu til nýja öfuga vísitölu. Annað tímabil líður, við búum til annað og annað.

Og þegar tekið er úrtak úr þessum öfugum vísitölum finnum við mengi öfugra vísitalna sem falla innan tiltekins bils. Og í samræmi við það veljum við auðkenni tímaröðarinnar þaðan.

Þetta sparar fjármagn vegna þess að við þurfum ekki að skoða hluta sem falla ekki innan tiltekins bils. Það er, venjulega, ef við veljum gögn fyrir síðustu klukkustund, þá sleppum við beiðnum fyrir fyrri tímabil.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Það er annar valkostur til að leysa þetta vandamál. Þetta er til að geyma fyrir hvern dag sérstakan lista yfir auðkenni tímaraðir sem áttu sér stað þann dag.

Kosturinn við þessa lausn umfram fyrri lausnina er að við afritum ekki upplýsingar um tímaraðir sem hverfa ekki með tímanum. Þeir eru stöðugt til staðar og breytast ekki.

Ókosturinn er sá að slík lausn er erfiðara í framkvæmd og erfiðara að kemba. Og VictoriaMetrics valdi þessa lausn. Svona gerðist þetta sögulega. Þessi lausn virkar líka vel miðað við þá fyrri. Vegna þess að þessi lausn var ekki útfærð vegna þess að það er nauðsynlegt að afrita gögn í hverri skiptingu fyrir tímaraðir sem breytast ekki, þ.e.a.s. hverfa ekki með tímanum. VictoriaMetrics var fyrst og fremst fínstillt fyrir plássnotkun og fyrri útfærsla gerði plássnotkun verri. En þessi útfærsla hentar betur til að lágmarka plássnotkun á disknum, svo hún varð fyrir valinu.

Ég varð að berjast við hana. Baráttan var sú að í þessari útfærslu þarf samt að velja mun stærri fjölda timeseries_ids fyrir gögn en þegar öfugvísitalan er tímaskipt.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hvernig leystum við þetta vandamál? Við leystum það á frumlegan hátt - með því að geyma nokkur tímaraðarauðkenni í hverri öfugri vísitölufærslu í stað eins auðkennis. Það er, við höfum lykil label=value, sem kemur fyrir í hverri tímaröð. Og nú björgum við nokkrum timeseries_ids í einni færslu.

Hér er dæmi. Áður höfðum við N færslur, en nú höfum við eina færslu þar sem forskeyti er það sama og allar hinar. Fyrir fyrri færslu inniheldur gildið öll auðkenni tímaraðar.

Þetta gerði það að verkum að hægt var að auka skönnunarhraða slíkrar öfugs vísitölu allt að 10 sinnum. Og það gerði okkur kleift að draga úr minnisnotkun fyrir skyndiminni, því nú geymum við strenginn label=value aðeins einu sinni í skyndiminni saman N sinnum. Og þessi lína getur verið stór ef þú geymir langar línur í merkjum þínum og merkimiðum, sem Kubernetes vill gjarnan ýta þangað.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Annar valkostur til að flýta fyrir leit á öfugum vísitölu er klipping. Að búa til nokkrar öfugar vísitölur í stað einnar og skipta gögnum á milli þeirra með lykli. Þetta er sett key=value gufu. Það er, við fáum nokkrar óháðar öfugar vísitölur, sem við getum spurt samhliða á nokkrum örgjörvum. Fyrri útfærslur leyfðu aðeins notkun í eins örgjörvaham, þ.e.a.s. skönnun gagna á aðeins einum kjarna. Þessi lausn gerir þér kleift að skanna gögn um nokkra kjarna í einu, eins og ClickHouse vill gera. Þetta er það sem við ætlum að hrinda í framkvæmd.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Snúum okkur nú aftur að kindunum okkar - að gatnamótaaðgerðinni timeseries_ids. Við skulum íhuga hvaða útfærslur það geta verið. Þessi aðgerð gerir þér kleift að finna timeseries_ids fyrir tiltekið sett label=value.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Fyrsti kosturinn er barnaleg útfærsla. Tvær hreiður lykkjur. Hér fáum við fallinntakið intersectInts tvær sneiðar - a и b. Við úttakið ætti það að skila okkur gatnamótum þessara sneiða.

Barnlaus útfærsla lítur svona út. Við endurtökum öll gildi frá sneið a, inni í þessari lykkju förum við í gegnum öll gildi sneiðarinnar b. Og við berum þá saman. Ef þeir passa saman, þá höfum við fundið gatnamót. Og vistaðu það inn result.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hverjir eru ókostirnir? Ferðungsflækjustig er helsti galli þess. Til dæmis, ef mál þín eru sneið a и b eina milljón í einu, þá mun þessi aðgerð aldrei skila þér svari. Vegna þess að það þarf að gera eina trilljón endurtekningar, sem er mikið jafnvel fyrir nútíma tölvur.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Önnur útfærslan er byggð á korti. Við búum til kort. Við setjum öll gildin frá sneið inn á þetta kort a. Síðan förum við í gegnum sneið í sérstakri lykkju b. Og við athugum hvort þetta gildi er frá sneið b í korti. Ef það er til skaltu bæta því við niðurstöðuna.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hverjir eru kostir? Kosturinn er sá að það er aðeins línulegt flókið. Það er, aðgerðin mun framkvæma mun hraðar fyrir stærri sneiðar. Fyrir milljón-stærðar sneið mun þessi aðgerð keyra í 2 milljón endurtekningum, öfugt við trilljón endurtekningar fyrri falls.

Gallinn er sá að þessi aðgerð þarf meira minni til að búa til þetta kort.

Annar gallinn er stór kostnaður fyrir hass. Þessi galli er ekki mjög augljós. Og fyrir okkur var það líka ekki mjög augljóst, þannig að fyrst í VictoriaMetrics var framkvæmd gatnamóta í gegnum kort. En svo sýndi prófílgreining að aðalvinnslutíminn fer í að skrifa á kortið og athuga hvort gildi sé til staðar á þessu korti.

Af hverju er örgjörvatími sóun á þessum stöðum? Vegna þess að Go framkvæmir hashing aðgerð á þessum línum. Það er, það reiknar kjötkássa lykilsins til að fá síðan aðgang að því á tiltekinni vísitölu í HashMap. Kássaútreikningsaðgerðinni er lokið á tugum nanósekúndna. Þetta er hægt hjá VictoriaMetrics.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Ég ákvað að innleiða bitasett sem er fínstillt sérstaklega fyrir þetta tilvik. Svona líta nú gatnamót tveggja sneiða út. Hér búum við til bitasett. Við bætum þáttum frá fyrstu sneiðinni við það. Síðan athugum við tilvist þessara þátta í annarri sneiðinni. Og bæta þeim við niðurstöðuna. Það er, það er nánast ekkert frábrugðið fyrra dæminu. Það eina hér er að við höfum skipt út aðgangi að korti fyrir sérsniðnar aðgerðir add и has.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við fyrstu sýn virðist sem þetta ætti að virka hægar, ef áður var notað staðlað kort þar, og þá eru nokkrar aðrar aðgerðir kallaðar, en prófílgreining sýnir að þessi hlutur virkar 10 sinnum hraðar en staðlað kort þegar um VictoriaMetrics er að ræða.

Að auki notar það mun minna minni miðað við kortaútfærsluna. Vegna þess að við erum að geyma bita hér í stað átta bæta gilda.

Ókosturinn við þessa útfærslu er að hún er ekki svo augljós, ekki léttvæg.

Annar galli sem margir taka kannski ekki eftir er að þessi útfærsla virkar kannski ekki vel í sumum tilfellum. Það er, það er fínstillt fyrir tiltekið tilvik, fyrir þetta tilvik þar sem skurðpunktur VictoriaMetrics tímaraðarauðkenna er. Þetta þýðir ekki að það henti öllum tilfellum. Ef það er notað vitlaust fáum við ekki frammistöðuaukningu heldur villu úr minni og hægari afköst.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við skulum íhuga útfærslu á þessari uppbyggingu. Ef þú vilt skoða þá er það staðsett í heimildum VictoriaMetrics, í möppunni lib/uint64set. Það er fínstillt sérstaklega fyrir VictoriaMetrics málið, þar sem timeseries_id er 64 bita gildi, þar sem fyrstu 32 bitarnir eru í grundvallaratriðum stöðugir og aðeins síðustu 32 bitarnir breytast.

Þessi gagnauppbygging er ekki geymd á diski, hún starfar aðeins í minni.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Hér er API þess. Það er ekki mjög flókið. API er sérsniðið að sérstöku dæmi um notkun VictoriaMetrics. Það er, það eru engar óþarfa aðgerðir hér. Hér eru aðgerðirnar sem eru sérstaklega notaðar af VictoriaMetrics.

Það eru aðgerðir add, sem bætir við nýjum gildum. Það er aðgerð has, sem leitar að nýjum gildum. Og það er hlutverk del, sem fjarlægir gildi. Það er hjálparaðgerð len, sem skilar stærð settsins. Virka clone klónar mikið. Og virka appendto breytir þessu setti í sneið timeseries_ids.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Svona lítur útfærsla þessa gagnaskipulags út. sett hefur tvo þætti:

  • ItemsCount er hjálparreitur til að skila hratt fjölda þátta í mengi. Það væri hægt að vera án þessa hjálparreits, en það varð að bæta því við hér vegna þess að VictoriaMetrics spyr oft um lengd bitasettsins í reikniritum sínum.

  • Annað sviðið er buckets. Þetta er sneið úr uppbyggingunni bucket32. Hvert mannvirki geymir hi sviði. Þetta eru efri 32 bitarnir. Og tvær sneiðar - b16his и buckets á bucket16 mannvirki.

Efstu 16 bitarnir í seinni hluta 64-bita uppbyggingarinnar eru geymdir hér. Og hér eru bitasett geymd fyrir neðri 16 bita hvers bæti.

Bucket64 samanstendur af fylki uint64. Lengdin er reiknuð út með þessum föstum. Í einu bucket16 hámark er hægt að geyma 2^16=65536 smá. Ef þú deilir þessu með 8, þá eru það 8 kílóbæti. Ef þú deilir aftur með 8 þá er það 1000 uint64 merkingu. Það er Bucket16 – þetta er 8 kílóbæta uppbyggingin okkar.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Við skulum skoða hvernig ein af aðferðum þessarar uppbyggingu til að bæta við nýju gildi er útfærð.

Þetta byrjar allt með uint64 merkingar. Við reiknum efri 32 bitana, við reiknum neðri 32 bitana. Við skulum fara í gegnum allt buckets. Við berum saman efstu 32 bitana í hverri fötu við verðmætið sem bætt er við. Og ef þeir passa saman, þá köllum við fallið add í byggingu b32 buckets. Og bættu við neðri 32 bitunum þar. Og ef það skilaði sér true, þá þýðir þetta að við bættum slíku gildi þarna og við höfðum ekki slíkt gildi. Ef það skilar sér false, þá var slík merking þegar til. Síðan fjölgum við þáttum í uppbyggingunni.

Ef við höfum ekki fundið þann sem þú þarft bucket með tilskildu há-gildi, þá köllum við fallið addAlloc, sem mun framleiða nýjan bucket, bætir því við fötubygginguna.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Þetta er útfærsla aðgerðarinnar b32.add. Það er svipað og fyrri útfærsla. Við reiknum út mikilvægustu 16 bitana, minnstu 16 bita.

Síðan förum við í gegnum alla efri 16 bitana. Við finnum samsvörun. Og ef það er samsvörun köllum við add-aðferðina, sem við munum íhuga á næstu síðu fyrir bucket16.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Og hér er lægsta stigið, sem ætti að hagræða eins mikið og mögulegt er. Við reiknum fyrir uint64 auðkennisgildi í sneiðbita og líka bitmask. Þetta er gríma fyrir tiltekið 64-bita gildi, sem hægt er að nota til að athuga tilvist þessa bita, eða stilla hann. Við athugum hvort þessi biti sé stilltur og stillum hann og skilum viðveru. Þetta er útfærsla okkar, sem gerði okkur kleift að flýta fyrir aðgerðum á skerandi auðkennum tímaraða um 10 sinnum miðað við hefðbundin kort.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Til viðbótar við þessa hagræðingu hefur VictoriaMetrics margar aðrar hagræðingar. Flestum þessara hagræðinga var bætt við af ástæðu, en eftir að hafa búið til kóðann í framleiðslu.

Þetta er meginreglan um hagræðingu - ekki bæta við hagræðingu að því gefnu að það verði flöskuháls hér, því það getur komið í ljós að það verður ekki flöskuháls þar. Hagræðing rýrir venjulega gæði kóðans. Þess vegna er það þess virði að hagræða aðeins eftir prófílgreiningu og helst í framleiðslu, þannig að þetta séu raunveruleg gögn. Ef einhver hefur áhuga geturðu skoðað VictoriaMetrics frumkóðann og skoðað aðrar hagræðingar sem eru til staðar.

Farðu í hagræðingar í VictoriaMetrics. Alexander Valyalkin

Ég er með spurningu um bitset. Mjög svipað og C++ vektor bool útfærslan, fínstillt bitasett. Tókstu útfærsluna þaðan?

Nei, ekki þaðan. Við innleiðingu þessa bitasetts hafði ég að leiðarljósi þekkingu á uppbyggingu þessara auðkennatímaraða, sem eru notaðar í VictoriaMetrics. Og uppbygging þeirra er þannig að efri 32 bitarnir eru í grundvallaratriðum stöðugir. Neðri 32 bitarnir geta breyst. Því lægri sem bitinn er, því oftar getur hann breyst. Þess vegna er þessi útfærsla sérstaklega fínstillt fyrir þessa gagnauppbyggingu. C++ útfærslan, eftir því sem ég best veit, er fínstillt fyrir almenna tilvikið. Ef þú hagræðir fyrir almenna tilvikið þýðir það að það verður ekki það besta fyrir tiltekið tilvik.

Ég ráðlegg þér líka að horfa á skýrslu Alexey Milovid. Fyrir um mánuði síðan talaði hann um hagræðingu í ClickHouse fyrir sérstakar sérhæfingar. Hann segir bara að í almennu tilvikinu sé C++ útfærsla eða einhver önnur útfærsla sniðin til að virka vel að meðaltali á sjúkrahúsi. Það gæti reynst verr en þekkingarsértæk útfærsla eins og okkar, þar sem við vitum að efstu 32 bitarnir eru að mestu stöðugir.

Ég er með aðra spurningu. Hver er grundvallarmunurinn á InfluxDB?

Það eru margir grundvallarmunir. Hvað varðar afköst og minnisnotkun, sýnir InfluxDB í prófunum 10 sinnum meiri minnisnotkun fyrir tímaraðir með miklar kardinalitetar, þegar þú ert með mikið af þeim, til dæmis milljónir. Til dæmis eyðir VictoriaMetrics 1 GB á hverja milljón virkra raða, en InfluxDB eyðir 10 GB. Og það er mikill munur.

Annar grundvallarmunurinn er sá að InfluxDB er með undarleg fyrirspurnartungumál - Flux og InfluxQL. Þeir eru ekki mjög þægilegir til að vinna með tímaraðir miðað við PromQL, sem er studd af VictoriaMetrics. PromQL er fyrirspurnartungumál frá Prometheus.

Og enn einn munurinn er sá að InfluxDB er með svolítið undarlegt gagnalíkan, þar sem hver lína getur geymt nokkra reiti með mismunandi setti af merkjum. Þessum línum er frekar skipt í ýmsar töflur. Þessar viðbótarflækjur torvelda síðari vinnu við þennan gagnagrunn. Það er erfitt að styðja og skilja.

Í VictoriaMetrics er allt miklu einfaldara. Þar er hver tímaröð lykilgildi. Gildið er sett af punktum - (timestamp, value), og lykillinn er settið label=value. Enginn aðskilnaður er á milli sviða og mælinga. Það gerir þér kleift að velja hvaða gögn sem er og síðan sameina, leggja saman, draga frá, margfalda, deila, ólíkt InfluxDB þar sem útreikningar á milli mismunandi raða eru enn ekki útfærðir eftir því sem ég best veit. Jafnvel þótt þau séu útfærð er það erfitt, þú þarft að skrifa mikinn kóða.

Ég er með skýringarspurningu. Skildi ég rétt að það væri einhver vandamál sem þú talaðir um, að þessi öfugvísisvísitala passar ekki inn í minnið, þannig að það er skipting þar?

Fyrst sýndi ég barnalega útfærslu á öfugum vísitölu á venjulegu Go korti. Þessi útfærsla hentar ekki fyrir gagnagrunna vegna þess að þessi öfugvísisvísitala er ekki vistuð á disk og gagnagrunnurinn verður að vista á disk svo þessi gögn verði áfram tiltæk við endurræsingu. Í þessari útfærslu, þegar þú endurræsir forritið, hverfur öfugvísitalan þín. Og þú munt missa aðgang að öllum gögnum vegna þess að þú munt ekki geta fundið þau.

Halló! Takk fyrir skýrsluna! Ég heiti Pavel. Ég er frá Wildberries. Ég hef nokkrar spurningar til þín. Spurning eitt. Heldurðu að ef þú hefðir valið aðra meginreglu þegar þú byggir upp arkitektúr forritsins þíns og skipt gögnunum í sundur með tímanum, þá hefðirðu kannski getað skorið gögn þegar leitað var, byggt eingöngu á því að ein skipting inniheldur gögn fyrir einn tímabil , það er að segja á einu tímabili og þú þyrftir ekki að hafa áhyggjur af því að stykkin þín dreifist öðruvísi? Spurning númer 2 - þar sem þú ert að innleiða svipað reiknirit með bitasetti og öllu öðru, þá hefurðu kannski reynt að nota örgjörvaleiðbeiningar? Kannski hefurðu prófað slíkar hagræðingar?

Ég svara þeirri seinni strax. Við erum ekki komin á þann stað ennþá. En ef nauðsyn krefur munum við komast þangað. Og sú fyrsta, hver var spurningin?

Þú ræddir tvær aðstæður. Og þeir sögðust hafa valið þann seinni með flóknari útfærslu. Og þeir vildu ekki þann fyrsta, þar sem gögnin eru skipt eftir tíma.

Já. Í fyrra tilvikinu væri heildarmagn vísitölunnar stærra, vegna þess að í hverri skiptingu þyrftum við að geyma afrit gögn fyrir þær tímaraðir sem halda áfram í gegnum allar þessar skiptingar. Og ef straumhraðinn þinn er lítill, þ.e.a.s. sömu röðin eru stöðugt notuð, þá myndum við í fyrra tilvikinu tapa miklu meira af uppteknu plássi miðað við annað tilvikið.

Og svo - já, tímaskipting er góður kostur. Prometheus notar það. En Prometheus hefur annan galla. Þegar þessi gögn eru sameinuð þarf það að geyma metaupplýsingar í minni fyrir öll merki og tímaröð. Þess vegna, ef gagnastykkin sem það sameinar eru stór, þá eykst minnisnotkun mjög mikið við sameiningu, ólíkt VictoriaMetrics. Við sameiningu eyðir VictoriaMetrics alls ekki minni; aðeins nokkur kílóbæti eru notuð, óháð stærð sameinaðra gagna.

Reikniritið sem þú notar notar minni. Það merkir tímaraðarmerki sem innihalda gildi. Og þannig athugarðu hvort pöruð viðvera sé í einu gagnafylki og í öðru. Og þú skilur hvort skurður átti sér stað eða ekki. Venjulega útfæra gagnagrunnar bendila og endurtekningar sem geyma núverandi innihald þeirra og keyra í gegnum flokkuð gögn vegna þess hve flóknar þessar aðgerðir eru einfaldar.

Af hverju notum við ekki bendilinn til að fara yfir gögn?

Já ég er.

Við geymum flokkaðar línur í LevelDB eða sameiningu. Við getum fært bendilinn og fundið gatnamótin. Af hverju notum við það ekki? Vegna þess að það er hægt. Vegna þess að bendillar þýða að þú þarft að kalla á fall fyrir hverja línu. Aðgerðarkall er 5 nanósekúndur. Og ef þú ert með 100 línur, þá kemur í ljós að við eyðum hálfri sekúndu í að hringja í fallið.

Það er til svoleiðis, já. Og síðasta spurningin mín. Spurningin hljómar kannski svolítið undarlega. Hvers vegna er ekki hægt að lesa allar nauðsynlegar upplýsingar um leið og gögnin berast og vista þau á tilskildu formi? Af hverju að spara mikið magn í sumum kerfum eins og VictoriaMetrics, ClickHouse o.s.frv., og eyða svo miklum tíma í þau?

Ég skal nefna dæmi til að gera það skýrara. Segjum hvernig virkar lítill leikfangahraðamælir? Það skráir vegalengdina sem þú hefur ferðast, bætir henni alltaf við eitt gildi og í annað skipti. Og sundrar. Og fær meðalhraða. Þú getur gert um það sama. Leggðu saman allar nauðsynlegar staðreyndir á flugu.

Allt í lagi, ég skil spurninguna. Dæmið þitt á sinn stað. Ef þú veist hvaða malarefni þú þarft, þá er þetta besta útfærslan. En vandamálið er að fólk vistar þessar mælingar, sum gögn í ClickHouse og þeir vita ekki enn hvernig þau munu safnast saman og sía þau í framtíðinni, svo það verður að vista öll hrá gögnin. En ef þú veist að þú þarft að reikna eitthvað að meðaltali, hvers vegna ekki að reikna það í stað þess að geyma fullt af hrágildum þar? En þetta er aðeins ef þú veist nákvæmlega hvað þú þarft.

Við the vegur, gagnagrunnar til að geyma tímaraðir styðja talningu á samanlögðum. Til dæmis styður Prometheus reglum um upptöku. Það er, þetta er hægt að gera ef þú veist hvaða einingar þú þarft. VictoriaMetrics er ekki með þetta ennþá, en það er venjulega á undan Prometheus, þar sem þetta er hægt að gera í umkóðun reglunum.

Til dæmis, í fyrra starfi mínu þurfti ég að telja fjölda atburða í rennandi glugga síðasta klukkutímann. Vandamálið er að ég þurfti að gera sérsniðna útfærslu í Go, þ.e.a.s þjónustu til að telja þennan hlut. Þessi þjónusta var á endanum ekki léttvæg, því það er erfitt að reikna hana út. Útfærslan getur verið einföld ef þú þarft að telja nokkrar tölur með föstu millibili. Ef þú vilt telja atburði í rennandi glugga, þá er það ekki eins einfalt og það virðist. Ég held að þetta hafi ekki enn verið innleitt í ClickHouse eða í tímaröð gagnagrunna, því það er erfitt í framkvæmd.

Og ein spurning í viðbót. Við vorum bara að tala um meðaltal og ég mundi að það var einu sinni til eitthvað sem hét Grafít með kolefnisbakenda. Og hann vissi hvernig á að þynna út gömul gögn, það er að skilja eftir einn punkt á mínútu, einn punkt á klukkustund osfrv. Í grundvallaratriðum er þetta mjög þægilegt ef við þurfum hrá gögn, tiltölulega séð, í mánuð, og allt annað getur vera þynnt út. En Prometheus og VictoriaMetrics styðja ekki þessa virkni. Er fyrirhugað að styrkja það? Ef ekki, hvers vegna ekki?

Takk fyrir spurninguna. Notendur okkar spyrja þessarar spurningar reglulega. Þeir spyrja hvenær við munum bæta við stuðningi við niðursýni. Hér eru nokkur vandamál. Í fyrsta lagi skilur hver notandi downsampling eitthvað annað: einhver vill fá hvaða geðþóttapunkt sem er á tilteknu bili, einhver vill hámarks-, lágmarks-, meðalgildi. Ef mörg kerfi skrifa gögn í gagnagrunninn þinn, þá geturðu ekki sameinað þetta allt saman. Það getur verið að hvert kerfi þurfi mismunandi þynningu. Og þetta er erfitt í framkvæmd.

Og annað er að VictoriaMetrics, eins og ClickHouse, er fínstillt til að vinna að miklu magni af hráum gögnum, þannig að það getur mokað milljarð línur á innan við sekúndu ef þú ert með marga kjarna í kerfinu þínu. Skannar tímaraðarpunkta í VictoriaMetrics – 50 punktar á sekúndu á kjarna. Og þessi árangur skalast að núverandi kjarna. Það er að segja, ef þú ert með 000 kjarna, til dæmis, muntu skanna milljarð punkta á sekúndu. Og þessi eign VictoriaMetrics og ClickHouse dregur úr þörfinni fyrir downsamling.

Annar eiginleiki er að VictoriaMetrics þjappar þessum gögnum á áhrifaríkan hátt. Þjöppun að meðaltali í framleiðslu er frá 0,4 til 0,8 bæti á punkt. Hver punktur er tímastimpill + gildi. Og það er þjappað niður í minna en eitt bæti að meðaltali.

Sergey. Ég er með spurningu. Hver er lágmarks upptökutími skammtafræði?

Ein millisekúnda. Við áttum nýlega samtal við aðra tímaraðagagnagrunnhönnuði. Lágmarks tímasneið þeirra er ein sekúnda. Og í Graphite, til dæmis, er það líka ein sekúnda. Í OpenTSDB er það líka ein sekúnda. InfluxDB hefur nanósekúndu nákvæmni. Í VictoriaMetrics er það ein millisekúnda, því í Prometheus er það ein millisekúnda. Og VictoriaMetrics var upphaflega þróað sem fjargeymslu fyrir Prometheus. En nú getur það vistað gögn frá öðrum kerfum.

Sá sem ég talaði við segir að þeir hafi sekúndu til sekúndu nákvæmni - það er nóg fyrir þá vegna þess að það fer eftir því hvers konar gögn eru geymd í tímaraðagagnagrunninum. Ef þetta eru DevOps gögn eða gögn úr innviðum, þar sem þú safnar þeim með 30 sekúndna millibili, á mínútu, þá er sekúndu nákvæmni nóg, þú þarft ekkert minna. Og ef þú safnar þessum gögnum frá hátíðniviðskiptakerfum, þá þarftu nanósekúndu nákvæmni.

Millisúndu nákvæmni í VictoriaMetrics hentar einnig DevOps tilfellinu og getur hentað flestum tilfellum sem ég nefndi í upphafi skýrslunnar. Það eina sem það hentar kannski ekki eru hátíðniviðskiptakerfi.

Þakka þér fyrir! Og önnur spurning. Hvað er eindrægni í PromQL?

Fullt afturábak eindrægni. VictoriaMetrics styður PromQL að fullu. Að auki bætir það við frekari háþróaðri virkni í PromQL, sem kallast MetricsQL. Það er talað á YouTube um þessa auknu virkni. Ég talaði á eftirlitsfundinum í vor í Pétursborg.

Rás símskeytis VictoriaMetrics.

Aðeins skráðir notendur geta tekið þátt í könnuninni. Skráðu þig inn, takk.

Hvað hindrar þig í að skipta yfir í VictoriaMetrics sem langtímageymslu fyrir Prometheus? (Skrifaðu í athugasemdir, ég bæti því við könnunina))

  • 71,4%Ég nota ekki Prometheus5

  • 28,6%Vissi ekki um VictoriaMetrics2

7 notendur kusu. 12 notendur sátu hjá.

Heimild: www.habr.com

Bæta við athugasemd