Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Aku saranake sampeyan maca transkrip laporan pungkasan taun 2019 dening Alexander Valyalkin "Go optimizations in VictoriaMetrics"

VictoriaMetrics - DBMS sing cepet lan bisa diukur kanggo nyimpen lan ngolah data ing wangun deret wektu (rekaman mbentuk wektu lan sakumpulan nilai sing cocog karo wektu iki, contone, dipikolehi liwat polling periodik status sensor utawa koleksi metrik).

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Iki link menyang video laporan iki - https://youtu.be/MZ5P21j_HLE

Geser

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Marang kita bab sampeyan dhewe. Aku Alexander Valyalkin. kene akun GitHubku. Aku kepengin banget babagan Go lan optimasi kinerja. Aku nulis akeh perpustakaan migunani lan ora dadi migunani. Padha miwiti karo salah siji fast, utawa karo quick ater-ater.

Aku saiki nggarap VictoriaMetrics. Apa iku lan apa aku ana? Aku bakal ngomong babagan iki ing presentasi iki.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Dhaptar laporan kasebut kaya ing ngisor iki:

  • Pisanan, aku bakal ngandhani apa VictoriaMetrics.
  • Banjur aku bakal pitutur marang kowe apa seri wektu.
  • Banjur aku bakal pitutur marang kowe carane database seri wektu bisa.
  • Sabanjure, aku bakal pitutur marang kowe babagan arsitektur database: apa sing kalebu.
  • Banjur ayo pindhah menyang optimasi sing diduweni VictoriaMetrics. Iki minangka optimasi kanggo indeks terbalik lan optimasi kanggo implementasi bitset ing Go.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Apa ana sing ngerti apa VictoriaMetrics? Wah, wis akeh sing ngerti. Iku kabar apik. Kanggo sing ora ngerti, iki database seri wektu. Iki adhedhasar arsitektur ClickHouse, ing sawetara rincian implementasi ClickHouse. Contone, ing kayata: MergeTree, pitungan podo ing kabeh intine prosesor kasedhiya lan Optimization kinerja dening digunakake ing pamblokiran data sing diselehake ing cache prosesor.

VictoriaMetrics nyedhiyakake kompresi data sing luwih apik tinimbang database seri wektu liyane.

Timbangan vertikal - yaiku, sampeyan bisa nambah prosesor liyane, luwih akeh RAM ing komputer siji. VictoriaMetrics bakal sukses nggunakake sumber daya sing kasedhiya lan bakal nambah produktivitas linear.

VictoriaMetrics uga skala horisontal - yaiku, sampeyan bisa nambah kelenjar tambahan menyang kluster VictoriaMetrics, lan kinerja bakal nambah meh linear.

Kaya sing sampeyan bayangake, VictoriaMetrics minangka basis data sing cepet, amarga aku ora bisa nulis wong liya. Lan ditulis ing Go, mula aku ngomong babagan iki ing pertemuan iki.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Sapa sing ngerti apa seri wektu? Dheweke uga ngerti akeh wong. Deret wektu yaiku seri pasangan (timestamp, значение), ing ngendi pasangan kasebut diurutake miturut wektu. Nilai kasebut minangka angka floating point - float64.

Saben seri wektu diidentifikasi kanthi unik kanthi tombol. Apa isine kunci iki? Iku kasusun saka set non-kosong pasangan kunci-nilai.

Punika conto saka seri wektu. Kunci seri iki yaiku dhaptar pasangan: __name__="cpu_usage" yaiku jeneng metrik, instance="my-server" - iki komputer ing ngendi metrik iki diklumpukake, datacenter="us-east" - iki pusat data ngendi komputer iki dumunung.

We rampung munggah karo jeneng seri wektu dumadi saka telung pasangan tombol-nilai. Tombol iki cocog karo dhaptar pasangan (timestamp, value). t1, t3, t3, ..., tN - iki cap wektu, 10, 20, 12, ..., 15 - nilai sing cocog. Iki minangka panggunaan CPU ing wektu tartamtu kanggo seri tartamtu.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ing endi time series bisa digunakake? Apa ana sing duwe ide?

  • Ing DevOps, sampeyan bisa ngukur CPU, RAM, jaringan, rps, jumlah kesalahan, lsp.
  • IoT - kita bisa ngukur suhu, tekanan, koordinat geo lan liya-liyane.
  • Uga keuangan - kita bisa ngawasi rega kanggo kabeh jinis saham lan mata uang.
  • Kajaba iku, seri wektu bisa digunakake kanggo ngawasi proses produksi ing pabrik. Kita duwe pangguna sing nggunakake VictoriaMetrics kanggo ngawasi turbin angin, kanggo robot.
  • Seri wektu uga migunani kanggo ngumpulake informasi saka sensor saka macem-macem piranti. Contone, kanggo mesin; kanggo ngukur tekanan ban; kanggo ngukur kacepetan, jarak; kanggo ngukur konsumsi bensin, lsp.
  • Seri wektu uga bisa digunakake kanggo ngawasi pesawat. Saben pesawat duwe kothak ireng sing nglumpukake seri wektu kanggo macem-macem parameter kesehatan pesawat. Seri wektu uga digunakake ing industri aerospace.
  • Kesehatan yaiku tekanan darah, pulsa, lsp.

Bisa uga ana luwih akeh aplikasi sing aku kelalen, nanging muga-muga sampeyan ngerti manawa seri wektu digunakake kanthi aktif ing jagad modern. Lan volume panggunaane tambah akeh saben taun.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Napa sampeyan butuh database seri wektu? Napa sampeyan ora bisa nggunakake database relasional biasa kanggo nyimpen seri wektu?

