TSDB-analyse i Prometheus 2

TSDB-analyse i Prometheus 2

Tidsseriedatabasen (TSDB) i Prometheus 2 er et utmerket eksempel på en ingeniørløsning som tilbyr store forbedringer i forhold til v2-lagringen i Prometheus 1 når det gjelder dataakkumuleringshastighet, spørringsutførelse og ressurseffektivitet. Vi implementerte Prometheus 2 i Percona Monitoring and Management (PMM), og jeg fikk muligheten til å forstå ytelsen til Prometheus 2 TSDB. I denne artikkelen vil jeg snakke om resultatene av disse observasjonene.

Gjennomsnittlig Prometheus-arbeidsmengde

For de som er vant til å håndtere databaser med generelle formål, er den typiske Prometheus-arbeidsmengden ganske interessant. Hastigheten for dataakkumulering har en tendens til å være stabil: vanligvis sender tjenestene du overvåker omtrent samme antall beregninger, og infrastrukturen endres relativt sakte.
Forespørsler om informasjon kan komme fra ulike kilder. Noen av dem, som varsler, streber også etter en stabil og forutsigbar verdi. Andre, for eksempel brukerforespørsler, kan forårsake utbrudd, selv om dette ikke er tilfelle for de fleste arbeidsbelastninger.

Lastetest

Under testingen fokuserte jeg på muligheten til å samle data. Jeg distribuerte Prometheus 2.3.2 kompilert med Go 1.10.1 (som en del av PMM 1.14) på ​​Linode-tjenesten ved å bruke dette skriptet: StackScript. For den mest realistiske lastgenereringen, bruk denne StackScript Jeg lanserte flere MySQL-noder med en reell belastning (Sysbench TPC-C Test), som hver emulerte 10 Linux/MySQL-noder.
Alle de følgende testene ble utført på en Linode-server med åtte virtuelle kjerner og 32 GB minne, og kjørte 20 belastningssimuleringer som overvåket to hundre MySQL-forekomster. Eller, i Prometheus-termer, 800 mål, 440 skrap per sekund, 380 tusen poster per sekund og 1,7 millioner aktive tidsserier.

Design

Den vanlige tilnærmingen til tradisjonelle databaser, inkludert den som brukes av Prometheus 1.x, er å minnegrense. Hvis det ikke er nok til å håndtere belastningen, vil du oppleve høye ventetider og noen forespørsler vil mislykkes. Minnebruk i Prometheus 2 kan konfigureres via nøkkel storage.tsdb.min-block-duration, som bestemmer hvor lenge opptak skal lagres i minnet før de skylles til disk (standard er 2 timer). Mengden minne som kreves vil avhenge av antall tidsserier, etiketter og skraper som legges til den innkommende nettostrømmen. Når det gjelder diskplass, har Prometheus som mål å bruke 3 byte per post (sample). På den annen side er minnekravene mye høyere.

Selv om det er mulig å konfigurere blokkstørrelsen, anbefales det ikke å konfigurere den manuelt, så du blir tvunget til å gi Prometheus så mye minne som det krever for arbeidsmengden din.
Hvis det ikke er nok minne til å støtte den innkommende strømmen av metrikk, vil Prometheus falle ut av minnet eller OOM-morderen kommer til det.
Å legge til swap for å forsinke krasjen når Prometheus går tom for minne hjelper egentlig ikke, fordi bruk av denne funksjonen forårsaker eksplosivt minneforbruk. Jeg tror det har noe med Go å gjøre, søppelsamleren og måten den håndterer bytte på.
En annen interessant tilnærming er å konfigurere hodeblokken til å skylles til disk på et bestemt tidspunkt, i stedet for å telle den fra starten av prosessen.

TSDB-analyse i Prometheus 2

Som du kan se av grafen, skjer skyllinger til disk annenhver time. Hvis du endrer parameteren min-blokkvarighet til én time, vil disse tilbakestillingene skje hver time, og starter etter en halv time.
Hvis du ønsker å bruke denne og andre grafer i din Prometheus-installasjon, kan du bruke denne dashbord. Den ble designet for PMM, men med mindre modifikasjoner passer den inn i enhver Prometheus-installasjon.
Vi har en aktiv blokk kalt hodeblokk som er lagret i minnet; blokker med eldre data er tilgjengelig via mmap(). Dette eliminerer behovet for å konfigurere cachen separat, men betyr også at du må ha nok plass til operativsystemets cache hvis du vil spørre etter data som er eldre enn hva head-blokken kan romme.
Dette betyr også at Prometheus virtuelle minneforbruk vil se ganske høyt ut, noe som ikke er noe å bekymre seg for.

TSDB-analyse i Prometheus 2

Et annet interessant designpunkt er bruken av WAL (write ahead log). Som du kan se fra lagringsdokumentasjonen, bruker Prometheus WAL for å unngå krasj. Spesifikke mekanismer for å garantere dataoverlevelse er dessverre ikke godt dokumentert. Prometheus versjon 2.3.2 skyller WAL til disk hvert 10. sekund, og dette alternativet kan ikke konfigureres av brukeren.

