TSDB-analyse i Prometheus 2

TSDB-analyse i Prometheus 2

Tidsseriedatabasen (TSDB) i Prometheus 2 er et godt eksempel på en ingeniørløsning, der tilbyder betydelige forbedringer i forhold til Prometheus 2 storage v1 med hensyn til dataindsamling og forespørgselsudførelseshastighed og ressourceeffektivitet. Vi implementerede Prometheus 2 i Percona Monitoring and Management (PMM), og jeg havde mulighed for at forstå ydeevnen af ​​Prometheus 2 TSDB. I denne artikel vil jeg tale om resultaterne af disse observationer.

Prometheus gennemsnitlige arbejdsbyrde

For dem, der er vant til at håndtere databaser til generelle formål, er den typiske Prometheus-arbejdsbyrde ret interessant. Hastigheden af ​​dataakkumulering har en tendens til en stabil værdi: normalt sender de tjenester, du overvåger, omtrent den samme mængde målinger, og infrastrukturen ændrer sig relativt langsomt.
Anmodninger om oplysninger kan komme fra forskellige kilder. Nogle af dem, ligesom alarmer, sigter også efter en stabil og forudsigelig værdi. Andre, såsom brugeranmodninger, kan forårsage stigninger, selvom dette ikke er tilfældet for det meste af arbejdsbyrden.

Belastningstest

Under testen fokuserede jeg på evnen til at akkumulere data. Jeg implementerede Prometheus 2.3.2 kompileret med Go 1.10.1 (som en del af PMM 1.14) på ​​en Linode-tjeneste ved hjælp af dette script: StackScript. For den mest realistiske belastningsgenerering, med dette StackScript Jeg kørte flere MySQL noder med en reel belastning (Sysbench TPC-C Test), som hver emulerede 10 Linux/MySQL noder.
Alle følgende test blev udført på en Linode-server med otte vCores og 32 GB hukommelse, der kørte 20 belastningssimuleringer, der overvågede 800 MySQL-forekomster. Eller, hvad angår Prometheus, 440 mål (mål), 380 gebyrer (afskrabninger) i sekundet, 1,7 tusinde optegnelser (prøver) i sekundet og XNUMX millioner aktive tidsserier.

design

Den sædvanlige traditionelle databasetilgang, inklusive den, der bruges af Prometheus 1.x, er at hukommelsesgrænse. Hvis det ikke er nok til at håndtere belastningen, vil du opleve høj latenstid, og nogle anmodninger vil ikke blive opfyldt. Hukommelsesbrug i Prometheus 2 kan konfigureres via en nøgle storage.tsdb.min-block-duration, som bestemmer, hvor længe poster vil blive gemt i hukommelsen, før de tømmes til disken (standard er 2 timer). Mængden af ​​hukommelse, der er nødvendig, afhænger af antallet af tidsserier, etiketter og afskrabninger plus nettoinputtet. Med hensyn til diskplads, sigter Prometheus efter at bruge 3 bytes pr. skrivning (sample). På den anden side er hukommelseskravene meget højere.

Selvom det er muligt at konfigurere blokstørrelsen, anbefales det ikke at indstille den manuelt, så du står tilbage med opgaven med at give Prometheus så meget hukommelse, som den har brug for til din arbejdsbyrde.
Hvis der ikke er nok hukommelse til at understøtte den indkommende strøm af metrikker, vil Prometheus falde ud af hukommelsen eller blive fanget af en OOM-morder.
Tilføjelse af swap for at forsinke nedbruddet, når Prometheus løber tør for hukommelse, hjælper ikke rigtigt, fordi brug af denne funktion forårsager hukommelseseksplosioner. Jeg tror, ​​det handler om Go, dens skraldeopsamler, og hvordan det fungerer med swap.
En anden interessant tilgang er at indstille hovedblokken til at blive skyllet til disken på et bestemt tidspunkt, i stedet for at tælle den fra det tidspunkt, hvor processen startede.

TSDB-analyse i Prometheus 2

Som du kan se på grafen, sker flushes til disk hver anden time. Hvis du ændrer parameteren min-blok-varighed til en time, vil disse nulstillinger ske hver time, startende om en halv time.
Hvis du vil bruge denne og andre grafer i din Prometheus-installation, kan du bruge denne dashboard. Den er designet til PMM, men med nogle få ændringer passer den ind i enhver Prometheus-installation.
Vi har en aktiv blok, kaldet hovedblokken, som er gemt i hukommelsen; blokke med ældre data er tilgængelige via mmap(). Dette fjerner behovet for at konfigurere cachen separat, men det betyder også, at du skal efterlade nok plads til operativsystemets cache, hvis du vil forespørge data, der er ældre end hovedblokken.
Det betyder også, at Prometheus' virtuelle hukommelsesforbrug vil se ret højt ud, hvilket ikke er noget at bekymre sig om.

TSDB-analyse i Prometheus 2

Et andet interessant designpunkt er brugen af ​​WAL (write ahead log). Som du kan se fra depotdokumentationen, bruger Prometheus WAL for at undgå nedbrud. Specifikke mekanismer til sikring af dataoverlevelse er desværre ikke veldokumenterede. Prometheus 2.3.2 skyller WAL til disk hvert 10. sekund, og denne indstilling kan ikke konfigureres af brugeren.

