GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Jag föreslÄr att du lÀser utskriften av rapporten frÄn sena 2019 av Alexander Valyalkin "Go optimizations in VictoriaMetrics"

VictoriaMetrics — ett snabbt och skalbart DBMS för lagring och bearbetning av data i form av en tidsserie (posten bildar tid och en uppsĂ€ttning vĂ€rden som motsvarar denna tid, till exempel erhĂ„llen genom periodisk undersökning av sensorernas status eller insamling av metrik).

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

HÀr Àr en lÀnk till videon av denna rapport - https://youtu.be/MZ5P21j_HLE

Diabilder

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

BerÀtta för oss om dig sjÀlv. Jag Àr Alexander Valyalkin. HÀr mitt GitHub-konto. Jag brinner för Go och prestandaoptimering. Jag skrev mÄnga anvÀndbara och inte sÀrskilt anvÀndbara bibliotek. De börjar med antingen fast, eller med quick prefix.

Jag jobbar just nu med VictoriaMetrics. Vad Àr det och vad gör jag dÀr? Jag kommer att prata om detta i denna presentation.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Sammanfattningen av rapporten Àr som följer:

  • Först ska jag berĂ€tta vad VictoriaMetrics Ă€r.
  • DĂ„ ska jag berĂ€tta vad tidsserier Ă€r.
  • Sedan ska jag berĂ€tta hur en tidsseriedatabas fungerar.
  • DĂ€refter ska jag berĂ€tta om databasarkitekturen: vad den bestĂ„r av.
  • Och lĂ„t oss sedan gĂ„ vidare till de optimeringar som VictoriaMetrics har. Detta Ă€r en optimering för det inverterade indexet och en optimering för bitsetimplementeringen i Go.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Vet nÄgon i publiken vad VictoriaMetrics Àr? Wow, mÄnga vet redan. Det Àr goda nyheter. För den som inte vet Àr detta en tidsseriedatabas. Den Àr baserad pÄ ClickHouse-arkitekturen, pÄ vissa detaljer om ClickHouse-implementeringen. Till exempel pÄ som: MergeTree, parallell berÀkning pÄ alla tillgÀngliga processorkÀrnor och prestandaoptimering genom att arbeta pÄ datablock som placeras i processorcachen.

VictoriaMetrics ger bÀttre datakomprimering Àn andra tidsseriedatabaser.

Den skalas vertikalt - det vill sÀga du kan lÀgga till fler processorer, mer RAM pÄ en dator. VictoriaMetrics kommer att framgÄngsrikt anvÀnda dessa tillgÀngliga resurser och kommer att förbÀttra linjÀr produktivitet.

VictoriaMetrics skalar ocksÄ horisontellt - det vill sÀga du kan lÀgga till ytterligare noder till VictoriaMetrics-klustret, och dess prestanda kommer att öka nÀstan linjÀrt.

Som du gissade Àr VictoriaMetrics en snabb databas, eftersom jag inte kan skriva andra. Och det Àr skrivet i Go, sÄ jag pratar om det pÄ det hÀr mötet.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Vem vet vad en tidsserie Ă€r? Han kĂ€nner ocksĂ„ mĂ„nga mĂ€nniskor. En tidsserie Ă€r en serie av par (timestamp, Đ·ĐœĐ°Ń‡Đ”ĐœĐžĐ”), dĂ€r dessa par sorteras efter tid. VĂ€rdet Ă€r ett flyttal – float64.

Varje tidsserie identifieras unikt med en nyckel. Vad bestÄr denna nyckel av? Den bestÄr av en icke-tom uppsÀttning nyckel-vÀrdepar.

HÀr Àr ett exempel pÄ en tidsserie. Nyckeln i denna serie Àr en lista med par: __name__="cpu_usage" Àr namnet pÄ mÄtten, instance="my-server" - det hÀr Àr datorn pÄ vilken detta mÄtt samlas in, datacenter="us-east" - det hÀr Àr datacentret dÀr den hÀr datorn finns.

Vi slutade med ett tidsserienamn bestĂ„ende av tre nyckel-vĂ€rdepar. Denna nyckel motsvarar en lista med par (timestamp, value). t1, t3, t3, ..., tN - det hĂ€r Ă€r tidsstĂ€mplar, 10, 20, 12, ..., 15 — motsvarande vĂ€rden. Detta Ă€r CPU-anvĂ€ndningen vid en given tidpunkt för en given rad.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Var kan tidsserier anvĂ€ndas? Är det nĂ„gon som har nĂ„gon aning?

  • I DevOps kan du mĂ€ta CPU, RAM, nĂ€tverk, rps, antal fel osv.
  • IoT – vi kan mĂ€ta temperatur, tryck, geokoordinater och nĂ„got annat.
  • Även ekonomi – vi kan övervaka priser för alla typer av aktier och valutor.
  • Dessutom kan tidsserier anvĂ€ndas för att övervaka produktionsprocesser i fabriker. Vi har anvĂ€ndare som anvĂ€nder VictoriaMetrics för att övervaka vindkraftverk, för robotar.
  • Tidsserier Ă€r ocksĂ„ anvĂ€ndbara för att samla in information frĂ„n sensorer för olika enheter. Till exempel för en motor; för mĂ€tning av dĂ€cktryck; för mĂ€tning av hastighet, avstĂ„nd; för mĂ€tning av bensinförbrukning m.m.
  • Tidsserier kan ocksĂ„ anvĂ€ndas för att övervaka flygplan. Varje flygplan har en svart lĂ„da som samlar in tidsserier för olika parametrar för flygplanets hĂ€lsa. Tidsserier anvĂ€nds ocksĂ„ inom flygindustrin.
  • SjukvĂ„rd Ă€r blodtryck, puls osv.

Det kan finnas fler applikationer som jag glömt bort, men jag hoppas att du förstÄr att tidsserier aktivt anvÀnds i den moderna vÀrlden. Och volymen av deras anvÀndning vÀxer varje Är.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Varför behöver du en tidsseriedatabas? Varför kan du inte anvÀnda en vanlig relationsdatabas för att lagra tidsserier?