Komprimeringer

Prometheus TSDB er utformet som et LSM-lager (Log Structured Merge): hodeblokken skylles med jevne mellomrom til disk, mens en komprimeringsmekanisme kombinerer flere blokker sammen for å unngå å skanne for mange blokker under spørringer. Her kan du se antall blokker som jeg observerte på testsystemet etter en dag med belastning.

TSDB-analyse i Prometheus 2

Hvis du vil lære mer om butikken, kan du undersøke meta.json-filen, som har informasjon om blokkene som er tilgjengelige og hvordan de ble til.

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

Komprimeringer i Prometheus er knyttet til tidspunktet hodeblokken spyles til disken. På dette tidspunktet kan flere slike operasjoner utføres.

TSDB-analyse i Prometheus 2

Det ser ut til at komprimeringer ikke er begrenset på noen måte og kan forårsake store I/O-spiker for disker under utførelse.

TSDB-analyse i Prometheus 2

CPU-belastningstopper

TSDB-analyse i Prometheus 2

Selvfølgelig har dette en ganske negativ innvirkning på hastigheten til systemet, og utgjør også en alvorlig utfordring for LSM-lagring: hvordan gjøre komprimering for å støtte høye forespørselsrater uten å forårsake for mye overhead?
Bruken av minne i komprimeringsprosessen ser også ganske interessant ut.

TSDB-analyse i Prometheus 2

Vi kan se hvordan, etter komprimering, det meste av minnet endrer tilstand fra Cached til Free: Dette betyr at potensielt verdifull informasjon har blitt fjernet derfra. Lurer på om det er brukt her fadvice() eller en annen minimeringsteknikk, eller er det fordi cachen ble frigjort fra blokker som ble ødelagt under komprimering?

Gjenoppretting etter feil

Gjenoppretting fra feil tar tid, og med god grunn. For en innkommende strøm på en million poster per sekund, måtte jeg vente i omtrent 25 minutter mens gjenopprettingen ble utført under hensyntagen til SSD-stasjonen.

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 med gjenopprettingsprosessen er høyt minneforbruk. Til tross for at serveren i en normal situasjon kan fungere stabilt med samme mengde minne, kan det hende at den ikke gjenopprettes på grunn av OOM hvis den krasjer. Den eneste løsningen jeg fant var å deaktivere datainnsamling, hente opp serveren, la den gjenopprette og starte på nytt med innsamling aktivert.

Varmer opp

En annen oppførsel å huske på under oppvarming er forholdet mellom lav ytelse og høyt ressursforbruk rett etter start. Under noen, men ikke alle starter, observerte jeg en alvorlig belastning på CPU og minne.

TSDB-analyse i Prometheus 2

TSDB-analyse i Prometheus 2

Huller i minnebruk indikerer at Prometheus ikke kan konfigurere alle samlinger fra starten, og noe informasjon går tapt.
Jeg har ikke funnet ut de eksakte årsakene til den høye CPU- og minnebelastningen. Jeg mistenker at dette skyldes opprettelsen av nye tidsserier i hodeblokken med høy frekvens.

CPU-belastningen øker

I tillegg til komprimeringene, som skaper en ganske høy I/O-belastning, la jeg merke til alvorlige topper i CPU-belastningen hvert annet minutt. Utbruddene er lengre når inngangsstrømmen er høy og ser ut til å være forårsaket av Gos søppeloppsamler, med i det minste noen kjerner som er fullastet.

TSDB-analyse i Prometheus 2

TSDB-analyse i Prometheus 2

Disse hoppene er ikke så ubetydelige. Det ser ut til at når disse oppstår, blir Prometheus' interne inngangspunkt og beregninger utilgjengelige, noe som forårsaker datahull i løpet av de samme tidsperioder.

TSDB-analyse i Prometheus 2

Du kan også legge merke til at Prometheus-eksportøren slår seg av i ett sekund.

TSDB-analyse i Prometheus 2

Vi kan merke sammenhenger med søppelinnsamling (GC).

TSDB-analyse i Prometheus 2

Konklusjon

TSDB i Prometheus 2 er rask, i stand til å håndtere millioner av tidsserier og samtidig tusenvis av poster per sekund ved bruk av ganske beskjeden maskinvare. CPU og disk I/O-utnyttelse er også imponerende. Eksemplet mitt viste opptil 200 000 metrikk per sekund per brukt kjerne.

For å planlegge utvidelse må du huske tilstrekkelige mengder minne, og dette må være ekte minne. Mengden brukt minne som jeg observerte var omtrent 5 GB per 100 000 poster per sekund av den innkommende strømmen, som sammen med operativsystemets cache ga omtrent 8 GB okkupert minne.

Selvfølgelig er det fortsatt mye arbeid å gjøre for å temme CPU og disk I/O-spiker, og dette er ikke overraskende med tanke på hvor ung TSDB Prometheus 2 er sammenlignet med InnoDB, TokuDB, RocksDB, WiredTiger, men de hadde alle lignende problemer tidlig i livssyklusen.

Kilde: www.habr.com

Legg til en kommentar