Amarga seri wektu biasane ngemot informasi sing akeh, sing angel disimpen lan diproses ing basis data konvensional. Mulane, database khusus kanggo seri wektu muncul. Basis kasebut kanthi efektif nyimpen poin (timestamp, value) karo tombol diwenehi. Dheweke nyedhiyakake API kanggo maca data sing disimpen kanthi kunci, kanthi pasangan nilai kunci siji, utawa kanthi pasangan nilai kunci, utawa regexp. Contone, sampeyan pengin nemokake beban CPU kabeh layanan sampeyan ing pusat data ing Amerika, banjur sampeyan kudu nggunakake pseudo-query iki.

Biasane database seri wektu nyedhiyakake basa pitakon khusus amarga SQL seri wektu ora cocog banget. Senajan ana database sing ndhukung SQL, iku ora cocok banget. Basa pitakon kayata PromQL, InfluxQL, mili, Q. Mugi sing wong wis krungu paling siji saka basa iki. Akeh wong sing wis krungu babagan PromQL. Iki minangka basa pitakon Prometheus.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Iki kaya arsitektur database seri wektu modern nggunakake VictoriaMetrics minangka conto.

Iku kasusun saka rong bagéan. Iki minangka panyimpenan kanggo indeks terbalik lan panyimpenan kanggo nilai seri wektu. Repositori kasebut dipisahake.

Nalika rekaman anyar teka ing basis data, kita pisanan ngakses indeks terbalik kanggo nemokake pengenal seri wektu kanggo set tartamtu. label=value kanggo metrik tartamtu. Kita nemokake pengenal iki lan nyimpen nilai kasebut ing nyimpen data.

Nalika panjalukan kanggo njupuk data saka TSDB, kita pindhah menyang indeks terbalik. Ayo entuk kabeh timeseries_ids cathetan sing cocog karo set iki label=value. Banjur kita entuk kabeh data sing dibutuhake saka gudang data, sing diindeks dening timeseries_ids.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ayo goleki conto carane database seri wektu ngolah pitakon pilih sing mlebu.

  • Kaping pisanan dheweke entuk kabeh timeseries_ids saka indeks terbalik sing ngemot pasangan sing diwenehake label=value, utawa gawe marem ekspresi reguler sing diwenehake.
  • Banjur njupuk kabeh titik data saka panyimpenan data ing interval wektu tartamtu kanggo sing ditemokake timeseries_ids.
  • Sawise iki, database nindakake sawetara petungan ing titik data kasebut, miturut panjaluk pangguna. Lan sawise iku bali jawaban.

Ing presentasi iki aku bakal ngandhani babagan bagean pisanan. Iki minangka panelusuran timeseries_ids dening indeks kuwalik. Sampeyan bisa nonton babagan bagean kapindho lan bagean katelu mengko Sumber VictoriaMetrics, utawa ngenteni nganti aku nyiapake laporan liyane :)

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ayo pindhah menyang indeks terbalik. Akeh sing mikir iki prasaja. Sapa sing ngerti apa indeks terbalik lan cara kerjane? Oh, ora akeh wong maneh. Ayo dadi nyoba kanggo mangerteni apa iku.

Iku bener prasaja. Iku mung kamus sing peta tombol kanggo nilai. Apa iku kunci? Pasangan iki label=valuengendi label и value - iki garis. Lan nilai kasebut minangka set timeseries_ids, kang kalebu pasangan diwenehi label=value.

Indeks terbalik ngidini sampeyan nemokake kabeh kanthi cepet timeseries_ids, ingkang sampun maringi label=value.

Sampeyan uga ngidini sampeyan nemokake kanthi cepet timeseries_ids seri wektu kanggo sawetara pasangan label=value, utawa kanggo pasangan label=regexp. Kepiye kedadeyan iki? Kanthi nemokake persimpangan saka set timeseries_ids kanggo saben pasangan label=value.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ayo goleki macem-macem implementasi indeks terbalik. Ayo dadi miwiti karo implementasine naif paling prasaja. Dheweke katon kaya iki.

fungsi getMetricIDs entuk dhaptar senar. Saben baris ngemot label=value. Fungsi iki ngasilake dhaptar metricIDs.

Cara kerjane? Ing kene kita duwe variabel global sing diarani invertedIndex. Iki kamus biasa (map), sing bakal peta string kanggo irisan ints. Ing baris ngandhut label=value.

implementasi fungsi: njaluk metricIDs kanggo pisanan label=value, banjur kita liwat kabeh liyane label=value, kita entuk metricIDs kanggo wong-wong mau. Lan nelpon fungsi intersectInts, sing bakal dibahas ing ngisor iki. Lan fungsi iki ngasilake persimpangan dhaptar kasebut.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Minangka sampeyan bisa ndeleng, ngleksanakake indeks terbalik ora rumit banget. Nanging iki implementasine naif. Apa kekurangane? Kerugian utama saka implementasine naif yaiku indeks terbalik kasebut disimpen ing RAM. Sawise miwiti maneh aplikasi kita kelangan indeks iki. Ora ana nyimpen indeks iki menyang disk. Indeks kuwalik kasebut ora cocog kanggo basis data.

Kakurangan kapindho uga ana hubungane karo memori. Indeks kuwalik kudu pas karo RAM. Yen ngluwihi ukuran RAM, banjur temenan kita bakal njaluk - metu saka kesalahan memori. Lan program ora bakal bisa.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Masalah iki bisa ditanggulangi kanthi nggunakake solusi sing wis siap kayata LevelDB, utawa RocksDB.

Ing cendhak, kita butuh database sing ngidini kita nindakake telung operasi kanthi cepet.

  • Operasi pisanan yaiku ngrekam ключ-значение menyang database iki. Dheweke nindakake iki cepet banget, ngendi ключ-значение iku strings sembarang.
  • Operasi kapindho yaiku telusuran cepet kanggo nilai nggunakake tombol sing diwenehake.
  • Lan operasi katelu yaiku telusuran cepet kanggo kabeh nilai kanthi prefiks sing diwenehake.