Eftersom tidsserier vanligtvis innehÄller en stor mÀngd information, vilket Àr svÄrt att lagra och bearbeta i konventionella databaser. DÀrför dök det upp specialiserade databaser för tidsserier. Dessa baser lagrar effektivt poÀng (timestamp, value) med den angivna nyckeln. De tillhandahÄller ett API för att lÀsa lagrad data efter nyckel, med ett enda nyckel-vÀrde-par, eller av flera nyckel-vÀrde-par, eller efter regexp. Om du till exempel vill hitta CPU-belastningen för alla dina tjÀnster i ett datacenter i Amerika, dÄ mÄste du anvÀnda den hÀr pseudofrÄgan.

Vanligtvis tillhandahĂ„ller tidsseriedatabaser specialiserade frĂ„gesprĂ„k eftersom tidsserier SQL inte Ă€r sĂ€rskilt vĂ€l lĂ€mpade. Även om det finns databaser som stöder SQL Ă€r det inte sĂ€rskilt lĂ€mpligt. FrĂ„ga sprĂ„k som t.ex PromQL, InfluxQL, Flux, Q. Jag hoppas att nĂ„gon har hört Ă„tminstone ett av dessa sprĂ„k. MĂ„nga har sĂ€kert hört talas om PromQL. Detta Ă€r frĂ„gesprĂ„ket Prometheus.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

SÄ hÀr ser en modern tidsseriedatabasarkitektur ut med VictoriaMetrics som exempel.

Den bestÄr av tvÄ delar. Detta Àr lagring för det inverterade indexet och lagring för tidsserievÀrden. Dessa förrÄd Àr separerade.

NÀr en ny post kommer in i databasen kommer vi först Ät det inverterade indexet för att hitta tidsserieidentifieraren för en given uppsÀttning label=value för ett givet mÄtt. Vi hittar denna identifierare och sparar vÀrdet i datalagret.

NÀr en begÀran kommer att hÀmta data frÄn TSDB gÄr vi först till det inverterade indexet. LÄt oss fÄ allt timeseries_ids rekord som matchar denna uppsÀttning label=value. Och sedan fÄr vi all nödvÀndig data frÄn datalagret, indexerad av timeseries_ids.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LÄt oss titta pÄ ett exempel pÄ hur en tidsseriedatabas behandlar en inkommande urvalsfrÄga.

  • Först och frĂ€mst fĂ„r hon allt timeseries_ids frĂ„n ett inverterat index som innehĂ„ller de givna paren label=value, eller uppfyller ett givet reguljĂ€rt uttryck.
  • Sedan hĂ€mtar den alla datapunkter frĂ„n datalagringen vid ett givet tidsintervall för de hittade timeseries_ids.
  • Efter detta utför databasen vissa berĂ€kningar pĂ„ dessa datapunkter, enligt anvĂ€ndarens begĂ€ran. Och efter det returnerar den svaret.

I den hÀr presentationen kommer jag att berÀtta om den första delen. Det hÀr Àr en sökning timeseries_ids genom inverterat index. Du kan se om den andra delen och den tredje delen senare VictoriaMetrics kÀllor, eller vÀnta tills jag förbereder andra rapporter :)

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LĂ„t oss gĂ„ vidare till det inverterade indexet. MĂ„nga kanske tycker att detta Ă€r enkelt. Vem vet vad ett inverterat index Ă€r och hur det fungerar? Åh, inte sĂ„ mycket folk lĂ€ngre. LĂ„t oss försöka förstĂ„ vad det Ă€r.

Det Àr faktiskt enkelt. Det Àr helt enkelt en ordbok som mappar en nyckel till ett vÀrde. Vad Àr en nyckel? Detta par label=valuevar label О value - det hÀr Àr rader. Och vÀrdena Àr en uppsÀttning timeseries_ids, som inkluderar det givna paret label=value.

Inverterat index gör att du snabbt kan hitta allt timeseries_ids, som har gett label=value.

Det lÄter dig ocksÄ snabbt hitta timeseries_ids tidsserier för flera par label=value, eller för par label=regexp. Hur gÄr det till? Genom att hitta skÀrningspunkten för uppsÀttningen timeseries_ids för varje par label=value.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LÄt oss titta pÄ olika implementeringar av det inverterade indexet. LÄt oss börja med den enklaste naiva implementeringen. Hon ser ut sÄ hÀr.

Funktion getMetricIDs fÄr en lista med strÀngar. Varje rad innehÄller label=value. Denna funktion returnerar en lista metricIDs.

Hur det fungerar? HÀr har vi en global variabel som heter invertedIndex. Detta Àr en vanlig ordbok (map), vilket kommer att mappa strÀngen till segmentints. Linjen innehÄller label=value.

Funktionsimplementering: get metricIDs för det första label=value, sedan gÄr vi igenom allt annat label=value, vi förstÄr metricIDs för dem. Och ring funktionen intersectInts, som kommer att diskuteras nedan. Och den hÀr funktionen returnerar skÀrningspunkten mellan dessa listor.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Som du kan se Àr det inte sÀrskilt komplicerat att implementera ett inverterat index. Men det hÀr Àr en naiv implementering. Vilka nackdelar har det? Den största nackdelen med den naiva implementeringen Àr att ett sÄdant inverterat index lagras i RAM. Efter att ha startat om programmet tappar vi detta index. Det finns ingen lagring av detta index pÄ disk. Ett sÄdant inverterat index Àr osannolikt lÀmpligt för en databas.

Den andra nackdelen Àr ocksÄ relaterad till minnet. Det inverterade indexet mÄste passa in i RAM. Om det överstiger storleken pÄ RAM-minnet, kommer vi uppenbarligen att fÄ ett minnesfel. Och programmet fungerar inte.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Detta problem kan lösas med hjÀlp av fÀrdiga lösningar som t.ex NivÄDBEller StenarDB.

