Analys av TSDB i Prometheus 2

Analys av TSDB i Prometheus 2

En tidsseriedatabas (TSDB, time series database) i Prometheus 2 Àr ett utmÀrkt exempel pÄ en ingenjörslösning som erbjuder betydande förbÀttringar jÀmfört med lagringssystemet v2 i Prometheus 1 i termer av datainsamlingens hastighet och frÄgeprestanda, samt resurseffektivitet. Vi implementerade Prometheus 2 i Percona Monitoring and Management (PMM), och jag hade möjlighet att utvÀrdera prestandan för Prometheus 2 TSDB. I denna artikel kommer jag att redogöra för resultaten av mina observationer.

Genomsnittlig arbetsbelastning för Prometheus

För dem som Àr vana vid att arbeta med produktionsdatabaser Àr den vanliga arbetsbelastningen för Prometheus ganska intressant. Hastigheten pÄ datainsamlingen tenderar att stabiliseras: vanligtvis skickar de tjÀnster som du övervakar ungefÀr samma antal metrik och infrastrukturen förÀndras relativt lÄngsamt.
FörfrÄgningar om information kan komma frÄn olika kÀllor. Vissa av dessa, som larm, tenderar ocksÄ att stabiliseras och bli förutsÀgbara. Andra, sÄsom anvÀndarförfrÄgningar, kan orsaka toppar, Àven om detta inte Àr typiskt för den större delen av belastningen.

Belastningstest

Under testningen fokuserade jag pÄ förmÄgan att samla in data. Jag rullade ut Prometheus 2.3.2, kompilerad med Go 1.10.1 (som en del av PMM 1.14) pÄ en Linode-tjÀnst, med hjÀlp av detta skript: StackScript. För att generera belastning sÄ realistiskt som möjligt anvÀnde jag detta StackScript jag startade flera MySQL-noder med verklig belastning (Sysbench TPC-C Test), dÀr varje nod emulerade 10 Linux/MySQL-noder.
Alla följande tester genomfördes pÄ en Linode-server med Ätta virtuella kÀrnor och 32 GB minne, dÀr 20 belastningssimuleringar av 200 MySQL-instans kördes. I termer av Prometheus, 800 mÄltavlor (targets), 440 insamlingar (scrapes) per sekund, 380 000 datauppsÀttningar (samples) per sekund och 1,7 miljoner aktiva tidsserier.

Design

Den vanliga metoden för traditionella databaser, inklusive den som anvĂ€ndes av Prometheus 1.x, innebĂŠrer minnesgrĂ€ns. Om det inte finns tillrĂ€ckligt med minne för att hantera belastningen kommer du att möta stora fördröjningar och vissa förfrĂ„gningar kommer att misslyckas. MinnesanvĂ€ndningen i Prometheus 2 konfigureras via nyckeln storage.tsdb.min-block-duration, som definierar hur lĂ€nge poster kommer att sparas i minnet innan de rensas till disken (standard Ă€r 2 timmar). Den nödvĂ€ndiga minnesmĂ€ngden beror pĂ„ antalet tidsserier, etiketter (labels) och intensiteten av datainsamling (scrapes) tillsammans med det rena inkommande flödet. NĂ€r det gĂ€ller diskutrymme strĂ€var Prometheus efter att anvĂ€nda 3 byte per post (sample). Å andra sidan Ă€r minneskraven mycket högre.

Även om det finns möjlighet att konfigurera blockstorleken, rekommenderas det inte att göra det manuellt, sĂ„ du stĂ„r inför behovet att ge Prometheus sĂ„ mycket minne som det ber om för din belastning.
Om det inte finns tillrÀckligt med minne för att stödja det inkommande flödet av metrik, kommer Prometheus att krascha med out of memory eller nÄs av OOM killer.
Att lÀgga till swap för att försena kraschen nÀr Prometheus gÄr tom pÄ minne hjÀlper inte mycket, eftersom anvÀndningen av den hÀr funktionen orsakar explosiv minnesanvÀndning. Jag tror att det har att göra med Go, dess skrÀpnivÄhanterare och hur den fungerar med swap.
En annan intressant metod Àr att stÀlla in rensning av head block till disken vid en viss tidpunkt, istÀllet för att rÀkna ned frÄn processens starttid.

Analys av TSDB i Prometheus 2