LevelDB lan RocksDB - database iki dikembangake dening Google lan Facebook. Pisanan teka LevelDB. Banjur wong lanang saka Facebook njupuk LevelDB lan wiwit nambah, dheweke nggawe RocksDB. Saiki meh kabeh basis data internal bisa digunakake ing RocksDB ing Facebook, kalebu sing wis ditransfer menyang RocksDB lan MySQL. Wong-wong mau dijenengi MyRocks.

Indeks terbalik bisa dileksanakake nggunakake LevelDB. Carane nindakake? Kita nyimpen minangka kunci label=value. Lan nilai kasebut minangka pengenal saka seri wektu ing ngendi pasangan kasebut ana label=value.

Yen kita duwe akeh seri wektu karo pasangan diwenehi label=value, banjur bakal ana akeh baris ing database iki karo tombol padha lan beda timeseries_ids. Kanggo entuk dhaptar kabeh timeseries_ids, sing diwiwiti karo iki label=prefix, kita nindakake scan sawetara sing database iki optimized. Yaiku, kita milih kabeh baris sing diwiwiti label=prefix lan entuk sing perlu timeseries_ids.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Mangkene conto implementasine kaya apa ing Go. Kita duwe indeks terbalik. Iki LevelDB.

Fungsi kasebut padha karo implementasine naif. Iku mbaleni implementasine naif meh baris dening baris. Mung titik iku tinimbang nguripake kanggo map kita ngakses indeks terbalik. Kita entuk kabeh nilai kanggo pisanan label=value. Banjur kita ngliwati kabeh pasangan sing isih ana label=value lan entuk set metrikID sing cocog kanggo dheweke. Banjur kita nemokake prapatan.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Kabeh katon apik, nanging ana kekurangan kanggo solusi iki. VictoriaMetrics wiwitane ngetrapake indeks terbalik adhedhasar LevelDB. Nanging pungkasane aku kudu nyerah.

Kenging punapa? Amarga LevelDB luwih alon tinimbang implementasine naif. Ing implementasine naif, diwenehi tombol diwenehi, kita langsung njupuk kabeh irisan metricIDs. Iki minangka operasi sing cepet banget - kabeh irisan siap digunakake.

Ing LevelDB, saben fungsi diarani GetValues sampeyan kudu ngliwati kabeh baris sing diwiwiti label=value. Lan entuk nilai kanggo saben baris timeseries_ids. Saka kuwi timeseries_ids ngumpulake irisan iki timeseries_ids. Temenan, iki luwih alon tinimbang mung ngakses peta biasa kanthi tombol.

Kekurangan kapindho yaiku LevelDB ditulis ing C. Nelpon fungsi C saka Go ora cepet banget. Butuh atusan nanodetik. Iki ora cepet banget, amarga dibandhingake karo telpon fungsi biasa sing ditulis ing go, sing njupuk 1-5 nanodetik, prabédan ing kinerja kaping puluhan. Kanggo VictoriaMetrics iki minangka cacat fatal :)

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Dadi aku nulis implementasine dhewe saka indeks terbalik. Lan dheweke nimbali dheweke mergeset.

Mergeset adhedhasar struktur data MergeTree. Struktur data iki dipinjam saka ClickHouse. Temenan, mergeset kudu dioptimalake kanggo nggoleki kanthi cepet timeseries_ids miturut kunci sing diwenehake. Mergeset ditulis kabeh ing Go. Sampeyan bisa ndeleng Sumber VictoriaMetrics ing GitHub. Implementasine mergeset ana ing folder kasebut /lib/mergeset. Sampeyan bisa nyoba kanggo ngerteni apa sing kedadeyan ing kana.

API mergeset meh padha karo LevelDB lan RocksDB. Yaiku, ngidini sampeyan nyimpen cathetan anyar kanthi cepet ing kana lan kanthi cepet milih cathetan kanthi prefiks sing diwenehake.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Kita bakal ngomong babagan kekurangan mergeset mengko. Saiki ayo ngomong babagan masalah apa sing kedadeyan karo VictoriaMetrics ing produksi nalika ngetrapake indeks terbalik.

Yagene padha njedhul?

Alasan pisanan yaiku tingkat churn sing dhuwur. Diterjemahake menyang basa Rusia, iki minangka owah-owahan ing seri wektu. Iki nalika seri wektu rampung lan seri anyar diwiwiti, utawa akeh seri wektu anyar diwiwiti. Lan iki asring kedadeyan.

Alasan kapindho yaiku nomer akeh seri wektu. Ing wiwitan, nalika ngawasi saya populer, jumlah seri wektu cilik. Contone, kanggo saben komputer sampeyan kudu ngawasi CPU, memori, jaringan lan beban disk. 4 seri wektu saben komputer. Contone, sampeyan duwe 100 komputer lan 400 seri wektu. Iki sithik banget.

Sajrone wektu, wong ngerti yen bisa ngukur informasi sing luwih akeh. Contone, ngukur beban ora kabeh prosesor, nanging kanthi kapisah saka saben inti prosesor. Yen sampeyan duwe 40 intine prosesor, sampeyan duwe 40 kaping luwih seri wektu kanggo ngukur beban prosesor.

Nanging ora mung kuwi. Saben inti prosesor bisa duwe sawetara negara, kayata nganggur, nalika nganggur. Lan uga bisa digunakake ing ruang pangguna, kerja ing ruang kernel lan negara liya. Lan saben negara kasebut uga bisa diukur minangka seri wektu sing kapisah. Iki uga nambah jumlah larik kanthi 7-8 kaping.

Saka siji metrik entuk 40 x 8 = 320 metrik kanggo mung siji komputer. Multiply dening 100, kita entuk 32 tinimbang 000.