Kort sagt, vi behöver en databas som gör att vi kan göra tre operationer snabbt.

  • Den första operationen Ă€r inspelning Đșлюч-Đ·ĐœĐ°Ń‡Đ”ĐœĐžĐ” till denna databas. Hon gör det hĂ€r vĂ€ldigt snabbt, var Đșлюч-Đ·ĐœĐ°Ń‡Đ”ĐœĐžĐ” Ă€r godtyckliga strĂ€ngar.
  • Den andra operationen Ă€r en snabb sökning efter ett vĂ€rde med hjĂ€lp av en given nyckel.
  • Och den tredje operationen Ă€r en snabb sökning efter alla vĂ€rden med ett givet prefix.

LevelDB och RocksDB - dessa databaser har utvecklats av Google och Facebook. Först kom LevelDB. Sedan tog killarna frÄn Facebook LevelDB och började förbÀttra det, de gjorde RocksDB. Nu fungerar nÀstan alla interna databaser pÄ RocksDB inuti Facebook, inklusive de som har överförts till RocksDB och MySQL. De namngav honom MyRocks.

Ett inverterat index kan implementeras med LevelDB. Hur man gör det? Vi sparar som nyckel label=value. Och vÀrdet Àr identifieraren för tidsserien dÀr paret finns label=value.

Om vi ​​har mĂ„nga tidsserier med ett givet par label=value, dĂ„ kommer det att finnas mĂ„nga rader i denna databas med samma nyckel och olika timeseries_ids. För att fĂ„ en lista över alla timeseries_ids, som börjar med detta label=prefix, gör vi en rĂ€ckviddsskanning för vilken denna databas Ă€r optimerad. Det vill sĂ€ga vi vĂ€ljer alla rader som börjar med label=prefix och fĂ„ det nödvĂ€ndiga timeseries_ids.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

HÀr Àr ett exempel pÄ hur det skulle se ut i Go. Vi har ett inverterat index. Det hÀr Àr LevelDB.

Funktionen Àr densamma som för den naiva implementeringen. Den upprepar den naiva implementeringen nÀstan rad för rad. Den enda poÀngen Àr att istÀllet för att vÀnda sig till map vi kommer Ät det inverterade indexet. Vi fÄr alla vÀrden för den första label=value. Sedan gÄr vi igenom alla ÄterstÄende par label=value och fÄ motsvarande uppsÀttningar av metricIDs för dem. Sedan hittar vi korsningen.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Allt verkar vara bra, men det finns nackdelar med denna lösning. VictoriaMetrics implementerade initialt ett inverterat index baserat pÄ LevelDB. Men till slut var jag tvungen att ge upp.

Varför? Eftersom LevelDB Àr lÄngsammare Àn den naiva implementeringen. I en naiv implementering, givet en given nyckel, hÀmtar vi omedelbart hela segmentet metricIDs. Detta Àr en mycket snabb operation - hela skivan Àr redo att anvÀndas.

I LevelDB, varje gÄng en funktion anropas GetValues du mÄste gÄ igenom alla rader som börjar med label=value. Och fÄ vÀrdet för varje rad timeseries_ids. Av sÄdant timeseries_ids samla en bit av dessa timeseries_ids. Uppenbarligen Àr detta mycket lÄngsammare Àn att bara komma Ät en vanlig karta med nyckel.

Den andra nackdelen Àr att LevelDB Àr skrivet i C. Att anropa C-funktioner frÄn Go gÄr inte sÀrskilt snabbt. Det tar hundratals nanosekunder. Detta Àr inte sÀrskilt snabbt, för jÀmfört med ett vanligt funktionsanrop skrivet i go, som tar 1-5 nanosekunder, Àr skillnaden i prestanda tiotals gÄnger. För VictoriaMetrics var detta ett ödesdigert fel :)

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

SĂ„ jag skrev min egen implementering av det inverterade indexet. Och han ringde henne mergeset.

Mergeset Àr baserat pÄ MergeTree-datastrukturen. Denna datastruktur Àr lÄnad frÄn ClickHouse. SjÀlvklart bör mergeset optimeras för snabb sökning timeseries_ids enligt den givna nyckeln. Mergeset Àr skrivet helt i Go. Du kan se VictoriaMetrics kÀllor pÄ GitHub. Implementeringen av mergeset finns i mappen /lib/mergeset. Du kan försöka ta reda pÄ vad som hÀnder dÀr.

Mergeset API Àr vÀldigt lik LevelDB och RocksDB. Det vill sÀga att du snabbt kan spara nya poster dÀr och snabbt vÀlja poster med ett givet prefix.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Vi kommer att prata om nackdelarna med mergeset senare. LÄt oss nu prata om vilka problem som uppstod med VictoriaMetrics i produktionen nÀr vi implementerade ett inverterat index.

Varför uppstod de?

Den första anledningen Ă€r den höga churn rate. Översatt till ryska Ă€r detta en frekvent förĂ€ndring i tidsserier. Det Ă€r nĂ€r en tidsserie slutar och en ny serie börjar, eller mĂ„nga nya tidsserier börjar. Och detta hĂ€nder ofta.

Det andra skÀlet Àr det stora antalet tidsserier. I början, nÀr övervakningen blev populÀr, var antalet tidsserier litet. Till exempel, för varje dator mÄste du övervaka CPU, minne, nÀtverk och diskbelastning. 4 tidsserier per dator. LÄt oss sÀga att du har 100 datorer och 400 tidsserier. Det hÀr Àr vÀldigt lite.

Med tiden kom mÀnniskor pÄ att de kunde mÀta mer detaljerad information. MÀt till exempel belastningen inte för hela processorn, utan separat för varje processorkÀrna. Om du har 40 processorkÀrnor har du 40 gÄnger fler tidsserier för att mÀta processorbelastningen.

Men det Àr inte allt. Varje processorkÀrna kan ha flera tillstÄnd, till exempel inaktiv, nÀr den Àr inaktiv. Och Àven arbeta i anvÀndarutrymme, arbeta i kÀrnutrymme och andra tillstÄnd. Och varje sÄdant tillstÄnd kan ocksÄ mÀtas som en separat tidsserie. Detta ökar dessutom antalet rader med 7-8 gÄnger.

FrÄn ett mÄtt fick vi 40 x 8 = 320 mÄtt för bara en dator. Multiplicera med 100, vi fÄr 32 000 istÀllet för 400.

