Analiza TSDB în Prometheus 2

Analiza TSDB în Prometheus 2

Baza de date în serie de timp (TSDB) din Prometheus 2 este un exemplu excelent de soluție de inginerie care oferă îmbunătățiri majore față de stocarea v2 din Prometheus 1 în ceea ce privește viteza de acumulare a datelor, execuția interogărilor și eficiența resurselor. Implementam Prometheus 2 în Percona Monitoring and Management (PMM) și am avut ocazia să înțeleg performanța Prometheus 2 TSDB. În acest articol voi vorbi despre rezultatele acestor observații.

Volumul mediu de lucru Prometheus

Pentru cei obișnuiți să se ocupe de baze de date de uz general, volumul de lucru tipic Prometheus este destul de interesant. Rata de acumulare a datelor tinde să fie stabilă: de obicei serviciile pe care le monitorizați trimit aproximativ același număr de metrici, iar infrastructura se modifică relativ lent.
Solicitările de informații pot veni din diverse surse. Unele dintre ele, cum ar fi alertele, se străduiesc, de asemenea, pentru o valoare stabilă și previzibilă. Altele, cum ar fi solicitările utilizatorilor, pot provoca explozii, deși acest lucru nu este cazul pentru majoritatea sarcinilor de lucru.

Test de încărcare

În timpul testării, m-am concentrat pe capacitatea de a acumula date. Am implementat Prometheus 2.3.2 compilat cu Go 1.10.1 (ca parte a PMM 1.14) pe serviciul Linode folosind acest script: StackScript. Pentru generarea de sarcină cea mai realistă, folosind aceasta StackScript Am lansat mai multe noduri MySQL cu o încărcare reală (Sysbench TPC-C Test), fiecare dintre ele emulând 10 noduri Linux/MySQL.
Toate testele următoare au fost efectuate pe un server Linode cu opt nuclee virtuale și 32 GB de memorie, rulând 20 de simulări de încărcare monitorizând două sute de instanțe MySQL. Sau, în termenii Prometheus, 800 de ținte, 440 de zgârieturi pe secundă, 380 de mii de înregistrări pe secundă și 1,7 milioane de serii cronologice active.

Desen

Abordarea obișnuită a bazelor de date tradiționale, inclusiv cea folosită de Prometheus 1.x, este să limita de memorie. Dacă nu este suficient pentru a gestiona sarcina, veți experimenta latențe mari și unele solicitări vor eșua. Utilizarea memoriei în Prometheus 2 este configurabilă prin tastă storage.tsdb.min-block-duration, care determină cât de mult timp vor fi păstrate înregistrările în memorie înainte de spălarea pe disc (implicit este de 2 ore). Cantitatea de memorie necesară va depinde de numărul de serii cronologice, etichete și scrape adăugate la fluxul net de intrare. În ceea ce privește spațiul pe disc, Prometheus își propune să folosească 3 octeți per înregistrare (eșantion). Pe de altă parte, cerințele de memorie sunt mult mai mari.

Deși este posibil să configurați dimensiunea blocului, nu este recomandat să o configurați manual, așa că sunteți forțat să oferiți Prometheus atâta memorie cât are nevoie pentru volumul dvs. de lucru.
Dacă nu există suficientă memorie pentru a suporta fluxul de valori primite, Prometheus va pierde memorie sau criminalul OOM va ajunge la el.
Adăugarea de swap pentru a întârzia prăbușirea atunci când Prometheus rămâne fără memorie nu ajută cu adevărat, deoarece utilizarea acestei funcții cauzează un consum exploziv de memorie. Cred că are ceva de-a face cu Go, colectorul de gunoi și felul în care se ocupă de schimb.
O altă abordare interesantă este să configurați blocul de cap pentru a fi spălat pe disc la un anumit moment, în loc să îl numărați de la începutul procesului.

Analiza TSDB în Prometheus 2

După cum puteți vedea din grafic, curățările pe disc au loc la fiecare două ore. Dacă modificați parametrul min-block-duration la o oră, atunci aceste resetări vor avea loc la fiecare oră, începând după o jumătate de oră.
Dacă doriți să utilizați acest grafic și alte grafice în instalația dvs. Prometheus, puteți utiliza acest lucru bord. A fost proiectat pentru PMM, dar, cu modificări minore, se potrivește în orice instalație Prometheus.
Avem un bloc activ numit head block care este stocat în memorie; blocurile cu date mai vechi sunt disponibile prin mmap(). Acest lucru elimină necesitatea de a configura cache-ul separat, dar înseamnă și că trebuie să lăsați suficient spațiu pentru memoria cache a sistemului de operare dacă doriți să interogați date mai vechi decât poate găzdui blocul de cap.
Acest lucru înseamnă, de asemenea, că consumul de memorie virtuală Prometheus va părea destul de mare, ceea ce nu este un motiv de îngrijorare.

Analiza TSDB în Prometheus 2

Un alt punct de design interesant este utilizarea WAL (write ahead log). După cum puteți vedea din documentația de stocare, Prometheus folosește WAL pentru a evita blocările. Mecanismele specifice pentru garantarea supraviețuirii datelor nu sunt, din păcate, bine documentate. Versiunea Prometheus 2.3.2 șterge WAL pe disc la fiecare 10 secunde și această opțiune nu este configurabilă de utilizator.

Compactări

Prometheus TSDB este proiectat ca un magazin LSM (Log Structured Merge): blocul principal este șters periodic pe disc, în timp ce un mecanism de compactare combină mai multe blocuri împreună pentru a evita scanarea prea multor blocuri în timpul interogărilor. Aici puteți vedea numărul de blocuri pe care le-am observat pe sistemul de testare după o zi de încărcare.

Analiza TSDB în Prometheus 2