Banjur Kubernetes teka. Lan dadi luwih elek amarga Kubernetes bisa dadi tuan rumah macem-macem layanan. Saben layanan ing Kubernetes kasusun saka akeh pods. Lan kabeh iki kudu dipantau. Kajaba iku, kita duwe panyebaran terus-terusan versi anyar layanan sampeyan. Kanggo saben versi anyar, seri wektu anyar kudu digawe. Akibaté, jumlah seri wektu mundhak kanthi eksponensial lan kita ngadhepi masalah akeh seri wektu, sing diarani kardinalitas dhuwur. VictoriaMetrics bisa ngatasi kanthi sukses dibandhingake karo database seri wektu liyane.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ayo dideleng kanthi cetha babagan tingkat churn sing dhuwur. Apa sing nyebabake tingkat churn dhuwur ing produksi? Amarga sawetara makna label lan tag terus saya ganti.

Contone, njupuk Kubernetes, sing duwe konsep deployment, yaiku nalika versi anyar aplikasi sampeyan diluncurake. Kanggo sawetara alasan, pangembang Kubernetes mutusake nambahake id penyebaran menyang label kasebut.

Iki nyebabake apa? Kajaba iku, kanthi saben panyebaran anyar, kabeh seri wektu lawas diganggu, lan tinimbang, seri wektu anyar diwiwiti kanthi nilai label anyar. deployment_id. Ana bisa atusan ewu lan malah mayuta-yuta larik kuwi.

Sing penting babagan kabeh iki yaiku jumlah seri wektu mundhak, nanging jumlah seri wektu sing saiki aktif lan nampa data tetep tetep. Negara iki diarani tingkat churn dhuwur.

Masalah utama tingkat churn dhuwur yaiku njamin kacepetan telusuran sing tetep kanggo kabeh seri wektu kanggo label tartamtu sajrone interval wektu tartamtu. Biasane iki interval wektu kanggo jam pungkasan utawa dina pungkasan.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Carane ngatasi masalah iki? Punika pilihan pisanan. Iki kanggo dibagi indeks kuwalik menyang bagean independen liwat wektu. Yaiku, sawetara interval wektu liwati, kita rampung nggarap indeks terbalik saiki. Lan nggawe indeks kuwalik anyar. Liyane interval wektu liwat, kita nggawe liyane lan liyane.

Lan nalika sampling saka indeks kuwalik iki, kita nemokake pesawat saka indeks kuwalik sing ana ing interval tartamtu. Lan, miturut, kita milih id saka seri wektu saka ing kono.

Iki ngirit sumber daya amarga kita ora kudu ndeleng bagean sing ora ana ing interval sing diwenehake. Yaiku, biasane, yen kita milih data kanggo jam pungkasan, banjur kanggo interval wektu sadurunge kita ngliwati pitakon.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ana pilihan liyane kanggo ngatasi masalah iki. Iki kanggo nyimpen saben dina dhaptar kapisah saka id seri wektu sing kedadeyan ing dina kasebut.

Kauntungan saka solusi iki tinimbang solusi sadurunge yaiku kita ora nggawe duplikat informasi seri wektu sing ora ilang saka wektu. Padha tansah ana lan ora owah.

Kerugian yaiku solusi kasebut luwih angel ditindakake lan luwih angel kanggo debug. Lan VictoriaMetrics milih solusi iki. Iki kedadeyan historis. Solusi iki uga performa apik dibandhingake karo sing sadurunge. Amarga solusi iki ora dileksanakake amarga perlu kanggo duplikat data ing saben partisi kanggo seri wektu sing ora owah, yaiku sing ora ilang saka wektu. VictoriaMetrics utamane dioptimalake kanggo konsumsi ruang disk, lan implementasine sadurunge nggawe konsumsi ruang disk luwih elek. Nanging implementasine iki luwih cocog kanggo nyilikake konsumsi ruang disk, mula dipilih.

Aku kudu nglawan dheweke. Perjuangan yaiku ing implementasine sampeyan isih kudu milih nomer sing luwih gedhe timeseries_ids kanggo data tinimbang nalika indeks kuwalik wektu partisi.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Kepiye carane ngatasi masalah iki? Kita ngrampungake kanthi cara asli - kanthi nyimpen sawetara pengenal seri wektu ing saben entri indeks terbalik tinimbang siji pengenal. Yaiku, kita duwe kunci label=value, sing dumadi ing saben seri wektu. Lan saiki kita nyimpen sawetara timeseries_ids ing siji entri.

Punika conto. Sadurunge kita duwe entri N, nanging saiki kita duwe siji entri sing awalan padha karo kabeh liyane. Kanggo entri sadurunge, nilai kasebut ngemot kabeh id seri wektu.

Iki ndadekake iku bisa kanggo nambah kacepetan mindhai saka indeks kuwalik kuwi nganti 10 kaping. Lan ngidini kita ngurangi konsumsi memori kanggo cache, amarga saiki kita nyimpen senar label=value mung sapisan ing cache bebarengan N kaping. Lan baris iki bisa dadi gedhe yen sampeyan nyimpen garis dawa ing tags lan labels, kang Kubernetes seneng shove ana.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Pilihan liyane kanggo nyepetake telusuran ing indeks terbalik yaiku sharding. Nggawe sawetara indeks kuwalik tinimbang siji lan sharding data antarane wong-wong mau dening tombol. Iki minangka set key=value uap. Yaiku, kita entuk sawetara indeks terbalik independen, sing bisa ditakoni kanthi podo karo sawetara prosesor. Implementasi sadurunge mung ngidini operasi ing mode prosesor siji, yaiku, mindhai data mung siji inti. Solusi iki ngidini sampeyan mindhai data ing sawetara intine bebarengan, kaya sing disenengi ClickHouse. Iki sing arep ditindakake.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Saiki ayo bali menyang wedhus kita - menyang fungsi persimpangan timeseries_ids. Ayo nimbang apa implementasine bisa uga ana. Fungsi iki ngidini sampeyan nemokake timeseries_ids kanggo pesawat diwenehi label=value.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Opsi pisanan yaiku implementasine naif. Loro puteran nested. Ing kene kita entuk input fungsi intersectInts loro irisan - a и b. Ing output, iku kudu bali menyang kita persimpangan saka irisan-irisan iki.