Som du kan se frÄn grafen sker rensningar till disken varannan timme. Om du Àndrar parametern min-block-duration till en timme kommer dessa rensningar att ske varje timme, med början efter en halvtimme.
Om du vill anvÀnda denna och andra grafer i din Prometheus-installation kan du anvÀnda denna dashboard. Den Àr utformad för PMM, men med nÄgra smÄ Àndringar passar den alla Prometheus-installationer.
Vi har en aktiv block som kallas head block, som lagras i minnet; block med Àldre data Àr tillgÀngliga genom mmap(). Detta eliminerar behovet av att konfigurera cache separat, men innebÀr ocksÄ att du mÄste lÀmna tillrÀckligt med utrymme för operativsystemets cache om du vill göra förfrÄgningar om data som Àr Àldre Àn vad head block kan rymma.
Dessutom betyder det att Prometheus virtuella minnesanvÀndning kommer att se ganska hög ut, vilket du inte behöver oroa dig för.

Analys av TSDB i Prometheus 2

En annan intressant aspekt av designen Àr anvÀndningen av WAL (write ahead log). Som framgÄr av dokumentationen för lagringen anvÀnder Prometheus WAL för att undvika förluster vid krasch. TyvÀrr Àr de specifika mekanismerna för att sÀkerstÀlla datalivslÀngd otillrÀckligt dokumenterade. Version 2.3.2 av Prometheus skriver WAL till disk var tionde sekund, och den hÀr instÀllningen kan inte konfigureras av anvÀndaren.

Kompakteringar (Compactions)

Prometheus TSDB Àr designad efter LSM-lager (Log Structured Merge - journalstrukturerat sammanslagningssystem): head block skrivs regelbundet till disk, samtidigt som kompakteringsmekanismen sammanfogar flera block för att undvika att skanna för mÄnga block vid förfrÄgningar. HÀr kan man se antalet block som jag observerade pÄ testsystemet efter ett dygns belastning.

Analys av TSDB i Prometheus 2

Om du vill veta mer om lagringen kan du studera filen meta.json, dÀr information finns om befintliga block och hur de kom till.

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

Kompakteringar i Prometheus Àr kopplade till tidpunkten för att head block skrivs till disk. Vid den tidpunkten kan flera sÄdana operationer utföras.

Analys av TSDB i Prometheus 2

Till synes finns det inga begrÀnsningar för komprimeringar, vilket kan orsaka stora spikar i disk-I/O under körning.

Analys av TSDB i Prometheus 2

CPU-belastningsspikar

Analys av TSDB i Prometheus 2

SjÀlvklart pÄverkar detta negativt systemets hastighet och utgör en betydande utmaning för LSM-lager: hur gör man komprimeringar för att stödja hög förfrÄgningshastighet utan att orsaka för mycket overhead?
MinnesanvÀndningen under komprimeringsprocesser ser ocksÄ ganska intressant ut.

Analys av TSDB i Prometheus 2

Vi kan se att efter komprimering Àndrar sig en stor del av minnet frÄn Cached till Free: det innebÀr att potentiellt vÀrdefull information har tagits bort dÀrifrÄn. Det Àr intressant om det anvÀnds fadvice() eller nÄgon annan teknik för minimering, eller om det beror pÄ att cachen har rensats frÄn block som förstörts vid komprimeringen?

ÅterstĂ€llning efter krasch

ÅterstĂ€llning efter krasch tar tid, och det Ă€r förstĂ„eligt. För en inkommande ström pĂ„ en miljon poster per sekund var jag tvungen att vĂ€nta cirka 25 minuter medan Ă„terstĂ€llningen genomfördes med SSD-disk.