Dacă doriți să aflați mai multe despre magazin, puteți examina fișierul meta.json, care conține informații despre blocurile disponibile și cum au apărut.

{
       "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
}

Compactările din Prometheus sunt legate de momentul în care blocul de cap este spălat pe disc. În acest moment, pot fi efectuate mai multe astfel de operațiuni.

Analiza TSDB în Prometheus 2

Se pare că compactările nu sunt limitate în niciun fel și pot provoca vârfuri mari de I/O pe disc în timpul execuției.

Analiza TSDB în Prometheus 2

Încărcarea procesorului crește

Analiza TSDB în Prometheus 2

Desigur, acest lucru are un impact destul de negativ asupra vitezei sistemului și, de asemenea, reprezintă o provocare serioasă pentru stocarea LSM: cum să faceți compactarea pentru a suporta rate mari de solicitare fără a cauza prea multă supraîncărcare?
Utilizarea memoriei în procesul de compactare pare, de asemenea, destul de interesantă.

Analiza TSDB în Prometheus 2

Putem vedea cum, după compactare, cea mai mare parte a memoriei își schimbă starea de la Cache la Free: asta înseamnă că informațiile potențial valoroase au fost eliminate de acolo. Curios dacă este folosit aici fadvice() sau o altă tehnică de minimizare, sau pentru că memoria cache a fost eliberată de blocurile distruse în timpul compactării?

Recuperare după un eșec

Recuperarea după eșecuri necesită timp și pentru un motiv întemeiat. Pentru un flux primit de un milion de înregistrări pe secundă, a trebuit să aștept aproximativ 25 de minute în timp ce recuperarea a fost efectuată ținând cont de unitatea SSD.

level=info ts=2018-09-13T13:38:14.09650965Z caller=main.go:222 msg="Starting 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="Start listening for 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="found 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="found healthy block" mint=1536732000000 maxt=1536753600000 ulid=01CQ78486TNX5QZTBF049PQHSM
level=info ts=2018-09-13T13:38:14.102267346Z caller=repair.go:39 component=tsdb msg="found healthy block" mint=1536537600000 maxt=1536732000000 ulid=01CQ78DE7HSQK0C0F5AZ46YGF0
level=info ts=2018-09-13T13:38:14.102660295Z caller=repair.go:39 component=tsdb msg="found healthy block" mint=1536775200000 maxt=1536782400000 ulid=01CQ7SAT4RM21Y0PT5GNSS146Q
level=info ts=2018-09-13T13:38:14.103075885Z caller=repair.go:39 component=tsdb msg="found 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."

Principala problemă a procesului de recuperare este consumul mare de memorie. În ciuda faptului că, într-o situație normală, serverul poate funcționa stabil cu aceeași cantitate de memorie, dacă se blochează, este posibil să nu se recupereze din cauza OOM. Singura soluție pe care am găsit-o a fost să dezactivez colectarea datelor, să afișez serverul, să-l las să se recupereze și să repornesc cu colectarea activată.

Incalzire

Un alt comportament de reținut în timpul încălzirii este relația dintre performanța scăzută și consumul ridicat de resurse imediat după pornire. La unele porniri, dar nu la toate, am observat o sarcină gravă asupra procesorului și memoriei.

Analiza TSDB în Prometheus 2

Analiza TSDB în Prometheus 2

Lacunele în utilizarea memoriei indică faptul că Prometheus nu poate configura toate colecțiile de la început și că unele informații se pierd.
Nu mi-am dat seama exact motivele pentru încărcarea mare a procesorului și a memoriei. Bănuiesc că acest lucru se datorează creării de noi serii temporale în blocul de cap cu o frecvență înaltă.

Încărcarea procesorului crește

Pe lângă compactări, care creează o sarcină I/O destul de mare, am observat creșteri serioase ale încărcării procesorului la fiecare două minute. Exploziile sunt mai lungi când debitul de intrare este mare și par a fi cauzate de colectorul de gunoi al lui Go, cel puțin unele nuclee fiind complet încărcate.

Analiza TSDB în Prometheus 2

Analiza TSDB în Prometheus 2

Aceste sărituri nu sunt atât de nesemnificative. Se pare că atunci când acestea apar, punctul de intrare intern și valorile lui Prometheus devin indisponibile, provocând lacune de date în aceleași perioade de timp.

Analiza TSDB în Prometheus 2

De asemenea, puteți observa că exportatorul Prometheus se închide pentru o secundă.

Analiza TSDB în Prometheus 2

Putem observa corelații cu colectarea gunoiului (GC).

Analiza TSDB în Prometheus 2

Concluzie

TSDB din Prometheus 2 este rapid, capabil să gestioneze milioane de serii cronologice și în același timp mii de înregistrări pe secundă folosind hardware destul de modest. Utilizarea CPU și I/O disc este, de asemenea, impresionantă. Exemplul meu a arătat până la 200 de metrici pe secundă per nucleu utilizat.

Pentru a planifica extinderea, trebuie să vă amintiți cantități suficiente de memorie, iar aceasta trebuie să fie memorie reală. Cantitatea de memorie folosită pe care am observat-o a fost de aproximativ 5 GB la 100 de înregistrări pe secundă din fluxul de intrare, care împreună cu memoria cache a sistemului de operare a oferit aproximativ 000 GB de memorie ocupată.

Desigur, mai este mult de făcut pentru a îmblânzi vârfurile I/O CPU și disc, iar acest lucru nu este surprinzător având în vedere cât de tânăr este TSDB Prometheus 2 în comparație cu InnoDB, TokuDB, RocksDB, WiredTiger, dar toate au avut similare probleme la începutul ciclului lor de viață.

Sursa: www.habr.com

Adauga un comentariu