A implementasine naif katon kaya iki. Kita ngulang kabeh nilai saka irisan a, ing daur ulang iki kita ngliwati kabeh nilai irisan b. Lan kita mbandhingake. Yen padha cocog, banjur kita wis ketemu prapatan. Lan nyimpen ing result.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Apa kekurangane? Kompleksitas kuadrat minangka kelemahan utama. Contone, yen dimensi sampeyan irisan a и b siji yuta ing wektu, banjur fungsi iki ora bakal bali jawaban kanggo sampeyan. Amarga kudu nggawe siji triliun iterasi, sing akeh banget kanggo komputer modern.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Implementasi kapindho adhedhasar peta. Kita nggawe peta. Kita sijine kabeh nilai saka irisan menyang peta iki a. Banjur kita ngliwati irisan ing daur ulang sing kapisah b. Lan kita mriksa apa nilai iki saka irisan b ing peta. Yen ana, banjur ditambahake menyang asil.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Apa keuntungane? Kauntungan iku mung ana kerumitan linier. Tegese, fungsi kasebut bakal ditindakake luwih cepet kanggo irisan sing luwih gedhe. Kanggo irisan ukuran yuta, fungsi iki bakal dileksanakake ing 2 yuta iterasi, minangka lawan saka triliun iterasi saka fungsi sadurunge.

Kekurangane yaiku fungsi iki mbutuhake memori luwih akeh kanggo nggawe peta iki.

Kekurangan kapindho yaiku overhead gedhe kanggo hashing. Kekurangan iki ora ketok banget. Lan kanggo kita uga ora ketok banget, mula ing VictoriaMetrics implementasine persimpangan kasebut ing peta. Nanging banjur profil nuduhake yen wektu prosesor utama ngginakaken nulis menyang peta lan mriksa anané nilai ing peta iki.

Napa wektu CPU boroske ing papan kasebut? Amarga Go nindakake operasi hashing ing baris kasebut. Yaiku, ngetung hash kunci supaya bisa ngakses ing indeks tartamtu ing HashMap. Operasi pitungan hash rampung ing puluhan nanodetik. Iki alon kanggo VictoriaMetrics.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Aku mutusaké kanggo ngleksanakake bitset optimized khusus kanggo kasus iki. Iki minangka persimpangan rong irisan saiki katon. Kene kita nggawe bitset. Kita nambah unsur saka irisan pisanan menyang. Banjur kita mriksa anané unsur kasebut ing irisan kapindho. Lan nambah menyang asil. Tegese, meh ora beda karo conto sadurunge. Siji-sijine ing kene yaiku ngganti akses menyang peta kanthi fungsi khusus add и has.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ing kawitan marketing, misale jek sing iki kudu luwih alon, yen sadurunge map standar digunakake ana, lan banjur sawetara fungsi liyane disebut, nanging profil nuduhake yen bab iki 10 kaping luwih cepet saka peta standar ing cilik saka VictoriaMetrics.

Kajaba iku, nggunakake memori akeh kurang dibandhingake implementasine map. Amarga kita nyimpen bit ing kene tinimbang nilai wolung bait.

Kerugian saka implementasine iki yaiku ora pati jelas, ora sepele.

Kelemahan liyane sing ora dingerteni akeh yaiku implementasine iki bisa uga ora bisa digunakake ing sawetara kasus. Yaiku, dioptimalake kanggo kasus tartamtu, kanggo kasus persimpangan id seri wektu VictoriaMetrics. Iki ora ateges cocog kanggo kabeh kasus. Yen digunakake kanthi ora bener, kita ora bakal entuk peningkatan kinerja, nanging kesalahan memori lan mudhun kinerja.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ayo nimbang implementasine saka struktur iki. Yen sampeyan pengin katon, dumunung ing sumber VictoriaMetrics, ing folder lib/uint64set. Iki dioptimalake khusus kanggo kasus VictoriaMetrics, ing ngendi timeseries_id punika Nilai 64-dicokot, ngendi pisanan 32 bit Sejatine pancet lan mung 32 bit pungkasan diganti.

Struktur data iki ora disimpen ing disk, mung dianggo ing memori.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Punika API sawijining. Ora rumit banget. API dirancang khusus kanggo conto tartamtu saka nggunakake VictoriaMetrics. Tegese, ora ana fungsi sing ora perlu ing kene. Iki minangka fungsi sing digunakake kanthi jelas dening VictoriaMetrics.

Ana fungsi add, sing nambah nilai anyar. Ana fungsi has, sing mriksa nilai anyar. Lan ana fungsi del, sing mbusak nilai. Ana fungsi helper len, sing ngasilake ukuran set. Fungsi clone klone akeh. Lan fungsi appendto ngowahi set iki dadi irisan timeseries_ids.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Iki minangka implementasine struktur data iki. set nduweni rong unsur:

  • ItemsCount iku lapangan helper kanggo cepet bali nomer unsur ing pesawat. Sampeyan bisa nindakake tanpa lapangan tambahan iki, nanging kudu ditambahake ing kene amarga VictoriaMetrics asring takon dawa bitset ing algoritma.

  • Lapangan kapindho yaiku buckets. Iki minangka potongan saka struktur bucket32. Saben struktur nyimpen hi lapangan. Iki minangka 32 bit ndhuwur. Lan rong irisan - b16his и buckets saka bucket16 struktur.

16 bit paling ndhuwur saka bagean kapindho struktur 64-bit disimpen ing kene. Lan ing kene bitsets disimpen kanggo 16 bit ngisor saben bait.