level=info ts=2018-09-13T13:38:14.09650965Z caller=main.go:222 msg="Startar 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="Börjar lyssna pÄ anslutningar" address=:9090
level=info ts=2018-09-13T13:38:14.097400393Z caller=main.go:533 msg="Startar TSDB ..."
level=info ts=2018-09-13T13:38:14.098718401Z caller=repair.go:39 component=tsdb msg="Hittade friskt 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="Hittade friskt block" mint=1536732000000 maxt=1536753600000 ulid=01CQ78486TNX5QZTBF049PQHSM
level=info ts=2018-09-13T13:38:14.102267346Z caller=repair.go:39 component=tsdb msg="Hittade friskt block" mint=1536537600000 maxt=1536732000000 ulid=01CQ78DE7HSQK0C0F5AZ46YGF0
level=info ts=2018-09-13T13:38:14.102660295Z caller=repair.go:39 component=tsdb msg="Hittade friskt block" mint=1536775200000 maxt=1536782400000 ulid=01CQ7SAT4RM21Y0PT5GNSS146Q
level=info ts=2018-09-13T13:38:14.103075885Z caller=repair.go:39 component=tsdb msg="Hittade friskt block" mint=1536753600000 maxt=1536775200000 ulid=01CQ7SV8WJ3C2W5S3RTAHC2GHB
level=error ts=2018-09-13T14:05:18.208469169Z caller=wal.go:275 component=tsdb msg="WAL-korrigering upptÀcktes; trunkering" err="oförvÀntad CRC32 checksum d0465484, vill ha 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 startad"
level=info ts=2018-09-13T14:05:19.471604598Z caller=main.go:603 msg="LĂ€ser konfigurationsfil" filename=\/etc\/prometheus.yml
level=info ts=2018-09-13T14:05:19.499156711Z caller=main.go:629 msg="Fullföljde inlÀsningen av konfigurationsfil" filename=\/etc\/prometheus.yml
level=info ts=2018-09-13T14:05:19.499228186Z caller=main.go:502 msg="Servern Àr redo att ta emot webbegÀrningar."

Det frĂ€msta problemet med Ă„terstĂ€llningsprocessen Ă€r den höga minnesanvĂ€ndningen. Även om servern normalt kan fungera stabilt med samma mĂ€ngd minne, kan den under ett driftstopp misslyckas att starta pĂ„ grund av OOM. Den enda lösningen jag har hittat Ă€r att stĂ€nga av datainsamlingen, starta servern, lĂ„ta den Ă„terhĂ€mta sig och sedan starta om med datainsamlingen aktiverad.

UppvÀrmning

En annan sak att tÀnka pÄ under uppvÀrmning Àr förhÄllandet mellan lÄg prestanda och hög resursanvÀndning direkt efter start. Vid vissa, men inte alla starter, har jag observerat en kraftig belastning pÄ CPU och minne.

Analys av TSDB i Prometheus 2

Analys av TSDB i Prometheus 2

Toppavbrott i minnesanvÀndningen visar att Prometheus inte kan konfigurera alla insamlare vid start, och viss information gÄr förlorad.
Jag har inte avgjort de exakta orsakerna till den höga belastningen pÄ CPU och minne. Jag misstÀnker att det Àr kopplat till skapandet av nya tidsserier i head block med hög frekvens.

Belastningsspikar pÄ CPU

Förutom kompressionerna som skapar ganska hög belastning pÄ I/O har jag noterat allvarliga belastningsspikar pÄ processorn varannan minut. Utslag varar lÀngre vid hög inströmning och verkar orsakats av Go:s skrÀpsamlare, Ätminstone Àr nÄgra kÀrnor helt belastade.

Analys av TSDB i Prometheus 2

Analys av TSDB i Prometheus 2

Dessa spikar Àr inte obetydliga. Det verkar som att nÀr de intrÀffar blir den interna ingÄngspunkten och Prometheus-metriker otillgÀngliga, vilket orsakar dataförluster under dessa tidpunkter.

Analys av TSDB i Prometheus 2

Det gÄr ocksÄ att observera att Prometheus-exportören blockerar i en sekund.

Analys av TSDB i Prometheus 2

Vi kan se korrelationer med skrÀpsamling (GC).

Analys av TSDB i Prometheus 2

Slutsats

TSDB i Prometheus 2 fungerar snabbt, den kan hantera miljoner tidsserier och samtidigt tusentals skrivningar per sekund med ganska blygsam hÄrdvara. CPU- och disk-I/O-utnyttjande Àr ocksÄ imponerande. Mitt exempel visade upp till 200 000 metrikdata per sekund pÄ en enda anvÀnd kÀrna.

För att planera för expansion mÄste man tÀnka pÄ tillrÀckliga minnesvolymer, och detta mÄste vara verkligt minne. Den minnesanvÀndning jag observerade lÄg pÄ cirka 5 GB för 100 000 poster per sekund av inströmning, vilket gav en total pÄ cirka 8 GB upptagen minne med operativsystemets cache.

SjÀlvklart finns det fortfarande mycket arbete kvar för att tygla spikarna i CPU- och disk-I/O, och det Àr inte förvÄnande med tanke pÄ hur ung TSDB Prometheus 2 fortfarande Àr jÀmfört med InnoDB, TokuDB, RocksDB, WiredTiger, men de hade alla liknande problem i början av livscykeln.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster