
Baza e të dhënave të serive të kohës (TSDB, time series database) në Prometheus 2 është një shembull i shkëlqyer i një zgjidhjeje inxhinierike, e cila ofron përmirësime të rëndësishme krahasuar me magazinimin v2 në Prometheus 1 në aspektin e shpejtësisë së akumulimit të të dhënave dhe ekzekutimit të pyetjeve, si dhe efikasitetit të përdorimit të burimeve. Ne kemi implementuar Prometheus 2 në Percona Monitoring and Management (PMM), dhe unë kam pasur mundësinë të kuptoj performancën e TSDB të Prometheus 2. Në këtë artikull, do të ndaj rezultatet e këtij vëzhgimi.
Mësynimi mesatar i ngarkesës për Prometheus
Për ata që janë mësuar me punën me databaza për qëllime të përgjithshme, ngarkesa e zakonshme për Prometheus është mjaft intriguese. Shpejtësia e akumulimit të të dhënave ka tendencë për tu stabilizuar: zakonisht shërbimet që monitoroni dërgojnë një numër të ngjashëm metrikash, dhe infrastruktura ndryshon relativisht ngadalë.
Kërkesat për informacion mund të vijnë nga burime të ndryshme. Disa prej tyre, siç janë alarmet, gjithashtu kanë tendencë të jenë të stabilizuara dhe parashikueshme. Të tjerat, si kërkesat e përdoruesve, mund të shkaktojnë shpërthime, megjithatë, kjo nuk është karakteristikë për pjesën më të madhe të ngarkesës.
Testi i ngarkesës
Gjatë testimit, u përqendrova në aftësinë për të akumuluar të dhëna. Unë vendosa të përdor Prometheus 2.3.2, i ndërtuar me Go 1.10.1 (si pjesë e PMM 1.14) në shërbimin Linode, duke përdorur këtë skript: . Për të gjeneruar ngarkesën sa më realiste, duke përdorur këtë unë aktivizova disa node MySQL me ngarkesë reale (Testi TPC-C i Sysbench), secili prej të cilëve imitoi 10 node Linux/MySQL.
Të gjitha testet e mëposhtme u kryen në serverin Linode me tetë bërthama virtuale dhe 32 GB memorie, ku u aktivizuan 20 simulime të ngarkesës duke monitoruar dyqind instanca MySQL. Ose, në terma të Prometheus, 800 cible (targets), 440 grumbuj (scrapes) për sekondë, 380 mijë regjistrime (samples) për sekondë dhe 1,7 milion seria aktive të kohës.
Dizajni
Qasja e zakonshme e databazave tradicionale, përfshirë atë që përdorte Prometheus 1.x, është . Nëse nuk ka mjaftueshëm, për të përballuar ngarkesën, ju do të përballeni me vonesa të mëdha, dhe disa kërkesa nuk do të plotësohen. Përdorimi i memories në Prometheus 2 konfigurohet përmes çelësit storage.tsdb.min-block-duration, i cili përcakton se sa gjatë regjistrimet do të mbahen në memorie përpara se të shkarkohen në disk (me përjashtim, kjo është 2 orë). Sasia e memories që nevojitet do të varet nga numri i serive të kohës, etiketimeve (labels) dhe intensitetit të grumbullimit të të dhënave (scrapes) së bashku me fluksin e pastër të hyrjes. Në aspektin e hapësirës disk, Prometheus ka tendencë të përdorë 3 bytes për regjistrim (sample). Nga ana tjetër, kërkesat për memorie janë shumë më të larta.
Megjithatë, ndonëse ka mundësinë për të konfiguruar madhësinë e bllokut, nuk rekomandohet ta rregulloni manualisht, prandaj ju vijnë përpara nevojës për t'i dhënë Prometheus aq memorie sa ai kërkon për ngarkesën tuaj.
Nëse memorie nuk është e mjaftueshme për të mbështetur fluksin e hyrjes së metrikeve, Prometheus do të bjerë me 'out of memory' ose do ta arrijë OOM killer.
Shtimi i swap-it për të vonuar momentin e rënies, kur Prometheus përfundon memorien, nuk ndihmon shumë, sepse përdorimi i këtij funksioni shkakton një konsum të shpejtë të memories. Mendoj se kjo lidhet me Go, kolektorin e tij të mbeturinave dhe me mënyrën si ai punon me swap.
Një qasje tjetër interesante duket të jetë caktimi i shëtitjes së bllokut kryesor në disk në një kohë të caktuar, në vend që ta llogarisni nga koha e nisjes së procesit.