Sedan kom Kubernetes. Och det blev vÀrre eftersom Kubernetes kan vara vÀrd för mÄnga olika tjÀnster. Varje tjÀnst i Kubernetes bestÄr av mÄnga poddar. Och allt detta mÄste övervakas. Dessutom har vi en stÀndig distribution av nya versioner av dina tjÀnster. För varje ny version mÄste nya tidsserier skapas. Som ett resultat vÀxer antalet tidsserier exponentiellt och vi stÄr inför problemet med ett stort antal tidsserier, vilket kallas högkardinalitet. VictoriaMetrics klarar det framgÄngsrikt jÀmfört med andra tidsseriedatabaser.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LÄt oss ta en nÀrmare titt pÄ hög churn rate. Vad orsakar en hög churn rate i produktionen? Eftersom vissa betydelser av etiketter och taggar förÀndras hela tiden.

Ta till exempel Kubernetes, som har konceptet deployment, det vill sÀga nÀr en ny version av din applikation rullas ut. Av nÄgon anledning bestÀmde sig Kubernetes-utvecklarna för att lÀgga till distributions-id:t pÄ etiketten.

Vad ledde detta till? Dessutom avbryts alla gamla tidsserier med varje ny implementering, och istÀllet för dem börjar nya tidsserier med ett nytt etikettvÀrde deployment_id. Det kan finnas hundratusentals och till och med miljoner sÄdana rader.

Det viktiga med allt detta Àr att det totala antalet tidsserier vÀxer, men antalet tidsserier som för nÀrvarande Àr aktiva och tar emot data förblir konstant. Detta tillstÄnd kallas hög churn rate.

Huvudproblemet med hög churn-hastighet Àr att sÀkerstÀlla en konstant sökhastighet för alla tidsserier för en given uppsÀttning etiketter under ett visst tidsintervall. Vanligtvis Àr detta tidsintervallet för den sista timmen eller den sista dagen.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Hur löser man detta problem? HĂ€r Ă€r det första alternativet. Detta för att dela upp det inverterade indexet i oberoende delar över tiden. Det vill sĂ€ga, ett tidsintervall gĂ„r, vi slutar arbeta med det aktuella inverterade indexet. Och skapa ett nytt inverterat index. Ännu ett tidsintervall gĂ„r, vi skapar en till och en till.

Och vid sampling frÄn dessa inverterade index hittar vi en uppsÀttning inverterade index som faller inom det givna intervallet. Och följaktligen vÀljer vi id för tidsserien dÀrifrÄn.

Detta sparar resurser eftersom vi inte behöver titta pÄ delar som inte faller inom det givna intervallet. Det vill sÀga, vanligtvis, om vi vÀljer data för den senaste timmen, sÄ hoppar vi över förfrÄgningar för tidigare tidsintervall.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Det finns ett annat alternativ för att lösa detta problem. Detta Àr för att lagra en separat lista för varje dag med id för tidsserier som intrÀffade den dagen.

Fördelen med denna lösning gentemot den tidigare lösningen Àr att vi inte duplicerar tidsserieinformation som inte försvinner med tiden. De Àr stÀndigt nÀrvarande och förÀndras inte.

Nackdelen Àr att en sÄdan lösning Àr svÄrare att implementera och svÄrare att felsöka. Och VictoriaMetrics valde denna lösning. SÄ hÀr gick det till historiskt. Denna lösning fungerar ocksÄ bra jÀmfört med den tidigare. Eftersom denna lösning inte implementerades pÄ grund av att det Àr nödvÀndigt att duplicera data i varje partition för tidsserier som inte förÀndras, d.v.s. som inte försvinner med tiden. VictoriaMetrics var i första hand optimerad för diskutrymmesförbrukning, och den tidigare implementeringen gjorde diskutrymmesförbrukningen vÀrre. Men den hÀr implementeringen Àr bÀttre lÀmpad för att minimera diskutrymmesförbrukningen, sÄ den valdes.

Jag var tvungen att slÄss mot henne. Kampen var att i den hÀr implementeringen mÄste du fortfarande vÀlja ett mycket större antal timeseries_ids för data Àn nÀr det inverterade indexet Àr tidspartitionerat.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Hur löste vi detta problem? Vi löste det pÄ ett originellt sÀtt - genom att lagra flera tidsserieidentifierare i varje inverterad indexpost istÀllet för en identifierare. Det vill sÀga vi har en nyckel label=value, som förekommer i varje tidsserie. Och nu sparar vi flera timeseries_ids i en post.

HÀr Àr ett exempel. Tidigare hade vi N poster, men nu har vi en post vars prefix Àr detsamma som alla andra. För den föregÄende posten innehÄller vÀrdet alla tidsserie-ID.

Detta gjorde det möjligt att öka skanningshastigheten för ett sÄdant inverterat index upp till 10 gÄnger. Och det gjorde det möjligt för oss att minska minnesförbrukningen för cachen, för nu lagrar vi strÀngen label=value endast en gÄng i cachen tillsammans N gÄnger. Och den hÀr raden kan bli stor om du lagrar lÄnga rader i dina taggar och etiketter, som Kubernetes gÀrna trycker dit.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Ett annat alternativ för att pÄskynda sökningen pÄ ett inverterat index Àr skÀrning. Skapa flera inverterade index istÀllet för ett och dela data mellan dem med nyckel. Det hÀr Àr ett set key=value Änga. Det vill sÀga att vi fÄr flera oberoende inverterade index, som vi kan frÄga parallellt pÄ flera processorer. Tidigare implementeringar tillÀt endast drift i enprocessorlÀge, d.v.s. skanning av data pÄ endast en kÀrna. Denna lösning lÄter dig skanna data pÄ flera kÀrnor samtidigt, som ClickHouse gillar att göra. Detta Àr vad vi planerar att genomföra.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LÄt oss nu ÄtergÄ till vÄra fÄr - till korsningsfunktionen timeseries_ids. LÄt oss övervÀga vilka implementeringar det kan finnas. Denna funktion lÄter dig hitta timeseries_ids för en given uppsÀttning label=value.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Det första alternativet Àr en naiv implementering. TvÄ kapslade slingor. HÀr fÄr vi funktionen input intersectInts tvÄ skivor - a О b. Vid utgÄngen bör det ÄtervÀnda till oss skÀrningspunkten mellan dessa skivor.

