{"id":80733,"date":"2020-05-08T13:42:31","date_gmt":"2020-05-08T11:42:31","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/go-optimizations-in-victoriametrics-aleksandr-valyalkin"},"modified":"2020-05-08T13:42:31","modified_gmt":"2020-05-08T11:42:31","slug":"go-optimizations-in-victoriametrics-aleksandr-valyalkin","status":"publish","type":"post","link":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/go-optimizations-in-victoriametrics-aleksandr-valyalkin","title":{"rendered":"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Pakun tutvuda 2019. aasta l\u00f5pu aruande t\u00f5lgendusega, mille autoriks on Aleksandr Valjalkin \"Go optimizations in VictoriaMetrics\"<\/strong><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/victoriametrics.com\/\">VictoriaMetrics<\/a><\/noindex> \u2014 kiire ja skaleeritav andmebaasi haldus\u00fcsteem, mis on m\u00f5eldud ajarealiste andmete salvestamiseks ja t\u00f6\u00f6tlemiseks (salvestus moodustab aja ja vastavad sellele ajale v\u00e4\u00e4rtuste kogumi, n\u00e4iteks anduritelt saadud perioodiliselt m\u00f5\u00f5detud olekute v\u00f5i meetrite kogumise kaudu).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/dd13ec10594aeb138be29ce439cc476a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Siin on link selle raporti videole \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/MZ5P21j_HLE\">https:\/\/youtu.be\/MZ5P21j_HLE<\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.google.com\/presentation\/d\/1k7OjHvxTHA7669MFwsNTCx8hII-a8lNvpmQetLxmrEU\/edit?usp=sharing\">Slaidid<\/a><\/noindex><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/0073390d6dbcc6ab3e5305907ac6a229.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>R\u00e4\u00e4gin natuke endast. Olen Aleksandr Valjalkin. Siin on <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/valyala\">minu GitHub konto<\/a><\/noindex>. Mind huvitab Go ja j\u00f5udluse optimeerimine. Olen kirjutanud palju kasulikke ja v\u00e4hem pruugi raamatukogusid. Need algavad kas <code>fast<\/code>, v\u00f5i <code>quick<\/code> eesliidelt. <\/p>\n<p><\/p>\n<p>Hetkel t\u00f6\u00f6tan VictoriaMetrics'i kallal. Mis see on ja mida ma seal teen? R\u00e4\u00e4gin sellest presentatsioonis. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/c9194bc3fee1f615d838979bec12f7d0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Raporti \u00fclevaade on j\u00e4rgmine:<\/p>\n<p><\/p>\n<ul>\n<li>Alustuseks r\u00e4\u00e4gin, mis on VictoriaMetrics. <\/li>\n<li>Seej\u00e4rel selgitan, mis on ajaread. <\/li>\n<li>K seej\u00e4rel r\u00e4\u00e4gin, kuidas ajarealiste andmete andmebaas t\u00f6\u00f6tab.<\/li>\n<li>Edasi r\u00e4\u00e4gin andmebaasi arhitektuurist: millest see koosneb.<\/li>\n<li>Ja seej\u00e4rel liigume edasi optimeerimistele, mis on olemas VictoriaMetrics'is. Need on p\u00f6\u00f6ratud indeksi optimeerimine ja bitset-realisatsiooni optimeerimine Go-s.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/3e0244b6b6fe952f660e4a094778921a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kas keegi teab, mis on VictoriaMetrics? Oh, juba paljud inimesed teavad. See on hea uudis. Neile, kes ei tea \u2013 see on ajarealiste andmete andmebaas. See p\u00f5hineb ClickHouse arhitektuuril, teatud ClickHouse'i rakenduse detailidel. N\u00e4iteks nagu: MergeTree, paralleelsed arvutused k\u00f5igil saadaval olevatel protsessorikasutajatel ja j\u00f5udluse optimeerimine t\u00f6\u00f6tamata andmeblokkide osas, mis paigutatakse protsessorikapslisse. <\/p>\n<p><\/p>\n<p>VictoriaMetrics pakub paremat andmete tihendamist v\u00f5rreldes teiste ajarealiste andmete andmebaasidega. <\/p>\n<p><\/p>\n<p>See skaleerub vertikaalselt \u2014 st v\u00f5ite lisada rohkem protsessoreid, rohkem RAM-i \u00fchte arvutisse. VictoriaMetrics suudab t\u00f5husalt kasutada neid ressursse ja kasvatada lineaarselt j\u00f5udlust.<\/p>\n<p><\/p>\n<p>Samuti skaleerub VictoriaMetrics horisontaalselt \u2014 st v\u00f5ite lisada t\u00e4iendavaid s\u00f5lmi VictoriaMetrics'i klastrisse ning selle j\u00f5udlus suureneb peaaegu lineaarselt.<\/p>\n<p><\/p>\n<p>Kuidas arvata v\u00f5isite, VictoriaMetrics on kiire andmebaas, sest ma ei oska kirjutada muid. Ja see on kirjutatud Go-s, seet\u00f5ttu r\u00e4\u00e4gin ma sellest kohtumisel.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/0121c9baead722eb1fe22fb6f900d4ad.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kes teab, mis on ajaread? Ka paljusid inimesi teab. Ajaread on paaride seeria <code>(timestamp, v\u00e4\u00e4rtus)<\/code>, kus paarid on j\u00e4rjestatud aja j\u00e4rgi. V\u00e4\u00e4rtus on ujuv-punktiga number \u2013 float64.<\/p>\n<p><\/p>\n<p>Iga ajareale tuvastatakse ainulaadne v\u00f5ti. Mis see v\u00f5ti sisaldab? See koosneb mitte-t\u00fchjast v\u00f5tme-v\u00e4\u00e4rtuse paaride kogumist. <\/p>\n<p><\/p>\n<p>Siin on n\u00e4ide ajareast. Selle rea v\u00f5tmena on paaride nimekiri: <code>__name__=\"cpu_usage\"<\/code> \u2013 see on m\u00f5\u00f5diku nimi, <code>instance=\"my-server\"<\/code> \u2014 see on arvuti, kus see m\u00f5\u00f5dik on kogutud, <code>datacenter=\"us-east\"<\/code> \u2014 see on andmekeskus, kus see arvuti asub.<\/p>\n<p><\/p>\n<p>Meil on ajareanimi, mis koosneb kolmest v\u00f5tme-v\u00e4\u00e4rtuse paarist. Sellele v\u00f5tmele vastab paaride nimekiri <code>(timestamp, value)<\/code>. <code>t1, t3, t3, ..., tN<\/code> \u2014 need on ajam\u00e4rgid, <code>10, 20, 12, ..., 15<\/code> \u2014 vastavad v\u00e4\u00e4rtused. See on cpu-kasutus antud ajahetkel selle rea jaoks.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/76cab9db0263318d355ac607ceb7e0f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kus v\u00f5ivad ajaread olla kasulikud? Kas kellelgi on ideid? <\/p>\n<p><\/p>\n<ul>\n<li>DevOps-is saab m\u00f5\u00f5ta CPU, RAM, v\u00f5rgu, rps, vigade arvu jne koormust. <\/li>\n<li>IoT \u2013 saame m\u00f5\u00f5ta temperatuuri, r\u00f5hku, geo-kordinaate ja veel midagi.<\/li>\n<li>Samuti rahanduses \u2013 saame j\u00e4lgida aktsiate ja valuutade hindu. <\/li>\n<li>Lisaks sellele v\u00f5ivad ajaread olla kasulikud t\u00f6\u00f6tlemisprotsesside j\u00e4lgimiseks tehasetes. Meil on kasutajaid, kes kasutavad VictoriaMetrics tuulegeneraatorite ja robotite j\u00e4lgimiseks.<\/li>\n<li>Ajaread on ka kasulikud teatud seadmete andurite info kogumiseks. N\u00e4iteks mootori jaoks; rehvide r\u00f5hu m\u00f5\u00f5tmiseks; kiirus, kaugus; k\u00fctusekulu m\u00f5\u00f5tmiseks jne.<\/li>\n<li>Ajaread v\u00f5ivad samuti olla kasulikud lennukite j\u00e4lgimiseks. Igas lennukis on must kast, mis kogub ajareade erinevate lennuki tervise parameetrite kohta. Ajaread on samuti kasutusel lennundust\u00f6\u00f6stuses. <\/li>\n<li>Tervishoid \u2013 see on verer\u00f5hk, pulss jne.<\/li>\n<\/ul>\n<p><\/p>\n<p>V\u00f5ib-olla on veel rakendusi, millest ma unustasin, kuid loodan, et te m\u00f5istate, et ajaread on kaasaegses maailmas aktiivselt kasutusel. Ja nende kasutamine suureneb iga aastaga.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/f1da29d372163751268b6a8f86836d04.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Miks on ajareadeks vajalik andmebaas? Miks ei saa ajareadeks kasutada tavalist relatsioonilist andmebaasi?<\/p>\n<p><\/p>\n<p>Kuna ajajoonetes on tavaliselt suur hulk teavet, mille s\u00e4ilitamine ja t\u00f6\u00f6tlemine tavap\u00e4rastes andmebaasides on keeruline. Seet\u00f5ttu on v\u00e4lja t\u00f6\u00f6tatud spetsialiseeritud ajajoonte andmebaasid. Need andmebaasid s\u00e4ilitavad punkte t\u00f5husalt, <code>(timestamp, value)<\/code> antud v\u00f5tme p\u00f5hjal. Nad pakuvad API-d salvestatud andmete lugemiseks v\u00f5tme j\u00e4rgi, kas \u00fche v\u00f5tme-v\u00e4\u00e4rtuse paari, mitme sellise paari v\u00f5i regexp j\u00e4rgi. N\u00e4iteks, kui soovite leida k\u00f5igi oma teenuste CPU koormuse andmed Ameerika andmekeskuses, peate kasutama sellist pseudo-p\u00e4ringut.<\/p>\n<p><\/p>\n<p>Tavaliselt esindavad ajajoonte andmebaasid spetsialiseeritud p\u00e4ringute keeli, kuna SQL ei sobi ajajoonte jaoks v\u00e4ga h\u00e4sti. Kuigi on andmebaase, mis toetavad SQL-i, ei ole see siiski eriti sobiv. Rohkem sobivad sellised p\u00e4ringu keeled nagu <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/@valyala\/promql-tutorial-for-beginners-9ab455142085\">PromQL<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.influxdata.com\/influxdb\/v1.8\/query_language\/spec\/\">InfluxQL<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.influxdata.com\/products\/flux\/\">Flux<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/code.kx.com\/q\/\">Q<\/a><\/noindex>. Loodan, et keegi on neist keeltest v\u00e4hemalt midagi kuulnud. O PromQL on ilmselt paljud kuulnud. See on Prometheuse p\u00e4ringu keel.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/59e5b6d82a2f7861077bc5fe34519ee4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nii n\u00e4eb v\u00e4lja kaasaegse ajajoonte andmebaasi arhitektuur VictoriaMetrics'i n\u00e4itel.<\/p>\n<p><\/p>\n<p>See koosneb kahest osast. Need on p\u00f6\u00f6rdindeksi salvestus ja ajajoonte v\u00e4\u00e4rtuste salvestus. Need salvestused on eraldatud. <\/p>\n<p><\/p>\n<p>Kui andmebaasi tuleb uus kirje, p\u00f6\u00f6rdume k\u00f5igepealt p\u00f6\u00f6rdindeksi poole, et leida ajajoonte identifikaator antud m\u00e4\u00e4ratud kogumi <code>label=value<\/code> selle m\u00f5\u00f5tiku jaoks. Leiame selle identifikaatori ja salvestame v\u00e4\u00e4rtuse andmesalvestusse.<\/p>\n<p><\/p>\n<p>Kui tuleb p\u00e4ring andmete valimiseks TSDB-st, vaatame k\u00f5igepealt p\u00f6\u00f6rdindeksi. Saame k\u00f5ik <code>timeseries_ids<\/code> kirjed, mis vastavad antud m\u00e4\u00e4ratud kogule. <code>label=value<\/code>Ja seej\u00e4rel saame k\u00f5ik vajalikud andmed andmesalvestusest, mille on indekseeritud <code>timeseries_ids<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/eb9b36fa3c6de2188b97b56ad3839b2c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vaadakem n\u00e4idet, kuidas ajajoonte andmebaas t\u00f6\u00f6tleb sisenevat select-p\u00e4ringut.<\/p>\n<p><\/p>\n<ul>\n<li>Esimese asjana saab ta k\u00f5ik <code>timeseries_ids<\/code> p\u00f6\u00f6rdindeksist, mis sisaldavad m\u00e4\u00e4ratud paare <code>label=value<\/code>, v\u00f5i vastavad m\u00e4\u00e4ratud regulaaravaldisele.<\/li>\n<li>Seej\u00e4rel saadab ta k\u00f5ik andmepunktid andmesalvestusest antud ajavahemikus leidudest <code>timeseries_ids<\/code>.<\/li>\n<li>P\u00e4rast seda teeb andmebaas kasutaja p\u00e4ringu j\u00e4rgi nende andmepunktide p\u00f5hjal arvutusi. Ja seej\u00e4rel tagastab vastuse.<\/li>\n<\/ul>\n<p><\/p>\n<p>Selles esitluses r\u00e4\u00e4gin ma teile esimesest osast. See on otsimine <code>timeseries_ids<\/code> p\u00f6\u00f6ratud indeksis. Teise ja kolmanda osa v\u00f5ite hiljem vaadata <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/VictoriaMetrics\/VictoriaMetrics\">VictoriaMetricsi l\u00e4htekoodid<\/a><\/noindex>, v\u00f5i oodata, kuni ma valmistan ette teisi ettekandeid \ud83d\ude42<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/3a7dab707dd1defb9bc674a342052a03.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Alustame p\u00f6\u00f6ratud indeksist. Paljudele v\u00f5ib tunduda, et see on lihtne. Kes teab, mis on p\u00f6\u00f6ratud indeks ja kuidas see t\u00f6\u00f6tab? Oh, inimesi, kes teavad, ei olegi nii palju. Proovime m\u00f5ista, mis see on. <\/p>\n<p><\/p>\n<p>Tegelikult on k\u00f5ik lihtne. See on lihtsalt s\u00f5nastik, mis seob v\u00f5tme v\u00e4\u00e4rtusega. Mis on v\u00f5ti? See paar <code>label=value<\/code>, kus <code>label<\/code> ja <code>value<\/code> on stringid. Ja v\u00e4\u00e4rtused \u2013 on kogum <code>timeseries_ids<\/code>, kuhu kuulub antud paar <code>label=value<\/code>.<\/p>\n<p><\/p>\n<p>P\u00f6\u00f6ratud indeks v\u00f5imaldab kiiresti leida k\u00f5ik <code>timeseries_ids<\/code>, millel on antud <code>label=value<\/code>.<\/p>\n<p><\/p>\n<p>Samuti v\u00f5imaldab see kiiresti leida <code>timeseries_ids<\/code> aja rea jaoks mitme paari <code>label=value<\/code>, v\u00f5i paaride jaoks <code>label=regexp<\/code>. Kuidas see toimub? T\u00f5mbamise kaudu hulkade \u00fchisosa <code>timeseries_ids<\/code> iga paari jaoks <code>label=value<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/837a15a078e8c9422c721f3f072c0c09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vaadakem erinevaid p\u00f6\u00f6ratud indeksi teostusi. Alustame k\u00f5ige lihtsama naiivse teostusega. See n\u00e4eb v\u00e4lja selline. <\/p>\n<p><\/p>\n<p>Funktsioon <code>getMetricIDs<\/code> saab loendi stringidest. Iga string sisaldab <code>label=value<\/code>. See funktsioon tagastab loendi <code>metricIDs<\/code>.<\/p>\n<p><\/p>\n<p>Kuidas see t\u00f6\u00f6tab? Siin on meil globaalne muutuja, mis nimetatakse <code>invertedIndex<\/code>. See on tavaline s\u00f5nastik (<code>map<\/code>), mis seondab stringi int slice'iga. String sisaldab <code>label=value<\/code>.<\/p>\n<p><\/p>\n<p>Funktsiooni teostamine: saame <code>metricIDs<\/code> esimese jaoks <code>label=value<\/code>, seej\u00e4rel k\u00e4ime \u00fcle k\u00f5ikide teiste <code>label=value<\/code>, saame <code>metricIDs<\/code> nende jaoks. Ja kutsume v\u00e4lja funktsiooni <code>intersectInts<\/code>, millest r\u00e4\u00e4gitakse j\u00e4rgmises osas. See funktsioon tagastab nende loendite \u00fchisosa.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/709beca79884a9693098781974c26f4d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kuidas n\u00e4ete, p\u00f6\u00f6ratud indeksi teostamine ei ole v\u00e4ga keeruline. Kuid see on naivne teostus. Millised on selle puudused? Peamine puudus naiivses teostuses on see, et selline p\u00f6\u00f6ratud indeks hoitakse meie m\u00e4lus. P\u00e4rast rakenduse taask\u00e4ivitamist kaotame selle indeksi. Ei ole indeksi salvestamist kettale. Andmebaasi jaoks ei sobi selline p\u00f6\u00f6ratud indeks t\u00f5en\u00e4oliselt.<\/p>\n<p><\/p>\n<p>Teine puudus on samuti seotud m\u00e4luga. P\u00f6\u00f6ratud indeks peab mahtuma operatiivm\u00e4lu. Kui see \u00fcletab operatiivm\u00e4lu suuruse, siis on ilmne, et saame \u2013 out of memory error. Ja programm ei t\u00f6\u00f6ta.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/495394168ac03aa8cbcf56ccad1cb2b8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Seda probleemi saab lahendada valmis lahendustega, nagu <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/google\/leveldb\">LevelDB<\/a><\/noindex>, v\u00f5i <noindex><a rel=\"nofollow\" href=\"https:\/\/rocksdb.org\/\">RocksDB<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>L\u00fchidalt \u00f6eldes, vajame andmebaasi, mis v\u00f5imaldab kiiresti teha kolme toimingut. <\/p>\n<p><\/p>\n<ul>\n<li>Esimene toiming on salvestamine <code>v\u00f5tme-v\u00e4\u00e4rtuse paar<\/code> sellesse andmebaasi. Seda teeb ta v\u00e4ga kiiresti, kus <code>v\u00f5tme-v\u00e4\u00e4rtuse paar<\/code> - need on v\u00f5ivad olla suvalised stringid. <\/li>\n<li>Teine toiming on kiire v\u00e4\u00e4rtuse otsimine antud v\u00f5tme alusel.<\/li>\n<li>Ja kolmas toiming on kiire k\u00f5igi v\u00e4\u00e4rtuste leidmine antud prefiksi alusel. <\/li>\n<\/ul>\n<p><\/p>\n<p>LevelDB ja RocksDB \u2013 need andmebaasid on v\u00e4lja t\u00f6\u00f6tatud Google'is ja Facebookis. Esiteks ilmus LevelDB. Siis v\u00f5tsid Facebooki inimesed LevelDB ja hakkasid seda t\u00e4iustama, luues RocksDB. Praegu t\u00f6\u00f6tab Facebooki sees peaaegu k\u00f5ikides andmebaasides RocksDB, sealhulgas nad on sellel \u00fcle viinud ka MySQL-i. Nad nimetasid seda <noindex><a rel=\"nofollow\" href=\"http:\/\/myrocks.io\/\">MyRocks<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>P\u00f6\u00f6ratud indeksi saab rakendada LevelDB abil. Kuidas seda teha? Me salvestame v\u00f5tmena <code>label=value<\/code>. Ja v\u00e4\u00e4rtusena \u2013 ajaseeria identifikaatori, kus see paar esineb. <code>label=value<\/code>.<\/p>\n<p><\/p>\n<p>Kui meil on palju ajaseeriaid selle paariga <code>label=value<\/code>, siis on sellel andmebaasis palju ridu sama v\u00f5tme ja erinevatega. <code>timeseries_ids<\/code>Selleks, et saada nimekiri k\u00f5igist <code>timeseries_ids<\/code>, mis algavad antud <code>label=prefix<\/code>, teeme ulatusliku skaneerimise, mille jaoks antud andmebaas on optimeeritud. Ehk valime k\u00f5ik read, mis algavad <code>label=prefix<\/code> ja saame vajalikud <code>timeseries_ids<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/a40877ecb758ac3bc1979bcd568d7e83.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Siin on umbkaudne teostus, kuidas see Go-s v\u00e4lja n\u00e4eks. Meil on p\u00f6\u00f6ratud indeks. See on LevelDB.<\/p>\n<p><\/p>\n<p>Funktsioon on sama, mis naiivses teostuses. See kordab peaaegu rida-realt naiivset teostust. Ainus moment on see, et tavalise <code>map<\/code> asemel p\u00f6\u00f6rdume p\u00f6\u00f6ratud indeksisse. Saame k\u00f5ik v\u00e4\u00e4rtused esimese jaoks <code>label=value<\/code>. Siis k\u00e4ime l\u00e4bi k\u00f5ik \u00fclej\u00e4\u00e4nud paarid <code>label=value<\/code> ja saame nende jaoks vastavad metricID-d. Seej\u00e4rel leiame ristumise. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/de11b15286816ada04b22727ff78e43d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tundub, et k\u00f5ik on h\u00e4sti, kuid selles lahenduses on puudusi. VictoriaMetrics rakendas alguses p\u00f6\u00f6ratud indeksi LevelDB-l p\u00f5hinevalt. Kuid l\u00f5puks tuli sellest loobuda.<\/p>\n<p><\/p>\n<p>Miks? Sest LevelDB on aeglasem kui naivne teostus. Naivses teostuses saame antud v\u00f5tme alusel kohe kogu viilu <code>metricIDs<\/code>. See on v\u00e4ga kiire toiming \u2014 kogu viilu saab kasutada.<\/p>\n<p><\/p>\n<p>Kuid LevelDB-s tuleb iga kord, kui kutsume v\u00e4lja funktsiooni <code>GetValues<\/code> l\u00e4bida k\u00f5ik read, mis algavad <code>label=value<\/code>. Ja iga read tuleb v\u00e4lja v\u00f5tta v\u00e4\u00e4rtus <code>timeseries_ids<\/code>. Sellest <code>timeseries_ids<\/code> koostatakse nende <code>timeseries_ids<\/code>. On selge, et see on palju aeglasem kui lihtsalt tavalise kaardi kasutamine v\u00f5tme kaudu.<\/p>\n<p><\/p>\n<p>Teine puudus on see, et LevelDB on kirjutatud C-s. C-funktsioonide v\u00e4ljakutsumine Go-st ei ole v\u00e4ga kiire. See v\u00f5tab sadu nanosekundeid. See pole v\u00e4ga kiire, sest v\u00f5rreldes tavap\u00e4rase funktsiooni v\u00e4ljakutsumisega, mis on kirjutatud Go-s ja mis kestab 1-5 nanosekundit, on j\u00f5udluse erinevus k\u00fcmneid kordi. VictoriaMetrics'i jaoks oli see saatuslik puudus \ud83d\ude42<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/47cace825807b7b062064c2e790dc9d3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Seet\u00f5ttu kirjutasin ma omaenda inversiooni indeksi rakenduse. Ja nimetasime selle <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/VictoriaMetrics\/VictoriaMetrics\/tree\/master\/lib\/mergeset\">mergeset<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Mergeset p\u00f5hineb MergeTree andmestruktuuril. See andmestruktuur on laenatud ClickHouse'ist. Selgelt peab mergeset olema optimeeritud kiireks otsimiseks <code>timeseries_ids<\/code> antud v\u00f5tme j\u00e4rgi. Mergeset on t\u00e4ielikult kirjutatud Go-s. Saate vaadata <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/VictoriaMetrics\/VictoriaMetrics\">VictoriaMetrics'i l\u00e4htekoodi GitHubis<\/a><\/noindex>. Mergeseti rakendus asub kaustas <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/VictoriaMetrics\/VictoriaMetrics\/tree\/master\/lib\/mergeset\">\/lib\/mergeset<\/a><\/noindex>. V\u00f5ite proovida aru saada, mis seal toimub.<\/p>\n<p><\/p>\n<p>Mergeseti API on v\u00e4ga sarnane LevelDB ja RocksDB-ga. See t\u00e4hendab, et see v\u00f5imaldab kiiresti salvestada uusi kirjeid ja kiiresti valida kirjeid antud prefiksi j\u00e4rgi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/845704ed36f70beb468907d22701af59.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mergeseti puudustest r\u00e4\u00e4gime hiljem. Praegu r\u00e4\u00e4gime probleemidest, mis tekkisid VictoriaMetrics'il tootmises inversiooni indeksi rakendamise k\u00e4igus.<\/p>\n<p><\/p>\n<p>Kuidas need tekkisid?<\/p>\n<p><\/p>\n<p>Esimene p\u00f5hjus on suur churn rate. T\u00f5lkes eesti keelde - see on ajaliselt rikka sagedane vahetus. See on juhul, kui ajakava l\u00f5peb ja algab uus, v\u00f5i algavad palju uusi ajakavasid. Seda juhtub sageli.<\/p>\n<p><\/p>\n<p>Teine p\u00f5hjus on suur hulk ajakavasid. Alguses, kui j\u00e4lgimine hakkas populaarsust koguma, oli ajakavasid v\u00e4he. N\u00e4iteks, iga arvuti jaoks tuleb j\u00e4lgida protsessori, m\u00e4luse, v\u00f5rgu ja ketta kasutamist. 4 ajakava iga arvuti kohta. Oletame, et teil on 100 arvutit, see teeb kokku 400 ajakava. See on v\u00e4ga v\u00e4he. <\/p>\n<p><\/p>\n<p>Aja jooksul m\u00f5istsid inimesed, et on v\u00f5imalik m\u00f5\u00f5ta \u00fcksikasjalikumat teavet. N\u00e4iteks m\u00f5\u00f5ta mitte ainult kogu protsessori, vaid ka iga protsessorituuma koormust eraldi. Kui teil on 40 protsessorituuma, siis vastavalt sellele teil on 40 korda rohkem ajakavasid protsessori koormuse m\u00f5\u00f5tmiseks. <\/p>\n<p><\/p>\n<p>Kuid see pole veel k\u00f5ik. Iga protsessorituuma puhul v\u00f5ivad olla mitmed olekud, nagu idle, kui see ei tee midagi. Lisaks on olemas t\u00f6\u00f6 user space'is, t\u00f6\u00f6 kernel space'is ja muid olekuid. Iga sellist olekut on samuti v\u00f5imalik m\u00f5\u00f5ta eraldi ajajoonena. See suurendab ridade arvu 7-8 korda.<\/p>\n<p><\/p>\n<p>Meie uurimisest saime \u00fche m\u00f5\u00f5diku p\u00f5hjal 40 x 8 = 320 m\u00f5\u00f5dikut ainult \u00fche arvuti kohta. Kui korrutame selle 100-ga, saame 32 000 asemel 400. <\/p>\n<p><\/p>\n<p>Hiljem ilmus Kubernetes. Ja see halvenes veelgi, kuna Kuberneteses v\u00f5idakse hostida palju erinevaid teenuseid. Iga teenus Kuberneteses koosneb paljusid pod'idest. K\u00f5ike seda tuleb j\u00e4lgida. Lisaks on meil pidev uute versioonide juurutamine teie teenuste jaoks. Iga uue versiooni jaoks tuleb luua uued ajajooned. L\u00f5ppkokkuv\u00f5ttes kasvab ajajoonte arv eksponentsiaalselt ja seisame silmitsi suure hulga ajajoonte probleemiga, mida nimetatakse high-cardinality. VictoriaMetrics suudab selle probleemiga t\u00f5husalt toime tulla v\u00f5rreldes teiste ajajoonte andmebaasidega. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/c11b7ce6d3294ae420243f72636af4b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vaatame l\u00e4hemalt high churn rate'i. Mis p\u00f5hjustab high churn rate'i tootmises? Sest m\u00f5ned sildid ja t\u00e4hised muutuvad pidevalt.<\/p>\n<p><\/p>\n<p>N\u00e4iteks v\u00f5tame Kubernetes, kus on m\u00f5isted <code>deployment<\/code>, st kui teie rakenduse uus versioon on v\u00e4lja lastud. Kubernetes'e arendajad otsustasid kuidagi lisada deployment'i id m\u00e4rgendisse.<\/p>\n<p><\/p>\n<p>Milles see seisneb? Iga uue deployment'i korral katkestatakse k\u00f5ik vanad ajaliselt j\u00e4rjestatud andmed ja nende asemel algavad uued ajaliselt j\u00e4rjestatud andmed uue m\u00e4rgendiv\u00e4\u00e4rtusega <code>deployment_id<\/code>. Selliseid ridasid v\u00f5ib olla sadu tuhandeid ja isegi miljoneid.<\/p>\n<p><\/p>\n<p>Kogu selle asja oluline erip\u00e4ra on see, et ajajoonte koguarv kasvab, kuid ajajoonte arv, mis praegu on aktiivsed, kuhu andmed voolavad, j\u00e4\u00e4b konstantseks. Seda olekut nimetatakse \u2013 high churn rate.<\/p>\n<p><\/p>\n<p>High churn rate'i peamine probleem on tagada pidev otsingukiirus k\u00f5igi ajajoonte seas, mis vastavad m\u00e4\u00e4ratud siltide kogumile teatud ajavahemiku jooksul. T\u00fc\u00fcpiliselt on see ajavahemik viimase tunni v\u00f5i viimase p\u00e4eva jooksul. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/ac18482b87cc37624d163b30c68cf7be.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kuidas seda probleemi lahendada? Siin on esimene variant. See on p\u00f6\u00f6rdindeksi jagamine s\u00f5ltumatuteks osadeks ajaperioodi kaupa. T. e. kui on m\u00f6\u00f6dunud mingi ajavahemik, l\u00f5petame k\u00e4esoleva p\u00f6\u00f6rdindeksiga t\u00f6\u00f6tamise ja loome uue p\u00f6\u00f6rdindeksi. M\u00f6\u00f6dub veel \u00fcks ajavahemik, loome veel \u00fche ja veel \u00fche. <\/p>\n<p><\/p>\n<p>Ja nende p\u00f6\u00f6rdindeksite valimisel leiame need p\u00f6\u00f6rdindeksid, mis j\u00e4\u00e4vad antud ajavahemikku. Ja seega valime sealt ajaliste j\u00e4rjestuste ID-d. <\/p>\n<p><\/p>\n<p>See v\u00f5imaldab ressursse s\u00e4\u00e4sta, kuna me ei pea vaatama osi, mis ei mahu antud ajavahemikku. T. e. tavaliselt, kui me valime andmed viimase tunni jooksul, siis eelnevate ajavahemike jaoks j\u00e4tame p\u00e4ringud vahele. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/1afa3a88caa7423941ae3494b9cec706.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>On olemas veel \u00fcks lahendus sellele probleemile. See on iga p\u00e4eva jaoks eraldi ajaj\u00e4rjestuste ID-de nimekirja hoidmine, mis sellel p\u00e4eval esinesid.<\/p>\n<p><\/p>\n<p>Selle lahenduse eelis v\u00f5rreldes eelneva lahendusega on selles, et me ei dubleeri teavet ajaj\u00e4rjestuste kohta, mis ei kao aja jooksul. Need on pidevalt olemas ja ei muutu. <\/p>\n<p><\/p>\n<p>Puuduseks on see, et selline lahendus on keerulisem rakendada ja debugeerida. Ja VictoriaMetrics valis selle lahenduse. See on ajalooliselt nii kujunenud. See lahendus n\u00e4itab end samuti \u00fcsna h\u00e4sti, v\u00f5rreldes eelneva lahendusega, kuna see lahendus ei olnud ellu viidud seet\u00f5ttu, et tuli dubleerida andmed igas jagunemises ajaj\u00e4rjestuste jaoks, mis ei muutu, t. e. mis ei kao aja jooksul. VictoriaMetrics oli esmajoones optimeeritud diskiruumi tarbimise osas ja eelmine rakendus halvendas diskiruumi tarbimist. Kuid see rakendus sobib paremini diskiruumi tarbimise minimeerimiseks, seega see valiti. <\/p>\n<p><\/p>\n<p>Pidime selle vastu v\u00f5itlema. V\u00f5itlus seisnes selles, et antud rakenduses tuleb siiski valida palju suurem hulk <code>timeseries_ids<\/code> andmete jaoks, kui siis, kui p\u00f6\u00f6rdindeks on jagatud ajaperioodi kaupa.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/5b10e61aaa803428ed3bfe31815f09d3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kuidas me selle probleemi lahendasime? Me lahendasime selle originaalsel viisil \u2013 salvestades iga p\u00f6\u00f6rdindeksi kirje sisse mitmeid ajaj\u00e4rjestuste identifikaatoreid \u00fche identifikaatori asemel. T. e. meil on v\u00f5ti <code>label=value<\/code>, mis esineb igas ajareas. Ja n\u00fc\u00fcd salvestame m\u00f5ned <code>timeseries_ids<\/code> \u00fches kirjes.<\/p>\n<p><\/p>\n<p>Siin on n\u00e4ide. Varem oli meil N kirjet, aga n\u00fc\u00fcd on meil \u00fcks kirjutis, mille prefiks on sama kui k\u00f5igil teistel. Eelmise kirje v\u00e4\u00e4rtus sisaldab k\u00f5iki ajareade id-sid. <\/p>\n<p><\/p>\n<p>See v\u00f5imaldas suurendada sellise p\u00f6\u00f6rdindeksi skaneerimise kiirus kuni 10 korda. Ja v\u00e4hendada m\u00e4lu tarbimist vahem\u00e4es, kuna n\u00fc\u00fcd salvestame rea <code>label=value<\/code> ainult \u00fcks kord vahem\u00e4esse koos N korraga. Ja see rida v\u00f5ib olla suur, kui teie siltides ja m\u00e4rgendites on pikad read, mille paneb sinna Kubernetes.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/ae4f38a440203bad2d03cf2abd1faafe.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Veel \u00fcks v\u00f5imalus p\u00f6\u00f6rdindeksi otsimise kiirusel kiirendamiseks on sharding. Luues mitu p\u00f6\u00f6rdindeksit \u00fche asemel ja jagades andmed nende vahel v\u00f5tme j\u00e4rgi. See on komplekt <code>key=value<\/code> paare. St. meil on mitu s\u00f5ltumatut p\u00f6\u00f6rdindeksit, mida saame k\u00fcsida paralleelselt mitmel protsessoril. Eelivad rakendused v\u00f5imaldasid t\u00f6\u00f6tada ainult \u00fche protsessori re\u017eiimis, st skaneerida andmeid ainult \u00fchel tuumal. See lahendus v\u00f5imaldab skaneerida andmeid kohe mitmel tuumal, nagu ClickHouse seda armastab teha. Seda plaanime rakendada.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/5ced6446efbf8ded8d7fb91694a999b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ja n\u00fc\u00fcd naaseme meie seadmete juurde \u2013 l\u00f5ikamise funktsioonile <code>timeseries_ids<\/code>. Vaatame, millised v\u00f5ivad olla rakendused. See funktsioon v\u00f5imaldab leida <code>timeseries_ids<\/code> antud komplekti jaoks <code>label=value<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/073a155018a91120c6996c324772f9af.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esimene variant \u2013 see on naive rakendus. Kaks sisemist ts\u00fcklit. Saame funktsioonile sisendi <code>intersectInts<\/code> kaks slice'i \u2014 <code>a<\/code> ja <code>b<\/code>. V\u00e4ljundina peaks see meile tagastama nende slice'ide l\u00f5ike.<\/p>\n<p><\/p>\n<p>Naive rakendus n\u00e4eb v\u00e4lja nii. L\u00e4bime k\u00f5ik v\u00e4\u00e4rtused slice'ist <code>a<\/code>, selle ts\u00fckli sees kontrollime k\u00f5iki v\u00e4\u00e4rtusi slice'ist <code>b<\/code>. Ja v\u00f5rdleme neid. Kui nad klapivad, siis oleme leidnud l\u00f5ike. Ja salvestame selle <code>result<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/b89dcbb4f6d73377f9cf4f50169d6dd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Millised on puudused? Kvadratiivne keerukus \u2013 see on tema peamine puudus. N\u00e4iteks, kui teie slice'i suurused <code>a<\/code> ja <code>b<\/code> on miljon, siis see funktsioon ei naudi kunagi vastust. Sest tal tuleb teha \u00fcks triljon iteratsiooni, mis on isegi t\u00e4nap\u00e4evastele arvutitele v\u00e4ga palju.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/bad26b0092a2fd7fc813bcb79a9138ce.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Teine rakendus p\u00f5hineb kaardil. Loome kaardi. Paneme sellesse kaardisse k\u00f5ik v\u00e4\u00e4rtused slice'ist <code>a<\/code>. Siis liigume eraldi ts\u00fckliga slice'i <code>b<\/code>. Ja kontrollime \u2013 kas see v\u00e4\u00e4rtus on slice'ist <code>b<\/code> map. Kui see on olemas, lisame selle tulemustesse. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/1e610acf641a9cfe4c80aac1fe26044c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Millised on eelised? Eelis seisneb selles, et siin on ainult lineaarne keerukus. See t\u00e4hendab, et funktsioon t\u00e4idab \u00fclesande palju kiiremini suurte slices'i suuruste korral. Miljoni suuruse slice'i jaoks t\u00e4idab see funktsioon 2 miljonit iteratsiooni, erinevalt triljonist iteratsioonist, nagu eelnevas funktsioonis.<\/p>\n<p><\/p>\n<p>Aga puuduseks on see, et see funktsioon vajab rohkem m\u00e4lu selle map'i loomiseks.<\/p>\n<p><\/p>\n<p>Teine puudus \u2013 see on suur overhead hash'i tegemisel. See puudus ei ole sugugi ilmselge. Ka meie jaoks ei olnud see alguses v\u00e4ga ilmne, seet\u00f5ttu oli VictoriaMetrics'i rakendamine intersection'i kaudu map. Kuid seej\u00e4rel profilib profili j\u00e4lgimise k\u00e4igus n\u00e4itas, et peamine protsessori aeg kulub map'i kirjutamisele ja selle map'is oleva v\u00e4\u00e4rtuse kontrollimisele.<\/p>\n<p><\/p>\n<p>Miks kulub protsessorite aeg just nendes kohtades? Sest nendes ridades teostab Go hash\u2019imise toimingut. See t\u00e4hendab, et see arvutab v\u00f5tme hash\u2019i, et seej\u00e4rel p\u00f6\u00f6rduda antud indeksi poole HashMap'is. Hash\u2019i arvutamise operatsioon kestab k\u00fcmneid nanosekundeid. See on VictoriaMetrics'i jaoks aeglane.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/969f10d875d88998e958894ca28b1181.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Otsustasin rakendada bitset'i, mis on spetsiaalselt selle juhtumi jaoks optimeeritud. Nii n\u00e4eb n\u00fc\u00fcd kahte slices'i ristumist. Siin loome bitset'i. Lisame sellesse esimesest slices'ist elemendid. Seej\u00e4rel kontrollime nende elementide olemasolu teises slices'is. Ja lisame need tulemustesse. Peaaegu ei erine eelmisest n\u00e4itest. Ainus, et oleme siin asendanud juurdep\u00e4\u00e4su map'ile kohandatud funktsioonidega. <code>add<\/code> ja <code>has<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/b4ec0753d30d9684868a031f605632c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esmapilgul n\u00e4ib, et see peaks t\u00f6\u00f6tama aeglasemalt, kui varem kasutati standardset map'i, n\u00fc\u00fcd kutsutakse v\u00e4lja m\u00f5ned funktsioonid, kuid profileerimine n\u00e4itab, et see asi t\u00f6\u00f6tab 10 korda kiiremini kui standardne map VictoriaMetrics'i jaoks.<\/p>\n<p><\/p>\n<p>Lisaks kasutab see v\u00f5rreldes map'i rakendusega m\u00e4rgatavalt v\u00e4hem m\u00e4lu. Sest me salvestame siin bitid 8-baidiste v\u00e4\u00e4rtuste asemel.<\/p>\n<p><\/p>\n<p>Selle rakendamise puudus on see, et see ei ole nii ilmne, mitte triviaalne. <\/p>\n<p><\/p>\n<p>Veel inimesed ei pruugi m\u00e4rkida, et sellel lahendusel on \u00fcks puudus: see v\u00f5ib m\u00f5nes olukorras halvasti t\u00f6\u00f6tada. See t\u00e4hendab, et see on optimeeritud konkreetse juhtumi, VictoriaMetrics'i ajavoo id-de ristumiste jaoks. See ei t\u00e4henda, et see sobib k\u00f5igile juhtumitele. Kui seda vale kasutada, siis saame mitte j\u00f5udluse suurenemise, vaid m\u00e4lu \u00fclet\u00e4itumise vea ja j\u00f5udluse v\u00e4henemise. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/94bd174afe43e67b3cf279dc7a1be17c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vaadakem selle struktuuri rakendust. Kui soovite vaadata, siis see asub VictoriaMetrics'i l\u00e4htekoodis kaustas <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/VictoriaMetrics\/VictoriaMetrics\/tree\/master\/lib\/uint64set\">lib\/uint64set<\/a><\/noindex>. See on optimeeritud just VictoriaMetrics'i jaoks, kus <code>timeseries_id<\/code> on 64-bitine v\u00e4\u00e4rtus, kus esimesed 32 bitti on peaaegu pidevad ja ainult viimased 32 bitti muutuvad.<\/p>\n<p><\/p>\n<p>See andmestruktuur ei salvestata kettale, see t\u00f6\u00f6tab ainult m\u00e4lu sees. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/e24ca65f860e2b04037e073f7acae0c1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Siin on selle API. See ei ole v\u00e4ga keeruline. API on kohandatud just VictoriaMetrics'i konkreetse kasutusn\u00e4ite j\u00e4rgi. See t\u00e4hendab, et siin ei ole \u00fcleliigseid funktsioone. Siin on funktsioonid, mida VictoriaMetrics selgelt kasutab.<\/p>\n<p><\/p>\n<p>On funktsioon <code>add<\/code>, mis lisab uusi v\u00e4\u00e4rtusi. On funktsioon <code>has<\/code>, mis kontrollib uusi v\u00e4\u00e4rtusi. Ja on funktsioon <code>del<\/code>, mis eemaldab v\u00e4\u00e4rtuseid. On abifunktsioon <code>len<\/code>, mis tagastab hulga suuruse. Funktsioon <code>clone<\/code> kloneerib hulga. Ja funktsioon <code>appendto<\/code> muudab selle komplekti viiluks. <code>timeseries_ids<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/874b04042d13f342d39f8f393e7fb78c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nii n\u00e4eb see andmestruktuuri rakendus v\u00e4lja. Set'is on kaks elementi:<\/p>\n<p><\/p>\n<ul>\n<li>\n<p><code>ItemsCount<\/code> \u2013 see on abiv\u00e4li, et kiiresti tagastada elementide arvu set'is. Ilma selle abiv\u00e4ljata oleks saanud hakkama, kuid see tuli siia lisada, sest VictoriaMetrics k\u00fcsib oma algoritmides sageli bitset'i pikkust.<\/p>\n<p>\n<\/li>\n<li>\n<p>Teine v\u00e4li on <code>buckets<\/code>. See on viil struktureeritud <code>bucket32<\/code>. Igas struktuuris on salvestatud <code>hi<\/code> v\u00e4li. See on \u00fclemised 32 bitti. Ja kaks viilu \u2014 <code>b16his<\/code> ja <code>buckets<\/code> API-s <code>bucket16<\/code> struktuurid. <\/p>\n<p>\n<\/li>\n<\/ul>\n<p><\/p>\n<p>Siin on salvestatud teise osa 64-bitise struktuuri \u00fclemised 16 bitti. Ja siin on salvestatud bitset'id iga byte'i madalamate 16 bitti jaoks. <\/p>\n<p><\/p>\n<p><code>Bucket64<\/code> koosneb massiivist <code>uint64<\/code>. Pikkus arvutatakse nende muutujate abil. \u00dches <code>bucket16<\/code> v\u00f5ib maksimaalselt hoida <code>2^16=65536<\/code> bitti. Kui jagada see 8-ga, siis on see 8 kilobaiti. Kui jagada veel 8-ga, siis on see 1000 <code>uint64<\/code> v\u00e4\u00e4rtuses. See t\u00e4hendab, et <code>Bucket16<\/code> \u2013 see on 8-kilobaitine struktuur. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/1cca4e6bfafa3408a3c95e0118e26d80.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vaadakem, kuidas on rakendatud \u00fcks selle struktuuri meetod uut v\u00e4\u00e4rtust lisada. <\/p>\n<p><\/p>\n<p>K\u00f5ik algab <code>uint64<\/code> v\u00e4\u00e4rtused. Arvutame \u00fclemised 32 bitti, arvutame alumised 32 bitti. L\u00e4bime k\u00f5ik <code>buckets<\/code>. V\u00f5rdleme iga bucket'i \u00fclemisi 32 bitti lisatavaga. Ja kui need kattuvad, kutsume v\u00e4lja funktsiooni <code>add<\/code> struktuuris b32 <code>buckets<\/code>. Ja lisame sinna alumised 32 bitti. Ja kui see tagastas <code>true<\/code>, siis t\u00e4hendab, et oleme sellise v\u00e4\u00e4rtuse sinna lisanud ja meil ei olnud sellist v\u00e4\u00e4rtust. Kui see tagastab <code>false<\/code>, siis selline v\u00e4\u00e4rtus oli juba olemas. Siis suurendame struktuuri elementide arvu. <\/p>\n<p><\/p>\n<p>Kui me ei leidnud vajalikku <code>bucket'i<\/code> vajaliku hi-v\u00e4\u00e4rtusega, siis kutsume v\u00e4lja funktsiooni <code>addAlloc<\/code>, mis eraldab uue <code>bucket'i<\/code>, lisades selle bucket-struktuuri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/c5d1e5de767f47c7c40e01e12b6d0617.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>See on funktsiooni <code>b32.add<\/code>. See sarnaneb eelneva teostusega. Arvutame vanemad 16 bitti, nooremad 16 bitti.<\/p>\n<p><\/p>\n<p>Siis k\u00e4ime l\u00e4bi k\u00f5ik \u00fclemised 16 bitti. Leiame kattuvused. Ja kattumise korral kutsume v\u00e4lja meetodi add, mida k\u00e4sitleme j\u00e4rgmisel lehel <code>bucket16<\/code>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/e98c4ef316f3a894fd7019c3c85696f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ja see on k\u00f5ige madalam tase, mis peaks olema maksimaalselt optimeeritud. Arvutame <code>uint64<\/code> id v\u00e4\u00e4rtuse slice bit, samuti <code>bitmask<\/code>. See on mask selle 64-bitise v\u00e4\u00e4rtuse jaoks, millega saab kontrollida selle bitti olemasolu v\u00f5i selle seadmist. Kontrollime, kas see bitt on seatud ja seadistame selle, ning tagastame olemasolu. Selline on meie teostus, mis v\u00f5imaldas kiirendada ids ajaseeriate ristumiste operatsiooni 10 korda v\u00f5rreldes tavap\u00e4raste maps'idega.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/4dfa5a6142829a3551be22d6c9c3ab92.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>VictoriaMetrics'is on peale selle optimeerimise palju teisi optimeerimisi. Enamik neist optimeerimistest ei ole lisatud lihtsalt niisama, vaid p\u00e4rast koodi profiliseerimist tootmises.<\/p>\n<p><\/p>\n<p>See on optimeerimise peamine reegel - \u00e4ra lisa optimeerimist, oletades, et siin on kitsaskoht, sest v\u00f5ib juhtuda, et seal ei olegi kitsaskohta. Optimeerimine halvendab tavaliselt koodi kvaliteeti. Seet\u00f5ttu on m\u00f5istlik optimeerida ainult p\u00e4rast profiliseerimist ja eelistatult tootmises, et need oleksid reaalsed andmed. Kui interese, siis v\u00f5ite vaadata VictoriaMetrics'i allikaid ja uurida teisi seal olevaid optimeerimisi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Go optimeerimised VictoriaMetrics. Aleksandr Valjalkin\" src=\"\/wp-content\/uploads\/2020\/05\/7585c4dc782627bac5b649e6a55e2ffb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><em>Mul on k\u00fcsimus bitset'i kohta. V\u00e4ga sarnane C++ vector bool'i teostusele, optimeeritud bitset. Kas te v\u00f5tsite sealt teostuse?<\/em><\/p>\n<p><\/p>\n<p>Ei, mitte sealt. Selle bitset'i elluviimisel tuginesin nende ids timeseries struktuuri teadmistele, mida kasutatakse VictoriaMetrics'is. Nende struktuur on selline, et \u00fclemised 32 bitti on enamasti p\u00fcsivad. Alumised 32 bitti v\u00f5ivad muutuda. Mida madalam on bitt, seda tihedamini v\u00f5ib see muutuda. Seet\u00f5ttu on see elluviimine optimeeritud just selle andmestruktuuri jaoks. C++ elluviimine, niipalju kui ma tean, on optimeeritud \u00fcldise juhtumi jaoks. Kui teha optimeerimist \u00fcldise juhtumi jaoks, siis see t\u00e4hendab, et see ei ole konkreetse juhtumi jaoks k\u00f5ige optimaalsem.<\/p>\n<p><\/p>\n<p>Soovitan teil veel vaadata Alexei Milovid'i ettekannet. Ta r\u00e4\u00e4kis kuskil kuu aega tagasi ClickHouse optimeerimisest konkreetsete spetsialiseerumiste jaoks. Ta r\u00e4\u00e4gib, et \u00fcldjuhul on C++ elluviimine v\u00f5i m\u00f5ni muu elluviimine suunatud hea t\u00f6\u00f6 tagamisele keskmiselt. See v\u00f5ib t\u00f6\u00f6tada halvemini kui spetsialiseeritud elluviimine konkreetsete teadmiste jaoks, nagu meil, kui me teame, et \u00fclemised 32 bitti on enamasti p\u00fcsivad.<\/p>\n<p><\/p>\n<p><em>Mul on teine k\u00fcsimus. Mis on kardinaalne erinevus InfluxDB-st?<\/em><\/p>\n<p><\/p>\n<p>Kardinaalseid erinevusi on palju. Kui r\u00e4\u00e4kida j\u00f5udlusest ja m\u00e4lu tarbimisest, siis InfluxDB n\u00e4itab testides 10 korda suuremat m\u00e4lu tarbimist k\u00f5rge kardinaalsusega ajarealistes, kui neid on palju, n\u00e4iteks miljonites. N\u00e4iteks VictoriaMetrics tarbib 1 GB miljoni aktiivse rea kohta, samas kui InfluxDB tarbib 10 Gb. Ja see on suur erinevus. <\/p>\n<p><\/p>\n<p>Teine kardinaalne erinevus on see, et InfluxDB-l on kummalised p\u00e4ringukeeled \u2013 Flux ja InfluxQL. Need ei ole ajarealistega t\u00f6\u00f6tamiseks eriti mugavad v\u00f5rreldes <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/@valyala\/promql-tutorial-for-beginners-9ab455142085\">PromQL<\/a><\/noindex>, mida toetatakse VictoriaMetrics'is. PromQL on p\u00e4ringukeel Prometheuses.<\/p>\n<p><\/p>\n<p>Ja veel \u00fcks erinevus \u2013 InfluxDB-l on veidi kummaline andmemudel, kus igas real v\u00f5ib olla mitu field'i erineva sildistuse kogumiga. Need read jagunevad veel erinevateks tabeliteks. Need lisakompleksused raskendavad sellele andmebaasile j\u00e4rgnevate toimingute tegemist. Seda on keeruline hallata ja m\u00f5ista.<\/p>\n<p><\/p>\n<p>VictoriaMetrics'is on k\u00f5ik kindlasti lihtsam. Seal esindab iga ajareaal v\u00f5tme-v\u00e4\u00e4rtuse paari. V\u00e4\u00e4rtus on punktide komplekt \u2013 <code>(timestamp, value)<\/code>, v\u00f5tme aga on kogum <code>label=value<\/code>. Ei ole mingit eraldatust fields ja measurements vahel. See v\u00f5imaldab teil valida \u00fcksk\u00f5ik milliseid andmeid ja seej\u00e4rel neid kombineerida, liita, lahutada, korrutada ja jagada, erinevalt InfluxDB-st, kus erinevate ridade vahelisi arvutusi pole seni niipalju teadaolevalt rakendatud. Isegi kui nad on rakendatud, on see keeruline ja selleks tuleb kirjutada palju koodi. <\/p>\n<p><\/p>\n<p><em>Mul on t\u00e4iendav k\u00fcsimus. Kas m\u00f5istsin \u00f5igesti, et oli mingi probleem, millest r\u00e4\u00e4kisite, et see p\u00f6\u00f6ratud indeks ei mahu m\u00e4llu, seet\u00f5ttu toimub seal partitsioneerimine?<\/em><\/p>\n<p><\/p>\n<p>Alguses n\u00e4itasin lihtsat p\u00f6\u00f6ratud indeksi rakendust tavalise Go kaardi baasil. Selline rakendus ei sobi andmebaaside jaoks, kuna see p\u00f6\u00f6ratud indeks ei salvestata kettale, aga andmebaas peab salvestama kettale, et need andmed j\u00e4\u00e4ksid p\u00e4rast taask\u00e4ivitamist k\u00e4ttesaadavaks. Sellises rakenduses kaotate taask\u00e4imise korral p\u00f6\u00f6ratud indeksi. Ja te kaotate juurdep\u00e4\u00e4su k\u00f5ikidele andmetele, kuna te ei suuda neid leida. <\/p>\n<p><\/p>\n<p><em>Tere! Ait\u00e4h ettekande eest! Minu nimi on Pavel. Olen ettev\u00f5ttest Wildberries. Mul on teile m\u00f5ned k\u00fcsimused. Esimene k\u00fcsimus. Kuidas arvate, et kui valiksite oma rakenduse arhitektuuri ehitamisel teise printsiibi ja partitsioneeriksite andmed ajas, siis v\u00f5iks-olla suudaksite te andmete ristumisi otsingul teha, tuginedes ainult sellele, et \u00fches partitsioonis on andmed \u00fche ajavahemiku kohta, st \u00fche aja vahe kohta ja te ei peaks muretsema selle \u00fcle, et teil on t\u00fckid erinevalt laiali jaotatud? Teine k\u00fcsimus \u2014 kuna te rakendate sarnast algoritmi bitsetiga ja k\u00f5igega muuga, kas olete proovinud kasutada protsessori k\u00e4ske? V\u00f5ib-olla olete proovinud selliseid optimeerimisi?<\/em><\/p>\n<p><\/p>\n<p>Teisele k\u00fcsimusele vastan kohe. Me ei ole sinna veel j\u00f5udnud. Aga kui on vaja, siis j\u00f5uame. Aga esimese, mis oli k\u00fcsimus?<\/p>\n<p><\/p>\n<p><em>Te arutasite kahte stsenaariumi. Ja \u00fctlesite, et valisite teise keerukama rakenduse. Ja ei eelistanud esimest, kus andmed on ajas partitsioneeritud.<\/em> <\/p>\n<p><\/p>\n<p>Jah. Esimeses variandis oleks indeksi kogumaht suurem, kuna igas partitsioonis peaksime hoidma andmete koopiaid nende ajaseeriate jaoks, mis kestavad l\u00e4bi k\u00f5ikide nende partitsioonide. Ja kui teie ajaseeriate churn rate on madal, st pidevalt kasutatakse samu seeriaid, siis esimese variandi puhul kaotaksime oluliselt rohkem kettaruumi v\u00f5rreldes teise variandiga.<\/p>\n<p><\/p>\n<p>Aga jah, ajap\u00f5hine partitsioneerimine on hea variant. Seda kasutab ka Prometheus. Kuid Prometheusel on teine puudus. Kui need andmeosad \u00fchendatakse, peab ta hoidma m\u00e4lus k\u00f5iki label\u2019i ja ajaseeriate metaandmeid. Seet\u00f5ttu, kui andmeosad, mida ta \u00fchendab, on suured, kasvab m\u00e4llu minev tarbimine oluliselt, erinevalt VictoriaMetricsist. VictoriaMetrics ei tarbi \u00fchendamisel \u00fcldse m\u00e4lu, seal tarbitakse vaid paar kilobaiti, s\u00f5ltumata \u00fchendatud andmeosade suurusest.<\/p>\n<p><\/p>\n<p><em>Teie kasutatav algoritm tarbib m\u00e4lu. Seal t\u00e4histatakse ajaseeriate silti, millel on v\u00e4\u00e4rtused. Nii kontrollite, kas \u00fches andme massiivis on paariline olemas ja teisest. Ja saate aru \u2013 kas toimus ristumine v\u00f5i mitte. T\u00fc\u00fcpiliselt rakendavad andmebaasid kursoreid, iteraatoreid, mis hoiavad oma praegust olekut ja liiguvad j\u00e4rjestatud andmete kaudu, tagades, et nende toimingute keerukus on lihtne.<\/em> <\/p>\n<p><\/p>\n<p>Miks me ei kasuta andmete ristumise jaoks kursoreid?<\/p>\n<p><\/p>\n<p><em>Jah.<\/em> <\/p>\n<p><\/p>\n<p>Meie LevelDB-s v\u00f5i mergeset'is ongi just j\u00e4rjekorras olevad read. Me saame kursori abil l\u00e4bida ja leida ristumise. Aga miks ei kasuta? Sest \u2013 see on aeglane. Sest kursorid eeldavad, et igale reale tuleb funktsioon kutsuda. Funktsiooni kutsumine on 5 nanosekundit. Ja kui teil on 100 000 000 rida, siis kulutame pelgalt funktsiooni kutsumise peale pool sekundit.<\/p>\n<p><\/p>\n<p><em>Selline asi on, jah. Ja mul on viimane k\u00fcsimus. K\u00fcsimus, mis v\u00f5ib-olla tunduda veidi imelik. Miks ei saa andmete sisestamise hetkel k\u00f5iki vajalikke agregaatide arvestusi teha ja neid vajalikus formaadis salvestada? Miks hoida tohutul hulgal andmeid s\u00fcsteemidesse nagu VictoriaMetrics, ClickHouse jne, et hiljem neile v\u00e4ga palju aega kulutada?<\/em><\/p>\n<p><\/p>\n<p><em>To clarify, let me give an example. How does a small toy speedometer work? It records the distance you have traveled, continuously adding it to one variable, while in another it tracks time. Then it divides to get the average speed. You can do something similar by collecting all necessary facts on the fly.<\/em><\/p>\n<p><\/p>\n<p>Alright, I understand the question. Your example has its merits. If you know which aggregates you need, it\u2019s the best implementation. The problem is that people save these metrics, some data in ClickHouse, and they don\u2019t yet know how they\u2019ll aggregate and filter them in the future, so they end up saving all the raw data. But if you know you need to calculate something average, why not calculate it instead of storing a bunch of raw values? This is only if you know exactly what you need.<\/p>\n<p><\/p>\n<p>By the way, databases for storing time series support aggregate counting. For instance, Prometheus supports <noindex><a rel=\"nofollow\" href=\"https:\/\/prometheus.io\/docs\/prometheus\/latest\/configuration\/recording_rules\/\">recording rules<\/a><\/noindex>. This can be done if you know what aggregates you will need. This feature is not available in VictoriaMetrics yet, but Prometheus is usually placed in front of it, where this can be done with recording rules.<\/p>\n<p><\/p>\n<p>For example, at my previous job, we needed to count the number of events in a sliding window over the last hour. The problem was that we had to create a custom implementation in Go, a service for counting this. Ultimately, this service was non-trivial because it's challenging to calculate. The implementation can be simple if you need to count aggregates at fixed time intervals. However, if you want to count events in a sliding window, it's not as easy as it seems. I believe this hasn't been implemented in ClickHouse or time series databases yet because it's complex to do.<\/p>\n<p><\/p>\n<p><em>And one more question. We were just discussing averaging, and I remembered that there used to be a tool called Graphite with a Carbon backend. It could prune old data, retaining one point per minute, one point per hour, and so on. It's quite convenient if we need raw data, say for a month, while everything else can be pruned. But Prometheus and VictoriaMetrics do not support this functionality. Will it be supported in the future? If not, why?<\/em><\/p>\n<p><\/p>\n<p>Ait\u00e4h k\u00fcsimuse eest. Meie kasutajad esitavad seda aeg-ajalt. Nad k\u00fcsivad, millal me lisame downsampling'i toe. Siin on mitu probleemi. Esiteks, iga kasutaja m\u00f5istab seda erinevalt. <code>allapoole n\u00e4itamine<\/code> Keegi soovib saada suvalist punkti m\u00e4\u00e4ratud intervallis, keegi soovib maksimaalseid, minimaalseid, keskmisi v\u00e4\u00e4rtuseid. Kui teie andmebaasi salvestavad andmeid paljud s\u00fcsteemid, siis ei saa neid \u00fchte patta panna. V\u00f5ib juhtuda, et iga s\u00fcsteemi jaoks tuleb kasutada erinevat downsampling'ut. Ja see on keeruline ellu viia.<\/p>\n<p><\/p>\n<p>Teiseks on see, et VictoriaMetrics, nagu ka ClickHouse, on optimeeritud t\u00f6\u00f6tama suurte tooredate kogustega, seet\u00f5ttu suudab see t\u00f6\u00f6delda miljardit rida v\u00e4hem kui sekundiga, kui teil on palju tuumasid teie s\u00fcsteemis. Aja rea punkte skaneerimine VictoriaMetrics'is \u2013 50 000 000 punkti sekundis \u00fches tuumas. Ja see j\u00f5udlus skaleerub olemasolevatele tuumadele. Ehk siis kui teil on n\u00e4iteks 20 tuuma, siis saate miljard punkti sekundis skaneerida. Ja see omadus v\u00e4hendab VictoriaMetrics'i ja ClickHouse'i vajadust downsampling'i j\u00e4rele.<\/p>\n<p><\/p>\n<p>Veel \u00fcks omadus on see, et VictoriaMetrics tihendab andmeid t\u00f5husalt. Tihendamine keskmiselt production'is on 0,4 kuni 0,8 baiti punkti kohta. Iga punkt \u2013 see on ajatemperatuur + v\u00e4\u00e4rtus. Ja see tihendatakse keskmiselt v\u00e4hem kui \u00fche baidi alla. <\/p>\n<p><\/p>\n<p><em>Sergei. Mul on k\u00fcsimus. Mis on minimaalne salvestamise ajavahemik?<\/em><\/p>\n<p><\/p>\n<p>\u00dcks millisekund. Hiljuti oli meil vestlus teiste ajareadade andmebaaside arendajatega. Nende minimaalne ajavahemik on \u00fcks sekund. N\u00e4iteks Graphites on see ka \u00fcks sekund. OpenTSDB-s on samuti \u00fcks sekund. InfluxDB-s on nanosekundiline t\u00e4psus. VictoriaMetrics'is on see \u00fcks millisekund, kuna Prometheus'el on \u00fcks millisekund. Ja VictoriaMetrics loodi algselt Prometheuse kaugandmete salvestamiseks. Kuid n\u00fc\u00fcd suudab see salvestada andmeid ka muudest s\u00fcsteemidest. <\/p>\n<p><\/p>\n<p>Inimene, kellega ma r\u00e4\u00e4kisin, \u00fctleb, et neil on sekundiline t\u00e4psus \u2014 sellest piisab, kuna see s\u00f5ltub andmete t\u00fc\u00fcbist, mida ajareadadesse salvestatakse. Kui need on DevOps andmed v\u00f5i andmed infrastruktuurist, kus te kogute neid 30 sekundi, minuti kaupa, siis seal piisab sekundilisest t\u00e4psusest, v\u00e4hem ei ole vajalik. Kuid kui te kogute andmeid k\u00f5rge sagedusega kauplemiss\u00fcsteemidest, siis on vajalik nanosekundiline t\u00e4psus.<\/p>\n<p><\/p>\n<p>Millisekundi t\u00e4psus VictoriaMetrics sobib nii DevOps juhtumitele, kui ka enamikule juhtumitest, millest ma aruandesse alguses r\u00e4\u00e4kisin. Ainus, mille jaoks see ei pruugi sobida, on k\u00f5rge sagedusega kaubanduss\u00fcsteemid.<\/p>\n<p><\/p>\n<p><em>Ait\u00e4h! Ja veel \u00fcks k\u00fcsimus. Milline on \u00fchilduvus PromQL-iga?<\/em><\/p>\n<p><\/p>\n<p>T\u00e4ielik tagasik\u00e4idatav \u00fchilduvus. VictoriaMetrics toetab t\u00e4ielikult PromQL-i. Peale selle lisab see ka t\u00e4iendavaid funktsioone PromQL-ile, mida nimetatakse <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/VictoriaMetrics\/VictoriaMetrics\/wiki\/MetricsQL\">MetricsQL<\/a><\/noindex>. Selle t\u00e4iendava funktsiooni kohta on YouTube'is ettekandeid. Olen sellest r\u00e4\u00e4kinud Monitoring Meetup'il kevadel Peterburis.<\/p>\n<p><\/p>\n<p>Telegrami kanal <noindex><a rel=\"nofollow\" href=\"https:\/\/t.me\/VictoriaMetrics_ru1\">VictoriaMetrics<\/a><\/noindex>.<\/p>\n<p class=\"for_users_only_msg\">Ainult registreeritud kasutajad saavad k\u00fcsitluses osaleda. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Logige sisse<\/a><\/noindex>, palun.<\/p>\n<h2 class=\"default-block__polling-title\">Mis takistab teid \u00fcleminekul VictoriaMetricsile kui pikaajalisele salvestuslahendusele Prometheusele? (Kirjutage kommentaaridesse, lisaan k\u00fcsitlusse))<\/h2>\n<ul class=\"poll-result\">\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent  poll-result__data-percent_winner\">71,4%<\/strong>Ei kasuta Prometheus5<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">28,6%<\/strong>Ei teadnud VictoriaMetrics2 kohta<\/p>\n<\/li>\n<\/ul>\n<p>    7 kasutajat h\u00e4\u00e4letas. 12 kasutajat viibis.<br \/>\n<br \/>Allikas: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/500844\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043a\u043e\u043d\u0446\u0430 2019 \u0433\u043e\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0412\u0430\u043b\u044f\u043b\u043a\u0438\u043d\u0430 &quot;Go optimizations in VictoriaMetrics&quot; VictoriaMetrics \u2014 \u0431\u044b\u0441\u0442\u0440\u0430\u044f \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u0430\u044f \u0421\u0423\u0411\u0414 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0444\u043e\u0440\u043c\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u044f\u0434\u0430 (\u0437\u0430\u043f\u0438\u0441\u044c \u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0438 \u043d\u0430\u0431\u043e\u0440 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u044d\u0442\u043e\u043c\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043e\u043f\u0440\u043e\u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0434\u0430\u0442\u0447\u0438\u043a\u043e\u0432 \u0438\u043b\u0438 \u0441\u0431\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a). \u0412\u043e\u0442 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u2014 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":80734,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-80733","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043a\u043e\u043d\u0446\u0430 2019 \u0433\u043e\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0412\u0430\u043b\u044f\u043b\u043a\u0438\u043d\u0430 &quot;Go optimizations in VictoriaMetrics&quot;\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/go-optimizations-in-victoriametrics-aleksandr-valyalkin\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Go optimizations in VictoriaMetrics. \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440 \u0412\u0430\u043b\u044f\u043b\u043a\u0438\u043d | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043a\u043e\u043d\u0446\u0430 2019 \u0433\u043e\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0412\u0430\u043b\u044f\u043b\u043a\u0438\u043d\u0430 &quot;Go optimizations in VictoriaMetrics&quot;\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/go-optimizations-in-victoriametrics-aleksandr-valyalkin\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-08T11:42:31+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-08T11:42:31+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47 Go optimeerimised VictoriaMetricsis. Alexander Valjalkin | ProHoster","description":"Tutvustan teile 2019. aasta l\u00f5pu raporti \"Go optimizations in VictoriaMetrics\" t\u00f5lgendust, mille autor on Aleksandr Valjalkin.","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/go-optimizations-in-victoriametrics-aleksandr-valyalkin","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Go optimizations in VictoriaMetrics. \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440 \u0412\u0430\u043b\u044f\u043b\u043a\u0438\u043d | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043a\u043e\u043d\u0446\u0430 2019 \u0433\u043e\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0412\u0430\u043b\u044f\u043b\u043a\u0438\u043d\u0430 &quot;Go optimizations in VictoriaMetrics&quot;","og:url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/go-optimizations-in-victoriametrics-aleksandr-valyalkin","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-08T11:42:31+00:00","article:modified_time":"2020-05-08T11:42:31+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"80733","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:12:22","updated":"2022-09-29 05:16:51","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/80733","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=80733"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/80733\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/80734"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=80733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=80733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=80733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}