Siç mund ta shihni nga grafiku, shkarkimet në disk ndodhin çdo dy orë. Nëse e ndryshoni parametrin min-block-duration në një orë, këto shkarkime do të ndodhin çdo orë, duke filluar pas gjysmë ore.
Nëse dëshironi të përdorni këtë dhe grafika të tjera në instalimin tuaj të Prometheus, mund të përdorni këtë . Ai është projektuar për PMM, por me disa ndryshime të vogla, është i përshtatshëm për çdo instalim të Prometheus.
Kemi një bllok aktiv të quajtur bllok kryesor, i cili ruhet në memorie; blloqet me të dhëna më të vjetra janë të aksesueshme përmes mmap(). Kjo heq nevojën për të konfiguruar cache-në veçmas, por gjithashtu do të thotë se duhet të lini mjaft hapësirë për cache-në e sistemit operativ, nëse dëshironi të bëni pyetje për të dhënat më të vjetra se ato që përfshihen në bllokun kryesor.
Gjithashtu, kjo do të thotë se konsumimi i memorjes virtuale të Prometheus do të duket mjaft i lartë, për të cilin nuk duhet të shqetësoheni.

Një tjetër aspekt interesant i dizajnit është përdorimi i WAL (write ahead log). Siç tregohet në dokumentacionin e ruajtjes, Prometheus përdor WAL për të shmangur humbjet gjatë rënieve. Mekanizmat specifikë të garantimit të qëndrueshmërisë së të dhënave, fatkeqësisht, nuk janë dokumentuar në mënyrë të mjaftueshme. Versioni Prometheus 2.3.2 regjistron WAL në disk çdo 10 sekonda, dhe ky parametër nuk është konfigurohet nga përdoruesi.
Kompaktimet
Prometheus TSDB është projektuar sipas modelit të magazinës LSM (Log Structured Merge): blloku kokë derdhet rregullisht në disk, ndërkohë që mekanizmi i kompaktimit bashkon disa blloqe së bashku për të shmangur skanimin e një numri të madh bllokesh gjatë kërkesave. Këtu shihet numri i bllokëve që kam observuar në sistemin testues pas një dite ngarkese.

Nëse dëshironi të dini më shumë rreth ruajtjes, mund të shqyrtoni skedarin meta.json, në të cilin ka informacione për blloqet ekzistuese dhe si janë krijuar ato.
{
"ulid": "01CPZDPD1D9R019JS87TPV5MPE",
"minTime": 1536472800000,
"maxTime": 1536494400000,
"stats": {
"numSamples": 8292128378,
"numSeries": 1673622,
"numChunks": 69528220
},
"compaction": {
"level": 2,
"sources": [
"01CPYRY9MS465Y5ETM3SXFBV7X",
"01CPYZT0WRJ1JB1P0DP80VY5KJ",
"01CPZ6NR4Q3PDP3E57HEH760XS"
],
"parents": [
{
"ulid": "01CPYRY9MS465Y5ETM3SXFBV7X",
"minTime": 1536472800000,
"maxTime": 1536480000000
},
{
"ulid": "01CPYZT0WRJ1JB1P0DP80VY5KJ",
"minTime": 1536480000000,
"maxTime": 1536487200000
},
{
"ulid": "01CPZ6NR4Q3PDP3E57HEH760XS",
"minTime": 1536487200000,
"maxTime": 1536494400000
}
]
},
"version": 1
}Kompaktimet në Prometheus janë të lidhura me kohën kur blloku kokë derdhet në disk. Në këtë moment mund të kryhen disa operacione të tilla.