En naiv implementering ser ut sÄ hÀr. Vi itererar över alla vÀrden frÄn slice a, inuti denna loop gÄr vi igenom alla vÀrden för skiva b. Och vi jÀmför dem. Om de matchar, dÄ har vi hittat en korsning. Och spara in den result.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Vilka Àr nackdelarna? Kvadratisk komplexitet Àr dess största nackdel. Till exempel om dina dimensioner Àr skiva a О b en miljon Ät gÄngen, dÄ kommer den hÀr funktionen aldrig att ge dig ett svar. Eftersom det kommer att behöva göra en biljon iterationer, vilket Àr mycket Àven för moderna datorer.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Den andra implementeringen Àr baserad pÄ karta. Vi skapar en karta. Vi lÀgger in alla vÀrden frÄn slice i den hÀr kartan a. Sedan gÄr vi igenom skiva i en separat slinga b. Och vi kontrollerar om detta vÀrde Àr frÄn skiva b i kartan. Om det finns, lÀgg till det i resultatet.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Vad Àr fördelarna? Fördelen Àr att det bara finns linjÀr komplexitet. Det vill sÀga, funktionen kommer att köras mycket snabbare för större skivor. För en miljonstor skiva kommer den hÀr funktionen att köras i 2 miljoner iterationer, i motsats till biljonerna iterationer av den tidigare funktionen.

Nackdelen Àr att den hÀr funktionen krÀver mer minne för att skapa den hÀr kartan.

Den andra nackdelen Àr den stora overheaden för hash. Denna nackdel Àr inte sÀrskilt uppenbar. Och för oss var det inte heller sÀrskilt uppenbart, sÄ till en början i VictoriaMetrics var genomförandet av korsningen genom en karta. Men sedan visade profilering att huvudprocessortiden gÄr Ät till att skriva till kartan och kontrollera om det finns ett vÀrde i denna karta.

Varför slösas CPU-tid pÄ dessa platser? Eftersom Go utför en hashoperation pÄ dessa rader. Det vill sÀga, den berÀknar nyckelns hash för att sedan komma Ät den vid ett givet index i HashMap. HashberÀkningsoperationen slutförs pÄ tiotals nanosekunder. Detta Àr lÄngsamt för VictoriaMetrics.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Jag bestÀmde mig för att implementera en bituppsÀttning optimerad specifikt för det hÀr fallet. SÄ hÀr ser skÀrningspunkten mellan tvÄ skivor ut nu. HÀr skapar vi ett bitset. Vi lÀgger till element frÄn den första skivan till den. Sedan kontrollerar vi nÀrvaron av dessa element i den andra skivan. Och lÀgg till dem i resultatet. Det vill sÀga att det nÀstan inte skiljer sig frÄn det tidigare exemplet. Det enda hÀr Àr att vi har ersatt Ätkomst till kartan med anpassade funktioner add О has.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Vid en första anblick verkar det som att detta borde fungera lÄngsammare, om det tidigare anvÀnts en standardkarta dÀr, och dÄ kallas vissa andra funktioner, men profilering visar att denna sak fungerar 10 gÄnger snabbare Àn standardkartan i fallet med VictoriaMetrics.

Dessutom anvÀnder den mycket mindre minne jÀmfört med kartimplementeringen. Eftersom vi lagrar bitar hÀr istÀllet för ÄttabytevÀrden.

Nackdelen med denna implementering Àr att den inte Àr sÄ uppenbar, inte trivial.

En annan nackdel som mÄnga kanske inte mÀrker Àr att denna implementering kanske inte fungerar bra i vissa fall. Det vill sÀga, den Àr optimerad för ett specifikt fall, för det hÀr fallet med korsningen av VictoriaMetrics tidsserie-ID. Det betyder inte att det Àr lÀmpligt för alla fall. Om den anvÀnds felaktigt fÄr vi ingen prestandaökning, utan ett fel pÄ minnet och en nedgÄng i prestanda.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LÄt oss övervÀga implementeringen av denna struktur. Om du vill titta sÄ finns det i VictoriaMetrics kÀllor, i mappen lib/uint64set. Den Àr optimerad specifikt för VictoriaMetrics-fallet, dÀr timeseries_id Àr ett 64-bitars vÀrde, dÀr de första 32 bitarna Àr i princip konstanta och endast de sista 32 bitarna Àndras.

Denna datastruktur lagras inte pÄ disk, den fungerar bara i minnet.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

HÀr Àr dess API. Det Àr inte sÀrskilt komplicerat. API:et Àr skrÀddarsytt specifikt för ett specifikt exempel pÄ anvÀndning av VictoriaMetrics. Det vill sÀga att det inte finns nÄgra onödiga funktioner hÀr. HÀr Àr de funktioner som uttryckligen anvÀnds av VictoriaMetrics.

Det finns funktioner add, vilket tillför nya vÀrden. Det finns en funktion has, som söker efter nya vÀrden. Och det finns en funktion del, vilket tar bort vÀrden. Det finns en hjÀlpfunktion len, vilket returnerar storleken pÄ uppsÀttningen. Fungera clone klonar mycket. Och funktion appendto konverterar denna uppsÀttning till skiva timeseries_ids.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

SÄ hÀr ser implementeringen av denna datastruktur ut. set har tvÄ element:

  • ItemsCount Ă€r ett hjĂ€lpfĂ€lt för att snabbt returnera antalet element i en uppsĂ€ttning. Det skulle vara möjligt att klara sig utan detta hjĂ€lpfĂ€lt, men det mĂ„ste lĂ€ggas till hĂ€r eftersom VictoriaMetrics ofta frĂ„gar bituppsĂ€ttningslĂ€ngden i sina algoritmer.

  • Det andra fĂ€ltet Ă€r buckets. Detta Ă€r en skiva frĂ„n strukturen bucket32. Varje struktur lagrar hi fĂ€lt. Dessa Ă€r de övre 32 bitarna. Och tvĂ„ skivor - b16his Đž buckets av bucket16 strukturer.