Sæler

Prometheus TSDB er designet i billedet af LSM-lager (Log Structured Merge - log-structured merge tree): hovedblokken skylles med jævne mellemrum til disk, mens komprimeringsmekanismen smelter flere blokke sammen for at undgå at scanne for mange blokke på anmodninger. Her kan du se antallet af blokke, som jeg observerede på testsystemet efter en dags belastning.

TSDB-analyse i Prometheus 2

Hvis du vil lære mere om opbevaring, kan du tjekke filen meta.json, som har information om de tilgængelige blokke, og hvordan de opstod.

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

Forseglinger i Prometheus er bundet til det tidspunkt, hvor hovedblokken skylles til disken. På dette tidspunkt kan flere sådanne operationer udføres.

TSDB-analyse i Prometheus 2

Det ser ud til, at komprimeringer ikke er begrænset på nogen måde og kan forårsage store disk I/O-spidser under udførelse.

TSDB-analyse i Prometheus 2

CPU-belastningsspidser

TSDB-analyse i Prometheus 2

Dette har selvfølgelig en ret negativ effekt på systemets hastighed og er også en alvorlig udfordring for LSM-lager: hvordan laver man komprimeringer for at understøtte høje forespørgselshastigheder uden at forårsage for meget overhead?
Brugen af ​​hukommelse i komprimeringsprocessen ser også ret nysgerrig ud.

TSDB-analyse i Prometheus 2

Vi kan se, hvordan det meste af hukommelsen efter komprimering ændrer tilstand fra Cached til Free: det betyder, at potentielt værdifuld information er blevet fjernet derfra. Spændende om det er brugt her fadvice() eller en anden minimeringsteknik, eller er det fordi cachen er blevet tømt for blokke ødelagt ved komprimering?

Gendannelse af fejl

Disaster recovery tager tid, og det er der god grund til. For en indgående strøm på en million poster i sekundet måtte jeg vente omkring 25 minutter, mens gendannelsen tog højde for SSD-drevet.

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."

Hovedproblemet ved gendannelsesprocessen er højt hukommelsesforbrug. Selvom serveren kan køre stabilt med den samme mængde hukommelse i en normal situation, vil den muligvis ikke stige på grund af OOM, hvis den går ned. Den eneste løsning, jeg har fundet, er at deaktivere dataindsamling, bringe serveren op, lade den genoprette og genstarte med indsamling aktiveret.

Varmer op

En anden adfærd, du skal huske på under opvarmning, er forholdet mellem lav ydeevne og højt ressourceforbrug lige efter opstart. Under nogle, men ikke alle starter, observerede jeg en alvorlig belastning af CPU'en og hukommelsen.

TSDB-analyse i Prometheus 2

TSDB-analyse i Prometheus 2

Fald i hukommelsesforbrug indikerer, at Prometheus ikke kan konfigurere alle gebyrer fra starten, og nogle oplysninger går tabt.
Jeg har ikke fundet ud af de præcise årsager til det høje CPU- og hukommelsesforbrug. Jeg formoder, at dette skyldes oprettelsen af ​​nye tidsserier i hovedblokken med en høj frekvens.

CPU-spidser

Ud over fortætninger, som skaber en ret høj I/O-belastning, har jeg bemærket alvorlige stigninger i CPU-belastning hvert andet minut. Udbruddene er længere med høj indgående trafik og ser ud som om de er forårsaget af Go-skraldesamleren, i det mindste nogle kerner er fuldt lastet.

TSDB-analyse i Prometheus 2

TSDB-analyse i Prometheus 2

Disse spring er ikke så ubetydelige. Det ser ud til, at når de opstår, bliver Prometheus' interne indgangspunkt og metrikker utilgængelige, hvilket forårsager datafald i de samme tidsintervaller.

TSDB-analyse i Prometheus 2

Du kan også bemærke, at Prometheus-eksportøren lukker ned i et sekund.

TSDB-analyse i Prometheus 2

Vi kan se sammenhænge med affaldsindsamling (GC).

TSDB-analyse i Prometheus 2

Konklusion

TSDB i Prometheus 2 er hurtig, i stand til at håndtere millioner af tidsserier og samtidig tusindvis af poster i sekundet ved brug af ret beskeden hardware. CPU- og disk I/O-udnyttelsen er også imponerende. Mit eksempel viste op til 200 metrics pr. sekund pr. brugt kerne.

For at planlægge udvidelse skal du huske, at der er nok hukommelse, og det skal være ægte hukommelse. Mængden af ​​brugt hukommelse, som jeg observerede, var omkring 5 GB pr. 100 poster i sekundet af den indkommende stream, hvilket i alt med operativsystemets cache gav omkring 000 GB optaget hukommelse.

Selvfølgelig er der stadig meget arbejde at gøre for at tæmme CPU- og disk I/O-spidser, og det er ikke overraskende, i betragtning af hvor ung TSDB Prometheus 2 er sammenlignet med InnoDB, TokuDB, RocksDB, WiredTiger, men de havde alle lignende problemer i begyndelsen af ​​deres livscyklus.

Kilde: www.habr.com

Tilføj en kommentar