Duket se kompaktimet nuk kanë ndonjë kufizim dhe mund të shkaktojnë rritje të mëdha në I/O-në e diskut gjatë ekzekutimit.

Rritjet e ngarkesës së CPU-së

Natyrisht, kjo ndikon negativisht në shpejtësinë e funksionimit të sistemit dhe paraqet një sfidë të madhe për magazinat LSM: si të bëjmë kompaktimet për të mbështetur një shpejtësi të lartë kërkesash dhe në të njëjtën kohë të mos shkaktojmë shumë overhead?
Përdorimi i memories gjatë kompaktimeve gjithashtu duket mjaft interesant.

Mund tĂ« shohim se pas kompaktimit, pjesa mĂ« e madhe e memories kalon nga Cached nĂ« Free: do tĂ« thotĂ« se informacione potencialisht tĂ« vlefshme janĂ« hequr nga aty. ĂshtĂ« e çuditshme nĂ«se pĂ«rdoret kĂ«tu fadvice() apo ndonjĂ« teknikĂ« tjetĂ«r minimizimi, apo Ă«shtĂ« shkaktuar nga fakti se cache u çlirua nga blloket qĂ« u shĂ«mbĂ«n gjatĂ« kompaktimit?
Rivendosja pas dështimit
Rikuperimi pas dështimeve merr kohë, dhe kjo është e arsyeshme. Për një fluks hyrës të një milioni regjistrash në sekondë, më duhej të prisja rreth 25 minuta derisa të përshtatej rikuperimi duke marrë parasysh diskun SSD.
level=info ts=2018-09-13T13:38:14.09650965Z caller=main.go:222 msg="Duke Prometheus" version="(version=2.3.2, branch=v2.3.2, revision=71af5e29e815795e9dd14742ee7725682fa14b7b)"
level=info ts=2018-09-13T13:38:14.096599879Z caller=main.go:223 build_context="(go=go1.10.1, user=Jenkins, date=20180725-08:58:13OURCE)"
level=info ts=2018-09-13T13:38:14.096624109Z caller=main.go:224 host_details="(Linux 4.15.0-32-generic #35-Ubuntu SMP Fri Aug 10 17:58:07 UTC 2018 x86_64 1bee9e9b78cf (none))"
level=info ts=2018-09-13T13:38:14.096641396Z caller=main.go:225 fd_limits="(soft=1048576, hard=1048576)"
level=info ts=2018-09-13T13:38:14.097715256Z caller=web.go:415 component=web msg="Fill available connections" address=:9090
level=info ts=2018-09-13T13:38:14.097400393Z caller=main.go:533 msg="Starting TSDB ..."
level=info ts=2018-09-13T13:38:14.098718401Z caller=repair.go:39 component=tsdb msg="discovered healthy block" mint=1536530400000 maxt=1536537600000 ulid=01CQ0FW3ME8Q5W2AN5F9CB7R0R
level=info ts=2018-09-13T13:38:14.100315658Z caller=web.go:467 component=web msg="router prefix" prefix=/prometheus
level=info ts=2018-09-13T13:38:14.101793727Z caller=repair.go:39 component=tsdb msg="discovered healthy block" mint=1536732000000 maxt=1536753600000 ulid=01CQ78486TNX5QZTBF049PQHSM
level=info ts=2018-09-13T13:38:14.102267346Z caller=repair.go:39 component=tsdb msg="discovered healthy block" mint=1536537600000 maxt=1536732000000 ulid=01CQ78DE7HSQK0C0F5AZ46YGF0
level=info ts=2018-09-13T13:38:14.102660295Z caller=repair.go:39 component=tsdb msg="discovered healthy block" mint=1536775200000 maxt=1536782400000 ulid=01CQ7SAT4RM21Y0PT5GNSS146Q
level=info ts=2018-09-13T13:38:14.103075885Z caller=repair.go:39 component=tsdb msg="discovered healthy block" mint=1536753600000 maxt=1536775200000 ulid=01CQ7SV8WJ3C2W5S3RTAHC2GHB
level=error ts=2018-09-13T14:05:18.208469169Z caller=wal.go:275 component=tsdb msg="WAL corruption detected; truncating" err="unexpected CRC32 checksum d0465484, want 0" file=/opt/prometheus/data/.prom2-data/wal/007357 pos=15504363
level=info ts=2018-09-13T14:05:19.471459777Z caller=main.go:543 msg="TSDB started"
level=info ts=2018-09-13T14:05:19.471604598Z caller=main.go:603 msg="Loading configuration file" filename=/etc/prometheus.yml
level=info ts=2018-09-13T14:05:19.499156711Z caller=main.go:629 msg="Completed loading of configuration file" filename=/etc/prometheus.yml
level=info ts=2018-09-13T14:05:19.499228186Z caller=main.go:502 msg="Server is ready to receive web requests."Problemi kryesor i procesit të rikuperimit është konsumimi i lartë i memories. Megjithëse në situata normale serveri mund të funksionojë stabël me të njëjtin sasi memories, gjatë rënies nuk mund të ngrihet për shkak të OOM. Zgjidhja e vetme që kam gjetur është të çaktivizoj mbledhjen e të dhënave, të ngre serverin, t'i lejoj atij të rikuperohet dhe të ri-ngre me mbledhjen e aktivizuar.
Ngrohje
Një tjetër sjellje që duhet mbajtur mend gjatë procesit të ngrohjes është raporti mes performancës së ulët dhe konsumit të lartë të burimeve sapo fillon. Gjatë disa, por jo të gjitha fillimeve, kam vërejtur një ngarkesë të rëndë në CPU dhe memory.