De översta 16 bitarna i den andra delen av 64-bitars strukturen lagras hÀr. Och hÀr lagras bituppsÀttningar för de lÀgre 16 bitarna av varje byte.

Bucket64 bestĂ„r av en array uint64. LĂ€ngden berĂ€knas med dessa konstanter. I ett bucket16 maximalt kan lagras 2^16=65536 bit. Om du delar detta med 8 sĂ„ Ă€r det 8 kilobyte. Om du delar med 8 igen Ă€r det 1000 uint64 menande. Det Ă€r Bucket16 – det hĂ€r Ă€r vĂ„r 8-kilobyte struktur.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

LÄt oss titta pÄ hur en av metoderna i denna struktur för att lÀgga till ett nytt vÀrde implementeras.

Allt börjar med uint64 betydelser. Vi berÀknar de övre 32 bitarna, vi berÀknar de nedre 32 bitarna. LÄt oss gÄ igenom allt buckets. Vi jÀmför de översta 32 bitarna i varje hink med vÀrdet som lÀggs till. Och om de matchar, dÄ kallar vi funktionen add i struktur b32 buckets. Och lÀgg till de lÀgre 32 bitarna dÀr. Och om det ÄtervÀnde true, dÄ betyder det att vi lagt till ett sÄdant vÀrde dÀr och att vi inte hade ett sÄdant vÀrde. Om den kommer tillbaka false, dÄ fanns redan en sÄdan innebörd. Sedan ökar vi antalet element i strukturen.

Om vi ​​inte har hittat den du behöver bucket med önskat hi-vĂ€rde, dĂ„ anropar vi funktionen addAlloc, som kommer att producera en ny bucket, lĂ€gga till den i hinkstrukturen.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Detta Àr implementeringen av funktionen b32.add. Det liknar den tidigare implementeringen. Vi berÀknar de mest signifikanta 16 bitarna, de minst signifikanta 16 bitarna.

Sedan gÄr vi igenom alla de övre 16 bitarna. Vi hittar matcher. Och om det finns en matchning kallar vi add-metoden, som vi kommer att övervÀga pÄ nÀsta sida för bucket16.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Och hÀr Àr den lÀgsta nivÄn, som bör optimeras sÄ mycket som möjligt. Vi rÀknar för uint64 id-vÀrde i skivbit och Àven bitmask. Detta Àr en mask för ett givet 64-bitars vÀrde, som kan anvÀndas för att kontrollera nÀrvaron av denna bit, eller stÀlla in den. Vi kontrollerar om den hÀr biten Àr instÀlld och stÀller in den, och ÄtergÄr nÀrvaro. Detta Àr vÄr implementering, som gjorde det möjligt för oss att pÄskynda driften av korsande id för tidsserier med 10 gÄnger jÀmfört med konventionella kartor.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Utöver denna optimering har VictoriaMetrics mÄnga andra optimeringar. De flesta av dessa optimeringar lades till av en anledning, men efter profilering av koden i produktionen.

Detta Àr huvudregeln för optimering - lÀgg inte till optimering förutsatt att det kommer att finnas en flaskhals hÀr, eftersom det kan visa sig att det inte kommer att finnas en flaskhals dÀr. Optimering försÀmrar vanligtvis kodens kvalitet. DÀrför Àr det vÀrt att optimera först efter profilering och helst i produktion, sÄ att detta Àr riktiga data. Om nÄgon Àr intresserad kan du titta pÄ VictoriaMetrics kÀllkod och utforska andra optimeringar som finns dÀr.

GĂ„ till optimeringar i VictoriaMetrics. Alexander Valyalkin

Jag har en frÄga om bitset. Mycket lik C++ vektorboolimplementeringen, optimerad bituppsÀttning. Tog du implementeringen dÀrifrÄn?

Nej, inte dÀrifrÄn. NÀr jag implementerade denna bituppsÀttning vÀgleddes jag av kunskap om strukturen för dessa ids-tidsserier, som anvÀnds i VictoriaMetrics. Och deras struktur Àr sÄdan att de övre 32 bitarna Àr i princip konstanta. De lÀgre 32 bitarna kan Àndras. Ju lÀgre bit, desto oftare kan det Àndras. DÀrför Àr denna implementering specifikt optimerad för denna datastruktur. C++-implementeringen, sÄ vitt jag vet, Àr optimerad för det allmÀnna fallet. Om man optimerar för det generella fallet betyder det att det inte blir det mest optimala för ett specifikt fall.

Jag rÄder dig ocksÄ att titta pÄ rapporten frÄn Alexey Milovid. För ungefÀr en mÄnad sedan pratade han om optimering i ClickHouse för specifika specialiseringar. Han sÀger bara att i det allmÀnna fallet Àr en C++-implementering eller nÄgon annan implementering skrÀddarsydd för att fungera bra i genomsnitt pÄ ett sjukhus. Det kan fungera sÀmre Àn en kunskapsspecifik implementering som vÄr, dÀr vi vet att de översta 32 bitarna Àr mestadels konstanta.

Jag har en andra frÄga. Vad Àr den grundlÀggande skillnaden frÄn InfluxDB?

Det finns mÄnga grundlÀggande skillnader. Sett till prestanda och minnesförbrukning visar InfluxDB i tester 10 gÄnger mer minnesförbrukning för tidsserier med hög kardinalitet, nÀr man har mÄnga av dem, till exempel miljoner. Till exempel förbrukar VictoriaMetrics 1 GB per miljon aktiva rader, medan InfluxDB förbrukar 10 GB. Och det Àr en stor skillnad.

Den andra grundlÀggande skillnaden Àr att InfluxDB har konstiga frÄgesprÄk - Flux och InfluxQL. De Àr inte sÀrskilt bekvÀma att arbeta med tidsserier jÀmfört med PromQL, som stöds av VictoriaMetrics. PromQL Àr ett frÄgesprÄk frÄn Prometheus.

Och ytterligare en skillnad Àr att InfluxDB har en lite konstig datamodell, dÀr varje rad kan lagra flera fÀlt med olika taggar. Dessa rader Àr vidare uppdelade i olika tabeller. Dessa ytterligare komplikationer komplicerar efterföljande arbete med denna databas. Det Àr svÄrt att stödja och förstÄ.