Bucket64 kasusun saka array uint64. Dawane diitung kanthi nggunakake konstanta kasebut. Ing siji bucket16 maksimum bisa disimpen 2^16=65536 dicokot. Yen dibagi 8, iku 8 kilobyte. Yen dibagi 8 maneh, dadi 1000 uint64 artine. Iku Bucket16 - iki struktur 8-kilobyte kita.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Ayo goleki carane salah sawijining metode struktur iki kanggo nambah nilai anyar ditindakake.

Iku kabeh diwiwiti karo uint64 tegesipun. Kita ngetung 32 bit ndhuwur, kita ngetung 32 bit ngisor. Ayo liwat kabeh buckets. Kita mbandhingake 32 bit ndhuwur ing saben ember kanthi nilai sing ditambahake. Lan yen padha cocog, banjur kita nelpon fungsi add ing struktur b32 buckets. Lan nambah 32 bit ngisor ana. Lan yen bali true, banjur iki tegese kita nambahake nilai kasebut ing kana lan kita ora duwe nilai kasebut. Yen bali false, banjur teges kang kaya mangkono iku wis ana. Banjur kita nambah jumlah unsur ing struktur.

Yen kita durung nemokake sing sampeyan butuhake bucket karo hi-nilai dibutuhake, banjur kita nelpon fungsi addAlloc, sing bakal ngasilake sing anyar bucket, nambahake menyang struktur ember.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Iki minangka implementasi saka fungsi kasebut b32.add. Iku padha karo implementasine sadurunge. Kita ngetung paling signifikan 16 bit, paling signifikan 16 bit.

Banjur kita ngliwati kabeh 16 bit ndhuwur. We golek cocog. Lan yen ana match, kita nelpon cara nambah, kang bakal nimbang ing kaca sabanjuré kanggo bucket16.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Lan ing kene tingkat paling murah, sing kudu dioptimalake sabisa. We ngitung kanggo uint64 nilai id ing irisan bit lan uga bitmask. Iki minangka topeng kanggo nilai 64-bit sing diwenehake, sing bisa digunakake kanggo mriksa anané bit iki, utawa nyetel. Kita mriksa apa dicokot iki disetel lan nyetel, lan bali ngarsane. Iki minangka implementasine, sing ngidini kita nyepetake operasi intersecting id saka seri wektu kanthi kaping 10 dibandhingake karo peta konvensional.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Saliyane optimasi iki, VictoriaMetrics nduweni akeh optimasi liyane. Umume optimasi kasebut ditambahake kanthi alesan, nanging sawise nggawe profil kode ing produksi.

Iki minangka aturan utama optimasi - aja nambah optimasi yen bakal ana bottleneck ing kene, amarga bisa uga ora ana bottleneck ing kana. Optimasi biasane ngrusak kualitas kode. Mulane, iku worth ngoptimalake mung sawise profiling lan luwih ing produksi, supaya iki data nyata. Yen ana sing kasengsem, sampeyan bisa ndeleng kode sumber VictoriaMetrics lan njelajah optimasi liyane sing ana.

Go optimizations ing VictoriaMetrics. Alexander Valyalkin

Aku duwe pitakonan babagan bitset. Banget padha karo implementasine bool vektor C ++, bitset optimized. Apa sampeyan njupuk implementasine saka kono?

Ora, ora saka kono. Nalika ngleksanakake bitset iki, Aku iki dipandu dening kawruh saka struktur ids timeseries iki, kang digunakake ing VictoriaMetrics. Lan strukture kaya sing 32 bit ndhuwur pancen tetep. 32 bit ngisor bisa diganti. Ing ngisor bit, luwih kerep bisa diganti. Mulane, implementasine iki khusus dioptimalake kanggo struktur data iki. C ++ implementasine, minangka adoh aku ngerti, optimized kanggo kasus umum. Yen sampeyan ngoptimalake kasus umum, iki tegese ora bakal dadi sing paling optimal kanggo kasus tartamtu.

Aku uga menehi saran supaya nonton laporan Alexey Milovid. Kira-kira sasi kepungkur, dheweke ngomong babagan optimasi ing ClickHouse kanggo spesialisasi tartamtu. Dheweke mung ujar manawa ing kasus umum, implementasi C ++ utawa sawetara implementasine liyane dicocogake kanthi rata-rata ing rumah sakit. Bisa uga luwih elek tinimbang implementasine khusus kawruh kaya kita, sing ngerti yen 32 bit paling dhuwur biasane tetep.

Aku duwe pitakonan kapindho. Apa prabédan dhasar saka InfluxDB?

Ana akeh beda dhasar. Ing babagan kinerja lan konsumsi memori, InfluxDB ing tes nuduhake 10 kaping konsumsi memori kanggo seri wektu cardinality dhuwur, nalika sampeyan duwe akeh, contone, yuta. Contone, VictoriaMetrics nggunakake 1 GB saben yuta baris aktif, nalika InfluxDB nganggo 10 GB. Lan sing prabédan amba.

Bentenane dhasar kapindho yaiku InfluxDB duwe basa pitakon aneh - Flux lan InfluxQL. Padha ora trep banget kanggo nggarap seri wektu dibandhingake karo PromQL, sing didhukung dening VictoriaMetrics. PromQL minangka basa pitakon saka Prometheus.

Lan prabédan liyane yaiku InfluxDB duwe model data sing rada aneh, ing ngendi saben baris bisa nyimpen sawetara kolom kanthi tag sing beda. Garis iki dipérang manèh dadi macem-macem tabel. Komplikasi tambahan iki nggawe rumit karya sabanjure karo database iki. Iku angel kanggo ndhukung lan ngerti.