Rëniet në përdorimin e memories tregojnë se Prometheus nuk mund të konfigurojë të gjitha mbledhjet nga fillimi dhe disa informacione humbasin.
Nuk kam arritur të zbuloj shkaqet e sakta të ngarkesës së lartë në procesor dhe memory. Dyshoj se kjo është e lidhur me krijimin e rreshtave të rinj të dhënash në bllokun kryesor me një frekuencë të lartë.
Shkallëzimet e ngarkesës në CPU
Përveç ngjeshjeve që krijojnë një ngarkesë të lartë në I/O, kam vërejtur ngritje të këtyre ngarkesave në procesor çdo dy minuta. Shtytjet zgjaten më shumë me një fluks të lartë hyrës dhe duket se ato shkaktohen nga mbledhësi i plehrave Go, të paktën disa bërthama janë plotësisht të ngarkuara.


Këto ngritje nuk janë të parëndësishme. Duket se kur ato ndodhin, pika e brendshme e hyrjes dhe metrikat e Prometheus bëhen të paprekshme, duke shkaktuar humbje të të dhënave gjatë këtyre periudhave.

Gjithashtu mund të vërehet se eksportuesi Prometheus bllokohet për një sekondë.

Mund të vërejmë korelacionet me pastrimin e plehrave (GC).

Përfundimi
TSDB në Prometheus 2 vepron shpejt, është në gjendje të menaxhojë miliona rreshta të dhënash dhe në të njëjtën kohë mijëra regjistrime për sekondë, duke përdorur një harduer relativisht modest. Shfrytëzimi i CPU dhe I/O gjithashtu është impresionues. Shembulli im tregoi deri në 200,000 metrika për sekondë për çdo bërthamë të përdorur.
Kur planifikohet zgjerimi, duhet të mbahet parasysh një sasi e mjaftueshme memories, dhe kjo duhet të jetë memorie e vërtetë. Sasia e memories që kam vërejtur ishte rreth 5 GB për 100,000 regjistrime për sekondë të fluksit hyrës, duke sjellë një total prej rreth 8 GB të memories së zënë me caches të sistemit operativ.
Natyrisht, ende ka shumë punë për të kontrolluar shkallëzimet e CPU dhe I/O, dhe kjo nuk është e habitshme, duke marrë parasysh sa e re është TSDB Prometheus 2 krahasuar me InnoDB, TokuDB, RocksDB, WiredTiger, por të gjitha ato kishin probleme të ngjashme në fillim të ciklit të jetës.
Burimi: habr.com