I VictoriaMetrics Ă€r allt mycket enklare. DĂ€r Ă€r varje tidsserie ett nyckel-vĂ€rde. VĂ€rdet Ă€r en uppsĂ€ttning poĂ€ng - (timestamp, value), och nyckeln Ă€r setet label=value. Det finns ingen Ă„tskillnad mellan fĂ€lt och mĂ„tt. Det lĂ„ter dig vĂ€lja vilken data som helst och sedan kombinera, addera, subtrahera, multiplicera, dividera, till skillnad frĂ„n InfluxDB dĂ€r berĂ€kningar mellan olika rader fortfarande inte Ă€r implementerade sĂ„ vitt jag vet. Även om de Ă€r implementerade Ă€r det svĂ„rt, man mĂ„ste skriva mycket kod.

Jag har en klargörande frÄga. Förstod jag rÀtt att det var nÄgot slags problem som du pratade om, att detta inverterade index inte passar in i minnet, sÄ det finns partitionering dÀr?

Först visade jag en naiv implementering av ett inverterat index pÄ en standard Go-karta. Denna implementering Àr inte lÀmplig för databaser eftersom detta inverterade index inte sparas pÄ disk, och databasen mÄste spara pÄ disk sÄ att denna data förblir tillgÀnglig vid omstart. I den hÀr implementeringen, nÀr du startar om programmet, kommer ditt inverterade index att försvinna. Och du kommer att förlora tillgÄngen till all data eftersom du inte kommer att kunna hitta den.

HallÄ! Tack för rapporten! Jag heter Pavel. Jag kommer frÄn Wildberries. Jag har nÄgra frÄgor till dig. FrÄga ett. Tror du att om du hade valt en annan princip nÀr du byggde arkitekturen för din applikation och partitionerat data över tid, sÄ kanske du skulle ha kunnat skÀra data vid sökning, bara baserat pÄ det faktum att en partition innehÄller data för en tidsperiod , det vill sÀga i ett tidsintervall och du behöver inte oroa dig för att dina pjÀser Àr olika utspridda? FrÄga nummer 2 - eftersom du implementerar en liknande algoritm med bitset och allt annat, kanske du försökte anvÀnda processorinstruktioner? Kanske har du provat sÄdana optimeringar?

Jag svarar pÄ den andra direkt. Vi har inte kommit dit Àn. Men om det behövs kommer vi dit. Och den första, vad var frÄgan?

Du diskuterade tvÄ scenarier. Och de sa att de valde den andra med en mer komplex implementering. Och de föredrog inte den första, dÀr data Àr uppdelad efter tid.

Ja. I det första fallet skulle den totala volymen av indexet vara större, eftersom vi i varje partition skulle behöva lagra dubblettdata för de tidsserier som fortsÀtter genom alla dessa partitioner. Och om din tidsserieavgÄngshastighet Àr liten, dvs samma serie anvÀnds stÀndigt, sÄ skulle vi i det första fallet förlora mycket mer i mÀngden diskutrymme som upptas jÀmfört med det andra fallet.

Och sÄ - ja, tidspartitionering Àr ett bra alternativ. Prometheus anvÀnder det. Men Prometheus har en annan nackdel. NÀr du slÄr samman dessa databitar mÄste den lagra metainformation för alla etiketter och tidsserier i minnet. DÀrför, om databitarna som den sammanfogar Àr stora, ökar minnesförbrukningen vÀldigt mycket under sammanslagning, till skillnad frÄn VictoriaMetrics. Vid sammanslagning förbrukar VictoriaMetrics inte minne alls, endast ett par kilobyte förbrukas, oavsett storleken pÄ de sammanslagna databitarna.

Algoritmen du anvÀnder anvÀnder minne. Den markerar tidsserietaggar som innehÄller vÀrden. Och pÄ detta sÀtt kontrollerar du om det finns parad nÀrvaro i en datamatris och i en annan. Och du förstÄr om korsning intrÀffade eller inte. Vanligtvis implementerar databaser markörer och iteratorer som lagrar deras nuvarande innehÄll och kör igenom de sorterade data pÄ grund av den enkla komplexiteten i dessa operationer.

Varför anvÀnder vi inte markörer för att gÄ igenom data?

Ja.

Vi lagrar sorterade rader i LevelDB eller mergeset. Vi kan flytta markören och hitta korsningen. Varför anvÀnder vi det inte? För det gÄr lÄngsamt. Eftersom markörer betyder att du mÄste anropa en funktion för varje rad. Ett funktionsanrop Àr 5 nanosekunder. Och om du har 100 000 000 rader, sÄ visar det sig att vi lÀgger en halv sekund pÄ att bara anropa funktionen.

Det finns en sÄdan sak, ja. Och min sista frÄga. FrÄgan lÄter kanske lite konstig. Varför Àr det inte möjligt att lÀsa alla nödvÀndiga aggregat i det ögonblick dÄ data anlÀnder och spara dem i den form som krÀvs? Varför spara stora volymer i vissa system som VictoriaMetrics, ClickHouse, etc., och sedan spendera mycket tid pÄ dem?

Jag ska ge ett exempel för att göra det tydligare. LÄt oss sÀga hur fungerar en liten leksakshastighetsmÀtare? Den registrerar strÀckan du har tillryggalagt, hela tiden lÀgger den till ett vÀrde, och den andra - gÄngen. Och delar. Och fÄr medelhastighet. Du kan göra ungefÀr samma sak. LÀgg ihop alla nödvÀndiga fakta i farten.

Okej, jag förstÄr frÄgan. Ditt exempel har sin plats. Om du vet vilka aggregat du behöver Àr detta den bÀsta implementeringen. Men problemet Àr att mÀnniskor sparar dessa mÀtvÀrden, en del data i ClickHouse och de vet Ànnu inte hur de kommer att samlas och filtrera dem i framtiden, sÄ de mÄste spara all rÄdata. Men om du vet att du behöver berÀkna nÄgot i genomsnitt, varför inte berÀkna det istÀllet för att lagra ett gÀng rÄvÀrden dÀr? Men detta Àr bara om du vet exakt vad du behöver.