Ing VictoriaMetrics kabeh luwih gampang. Ing kana, saben seri wektu minangka nilai kunci. Nilai kasebut minangka set poin - (timestamp, value), lan kuncine yaiku set label=value. Ora ana pamisahan antarane lapangan lan pangukuran. Iku ngijini sampeyan kanggo milih data lan banjur gabungke, nambah, nyuda, Multiply, dibagi, ora kaya InfluxDB ngendi petungan antarane larik beda isih ora dipun ginakaken minangka adoh aku ngerti. Malah yen lagi dipun ginakaken, iku angel, sampeyan kudu nulis akeh kode.

Aku duwe pitakonan clarifying. Apa aku ngerti kanthi bener yen ana sawetara masalah sing sampeyan gunakake, yen indeks terbalik iki ora cocog karo memori, mula ana pemisahan?

Kaping pisanan, aku nuduhake implementasi naif saka indeks terbalik ing peta Go standar. Implementasine iki ora cocok kanggo database amarga indeks kuwalik iki ora disimpen ing disk, lan database kudu disimpen ing disk supaya data iki tetep kasedhiya nalika miwiti maneh. Ing implementasine iki, nalika sampeyan miwiti maneh aplikasi, indeks kuwalik bakal ilang. Lan sampeyan bakal kelangan akses menyang kabeh data amarga sampeyan ora bakal bisa nemokake iku.

Hello! Matur nuwun kanggo laporan! Jenengku Pavel. Aku saka Wildberries. Aku duwe sawetara pitakonan kanggo sampeyan. Pitakonan siji. Apa sampeyan mikir yen sampeyan milih prinsip sing beda nalika mbangun arsitektur aplikasi sampeyan lan misahake data saka wektu, mula sampeyan bisa uga bisa intersect data nalika nggoleki, mung adhedhasar kasunyatan sing siji partisi ngemot data kanggo siji. periode wektu , yaiku, ing interval wektu lan sampeyan ora kudu kuwatir yen potongan sampeyan kasebar kanthi beda? Pitakonan nomer 2 - amarga sampeyan ngetrapake algoritma sing padha karo bitset lan liya-liyane, mula sampeyan bisa uga nyoba nggunakake instruksi prosesor? Mungkin sampeyan wis nyoba optimasi kasebut?

Aku bakal mangsuli sing nomer loro langsung. Kita durung tekan titik kasebut. Nanging yen perlu, kita bakal teka. Lan sing pisanan, apa pitakonan?

Sampeyan ngrembug rong skenario. Lan dheweke ujar manawa milih sing nomer loro kanthi implementasine sing luwih rumit. Lan dheweke ora seneng karo sing pertama, ing ngendi data dipisahake kanthi wektu.

ya wis. Ing kasus sing sepisanan, volume total indeks bakal luwih gedhe, amarga ing saben partisi kita kudu nyimpen data duplikat kanggo seri wektu sing terus liwat kabeh partisi kasebut. Lan yen tingkat churn seri wektu sampeyan cilik, yaiku seri sing padha terus digunakake, mula ing kasus sing sepisanan, jumlah ruang disk sing dikuwasani luwih akeh tinimbang kasus liyane.

Lan - ya, pemisahan wektu minangka pilihan sing apik. Prometheus nggunakake. Nanging Prometheus duwe kekurangan liyane. Nalika nggabungake potongan data kasebut, sampeyan kudu nyimpen informasi meta memori kanggo kabeh label lan seri wektu. Mulane, yen potongan-potongan data sing digabungake gedhe, konsumsi memori mundhak banget nalika gabung, ora kaya VictoriaMetrics. Nalika gabung, VictoriaMetrics ora nganggo memori babar pisan; mung sawetara kilobyte sing dikonsumsi, preduli saka ukuran potongan data sing digabung.

Algoritma sing sampeyan gunakake nggunakake memori. Nandhani tag timeseries sing ngemot nilai. Lan kanthi cara iki sampeyan mriksa ngarsane sing dipasangake ing siji array data lan ing liyane. Lan sampeyan ngerti apa intersect dumadi utawa ora. Biasane, database ngleksanakake kursor lan iterator sing nyimpen isi sing saiki lan mbukak liwat data diurutake amarga kerumitan prasaja saka operasi iki.

Napa kita ora nggunakake kursor kanggo ngliwati data?

Ya.

Kita nyimpen baris sing diurutake ing LevelDB utawa mergeset. Kita bisa mindhah kursor lan nemokake prapatan. Apa kita ora nggunakake? Amarga iku alon. Amarga kursor tegese sampeyan kudu nelpon fungsi kanggo saben baris. Panggilan fungsi yaiku 5 nanodetik. Lan yen sampeyan duwe 100 baris, banjur dadi metu sing kita nglampahi setengah detik mung nelpon fungsi.

Ana sing kaya ngono, ya. Lan pitakonan pungkasan. Pitakonan kasebut bisa uga rada aneh. Napa ora bisa maca kabeh agregat sing dibutuhake nalika data teka lan disimpen ing formulir sing dibutuhake? Napa nyimpen volume gedhe ing sawetara sistem kaya VictoriaMetrics, ClickHouse, lan liya-liyane, banjur mbuwang wektu akeh?

Aku bakal menehi conto supaya luwih jelas. Ayo ngomong carane spedometer dolanan cilik bisa digunakake? Iku nyathet jarak sing wis sampeyan lelungan, kabeh wektu ditambahake menyang siji nilai, lan kaping pindho. Lan dibagi. Lan entuk kacepetan rata-rata. Sampeyan bisa nindakake bab sing padha. Tambah munggah kabeh bukti perlu ing fly.

Oke, aku ngerti pitakonan. Conto sampeyan duwe panggonan. Yen sampeyan ngerti agregat apa sing sampeyan butuhake, mula iki minangka implementasine sing paling apik. Nanging masalahe yaiku wong nyimpen metrik kasebut, sawetara data ing ClickHouse lan durung ngerti carane bakal ngumpulake lan nyaring ing mangsa ngarep, mula kudu nyimpen kabeh data mentah. Nanging yen sampeyan ngerti sampeyan kudu ngetung rata-rata, mula kenapa ora ngetung tinimbang nyimpen akeh nilai mentah ing kana? Nanging iki mung yen sampeyan ngerti persis apa sing sampeyan butuhake.