Förresten, databaser för lagring av tidsserier stödjer rÀkning av aggregat. Prometheus stödjer till exempel inspelningsregler. Det vill sÀga att detta kan göras om du vet vilka enheter du behöver. VictoriaMetrics har inte detta Ànnu, men det föregÄs vanligtvis av Prometheus, dÀr detta kan göras i omkodningsreglerna.

Till exempel, i mitt tidigare jobb behövde jag rÀkna antalet hÀndelser i ett glidande fönster under den senaste timmen. Problemet Àr att jag var tvungen att göra en anpassad implementering i Go, det vill sÀga en tjÀnst för att rÀkna den hÀr saken. Denna tjÀnst var i slutÀndan icke-trivial, eftersom den Àr svÄr att berÀkna. Implementeringen kan vara enkel om du behöver rÀkna nÄgra aggregat med fasta tidsintervall. Om du vill rÀkna hÀndelser i ett glidande fönster, sÄ Àr det inte sÄ enkelt som det verkar. Jag tror att detta Ànnu inte har implementerats i ClickHouse eller i tidsseriedatabaser, eftersom det Àr svÄrt att implementera.

Och en frĂ„ga till. Vi pratade bara om medelvĂ€rde, och jag kom ihĂ„g att det en gĂ„ng fanns nĂ„got sĂ„dant som Graphite med en Carbon-backend. Och han visste hur man tunnade ut gammal data, det vill sĂ€ga lĂ€mna en poĂ€ng per minut, en poĂ€ng per timme, etc. I princip Ă€r detta ganska bekvĂ€mt om vi behöver rĂ„data, relativt sett, för en mĂ„nad, och allt annat kan tunnas ut. Men Prometheus och VictoriaMetrics stöder inte den hĂ€r funktionen. Är det planerat att stödja det? Om inte, varför inte?

Tack för frÄgan. VÄra anvÀndare stÀller denna frÄga med jÀmna mellanrum. De frÄgar nÀr vi kommer att lÀgga till stöd för nedsampling. Det finns flera problem hÀr. För det första förstÄr varje anvÀndare downsampling nÄgot annat: nÄgon vill fÄ vilken godtycklig punkt som helst pÄ ett givet intervall, nÄgon vill ha maximala, lÀgsta, medelvÀrden. Om mÄnga system skriver data till din databas kan du inte klumpa ihop allt. Det kan vara sÄ att varje system krÀver olika gallring. Och detta Àr svÄrt att genomföra.

Och det andra Ă€r att VictoriaMetrics, precis som ClickHouse, Ă€r optimerat för att arbeta med stora mĂ€ngder rĂ„data, sĂ„ det kan skyffla en miljard rader pĂ„ mindre Ă€n en sekund om du har mĂ„nga kĂ€rnor i ditt system. Skanna tidsseriepunkter i VictoriaMetrics – 50 000 000 poĂ€ng per sekund per kĂ€rna. Och denna prestanda skalar till befintliga kĂ€rnor. Det vill sĂ€ga, om du till exempel har 20 kĂ€rnor kommer du att skanna en miljard poĂ€ng per sekund. Och denna egenskap hos VictoriaMetrics och ClickHouse minskar behovet av nedsamling.

En annan funktion Àr att VictoriaMetrics effektivt komprimerar denna data. Kompression i genomsnitt i produktionen Àr frÄn 0,4 till 0,8 byte per punkt. Varje punkt Àr en tidsstÀmpel + vÀrde. Och den komprimeras till mindre Àn en byte i genomsnitt.

Sergey. Jag har en frÄga. Vad Àr det minsta kvantumet för inspelningstid?

En millisekund. Vi hade nyligen ett samtal med andra tidsseriedatabasutvecklare. Deras minsta tidsintervall Àr en sekund. Och i Graphite, till exempel, Àr det ocksÄ en sekund. I OpenTSDB Àr det ocksÄ en sekund. InfluxDB har nanosekundsprecision. I VictoriaMetrics Àr det en millisekund, för i Prometheus Àr det en millisekund. Och VictoriaMetrics utvecklades ursprungligen som fjÀrrlagring för Prometheus. Men nu kan den spara data frÄn andra system.

Personen jag pratade med sÀger att de har andra till sekunds noggrannhet - det rÀcker för dem eftersom det beror pÄ vilken typ av data som lagras i tidsseriedatabasen. Om det hÀr Àr DevOps-data eller data frÄn infrastruktur, dÀr du samlar in det med intervaller pÄ 30 sekunder, per minut, sÄ rÀcker det med andras noggrannhet, du behöver inget mindre. Och om du samlar in dessa data frÄn högfrekventa handelssystem, behöver du nanosekundsnoggrannhet.

Millisekundens noggrannhet i VictoriaMetrics Àr ocksÄ lÀmplig för DevOps-fallet, och kan vara lÀmplig för de flesta fall som jag nÀmnde i början av rapporten. Det enda som det kanske inte Àr lÀmpligt för Àr högfrekventa handelssystem.

Tack! Och en annan frÄga. Vad Àr kompatibilitet i PromQL?

Full bakÄtkompatibilitet. VictoriaMetrics stöder fullt ut PromQL. Dessutom lÀgger den till ytterligare avancerad funktionalitet i PromQL, som kallas MetricsQL. Det pratas pÄ YouTube om denna utökade funktionalitet. Jag talade pÄ Monitoring Meetup i vÄras i St. Petersburg.

Telegram kanal VictoriaMetrics.

Endast registrerade anvÀndare kan delta i undersökningen. Logga in, SnÀlla du.

Vad hindrar dig frÄn att byta till VictoriaMetrics som din lÄngtidslagring för Prometheus? (Skriv i kommentarerna, jag lÀgger till det i omröstningen))

  • 71,4%Jag anvĂ€nder inte Prometheus5

  • 28,6%Visste inte om VictoriaMetrics2

7 anvÀndare röstade. 12 anvÀndare avstod frÄn att rösta.

KĂ€lla: will.com

LĂ€gg en kommentar