Miturut cara, database kanggo nyimpen seri wektu ndhukung pancacahan agregat. Contone, Prometheus ndhukung aturan ngrekam. Yaiku, iki bisa ditindakake yen sampeyan ngerti unit apa sing dibutuhake. VictoriaMetrics durung duwe iki, nanging biasane didhisiki dening Prometheus, sing bisa ditindakake ing aturan recoding.

Contone, ing proyek sadurunge aku kudu ngetung jumlah acara ing jendela geser sajrone jam pungkasan. Masalah iku aku kudu nggawe implementasine adat ing Go, IE layanan kanggo ngetang bab iki. Layanan iki pungkasane ora pati penting, amarga angel ngetung. Implementasine bisa gampang yen sampeyan kudu ngetung sawetara agregat kanthi interval wektu sing tetep. Yen sampeyan pengin ngetung acara ing jendela geser, mula ora gampang kaya sing katon. Aku iki durung dileksanakake ing ClickHouse utawa ing timeseries database, amarga iku angel kanggo ngleksanakake.

Lan pitakonan liyane. Kita mung ngomong babagan rata-rata, lan aku eling yen ana sing kaya Graphite karo backend Carbon. Lan dheweke ngerti carane tipis data lawas, yaiku, ninggalake siji titik saben menit, siji titik saben jam, lan liya-liyane. dadi tipis. Nanging Prometheus lan VictoriaMetrics ora ndhukung fungsi iki. Apa direncanakake kanggo ndhukung? Yen ora, kenapa ora?

Matur nuwun kanggo pitakonan. Pangguna kita takon pitakonan iki sacara periodik. Dheweke takon nalika kita bakal nambah dhukungan kanggo downsampling. Ana sawetara masalah ing kene. Kaping pisanan, saben pangguna ngerti downsampling soko beda: wong pengin njaluk sembarang titik kasepakatan ing interval tartamtu, wong pengin maksimum, minimal, nilai rata-rata. Yen akeh sistem nulis data menyang database, sampeyan ora bisa ngumpulake kabeh. Bisa uga saben sistem mbutuhake thinning sing beda. Lan iki angel dileksanakake.

Lan sing nomer loro yaiku VictoriaMetrics, kaya ClickHouse, dioptimalake kanggo nggarap data mentah sing akeh, saengga bisa nyopot milyaran baris kurang saka detik yen sampeyan duwe akeh inti ing sistem sampeyan. Pindai titik seri wektu ing VictoriaMetrics - 50 poin per detik per inti. Lan kinerja iki ukuran kanggo inti ana. Yaiku, yen sampeyan duwe 000 intine, contone, sampeyan bakal mindai milyar poin per detik. Lan property VictoriaMetrics lan ClickHouse iki nyuda perlu kanggo downsamling.

Fitur liyane yaiku VictoriaMetrics kanthi efektif ngompres data iki. Kompresi rata-rata ing produksi yaiku saka 0,4 nganti 0,8 bita saben titik. Saben titik minangka tandha wektu + nilai. Lan dikompres dadi kurang saka siji bait rata-rata.

Sergey. Aku duwe pitakonan. Apa kuantum wektu rekaman minimal?

Siji milidetik. Kita bubar ngobrol karo pangembang database seri wektu liyane. Irisan wektu minimal siji detik. Lan ing Grafit, contone, uga siji detik. Ing OpenTSDB uga siji detik. InfluxDB nduweni presisi nanodetik. Ing VictoriaMetrics iku siji milidetik, amarga ing Prometheus iku siji milidetik. Lan VictoriaMetrics wiwitane dikembangake minangka panyimpenan remot kanggo Prometheus. Nanging saiki bisa nyimpen data saka sistem liyane.

Wong sing dakkandhakake ujar manawa dheweke duwe akurasi kaping pindho - cukup kanggo dheweke amarga gumantung saka jinis data sing disimpen ing database seri wektu. Yen iki data DevOps utawa data saka infrastruktur, ing ngendi sampeyan ngumpulake kanthi interval 30 detik, saben menit, banjur akurasi detik cukup, sampeyan ora butuh apa-apa. Lan yen sampeyan ngumpulake data iki saka sistem dagang frekuensi dhuwur, sampeyan butuh akurasi nanodetik.

Akurasi Millisecond ing VictoriaMetrics uga cocog kanggo kasus DevOps, lan bisa uga cocog kanggo umume kasus sing dakkandhakake ing wiwitan laporan. Siji-sijine sing bisa uga ora cocog yaiku sistem dagang frekuensi dhuwur.

Matur nuwun! Lan pitakonan liyane. Apa kompatibilitas ing PromQL?

Kompatibilitas mundur lengkap. VictoriaMetrics ndhukung PromQL kanthi lengkap. Kajaba iku, nambah fungsi majeng tambahan ing PromQL, kang disebut MetricsQL. Ana dhiskusi ing YouTube babagan fungsi lengkap iki. Aku ngandika ing Meetup ngawasi ing spring ing St.

Saluran telegram VictoriaMetrics.

Mung pangguna pangguna sing bisa melu survey. mlebunggih.

Apa sing ngalangi sampeyan ngalih menyang VictoriaMetrics minangka panyimpenan jangka panjang kanggo Prometheus? (Tulis ing komentar, aku bakal nambah menyang polling))

  • 71,4%Aku ora nggunakake Prometheus5

  • 28,6%Ora ngerti babagan VictoriaMetrics2

7 pangguna milih. 12 kedhaftar abstained.

Source: www.habr.com

Add a comment