
La base de donnĂ©es de sĂ©ries chronologiques (TSDB) de Prometheus 2 est un excellent exemple de solution d'ingĂ©nierie qui offre des amĂ©liorations majeures par rapport au stockage v2 de Prometheus 1 en termes de vitesse d'accumulation de donnĂ©es, d'exĂ©cution de requĂȘtes et d'efficacitĂ© des ressources. Nous implĂ©mentions Prometheus 2 dans Percona Monitoring and Management (PMM) et j'ai eu l'occasion de comprendre les performances de Prometheus 2 TSDB. Dans cet article, je parlerai des rĂ©sultats de ces observations.
Charge de travail moyenne de Prometheus
Pour ceux qui sont habituĂ©s Ă gĂ©rer des bases de donnĂ©es Ă usage gĂ©nĂ©ral, la charge de travail typique de Prometheus est assez intĂ©ressante. Le taux d'accumulation de donnĂ©es a tendance Ă ĂȘtre stable : gĂ©nĂ©ralement, les services que vous surveillez envoient Ă peu prĂšs le mĂȘme nombre de mĂ©triques et l'infrastructure Ă©volue relativement lentement.
Les demandes dâinformations peuvent provenir de diverses sources. Certaines dâentre elles, comme les alertes, visent Ă©galement une valeur stable et prĂ©visible. D'autres, comme les demandes des utilisateurs, peuvent provoquer des salves, bien que ce ne soit pas le cas pour la plupart des charges de travail.
Test de charge
Lors des tests, je me suis concentrĂ© sur la capacitĂ© Ă accumuler des donnĂ©es. J'ai dĂ©ployĂ© Prometheus 2.3.2 compilĂ© avec Go 1.10.1 (dans le cadre de PMM 1.14) sur le service Linode en utilisant ce script : . Pour la gĂ©nĂ©ration de charge la plus rĂ©aliste, en utilisant ceci J'ai lancĂ© plusieurs nĆuds MySQL avec une charge rĂ©elle (test Sysbench TPC-C), chacun Ă©mulant 10 nĆuds. Linux/MySQL.
Tous les tests suivants ont Ă©tĂ© effectuĂ©s sur un serveur Linode dotĂ© de huit cĆurs virtuels et de 32 Go de mĂ©moire, exĂ©cutant 20 simulations de charge surveillant deux cents instances MySQL. Soit, en termes de Prometheus, 800 cibles, 440 grattages par seconde, 380 1,7 enregistrements par seconde et XNUMX million de sĂ©ries temporelles actives.
Conception
L'approche habituelle des bases de donnĂ©es traditionnelles, y compris celle utilisĂ©e par Prometheus 1.x, consiste Ă . Si cela ne suffit pas Ă gĂ©rer la charge, vous rencontrerez des latences Ă©levĂ©es et certaines requĂȘtes Ă©choueront. L'utilisation de la mĂ©moire dans Prometheus 2 est configurable via une clĂ© storage.tsdb.min-block-duration, qui dĂ©termine la durĂ©e pendant laquelle les enregistrements seront conservĂ©s en mĂ©moire avant d'ĂȘtre transfĂ©rĂ©s sur le disque (la valeur par dĂ©faut est de 2 heures). La quantitĂ© de mĂ©moire requise dĂ©pendra du nombre de sĂ©ries temporelles, dâĂ©tiquettes et de scrapes ajoutĂ©s au flux entrant net. En termes d'espace disque, Prometheus vise Ă utiliser 3 octets par enregistrement (Ă©chantillon). En revanche, les besoins en mĂ©moire sont bien plus Ă©levĂ©s.
Bien qu'il soit possible de configurer la taille du bloc, il n'est pas recommandĂ© de la configurer manuellement, vous ĂȘtes donc obligĂ© de donner Ă Prometheus autant de mĂ©moire que nĂ©cessaire pour votre charge de travail.
S'il n'y a pas assez de mémoire pour prendre en charge le flux de métriques entrant, Prometheus manquera de mémoire ou le tueur de MOO y parviendra.
Ajouter un swap pour retarder le crash lorsque Prometheus manque de mémoire n'aide pas vraiment, car l'utilisation de cette fonction entraßne une consommation explosive de mémoire. Je pense que cela a quelque chose à voir avec Go, son garbage collector et la façon dont il gÚre le swap.
Une autre approche intĂ©ressante consiste Ă configurer le bloc de tĂȘte pour qu'il soit vidĂ© sur le disque Ă un certain moment, au lieu de le compter depuis le dĂ©but du processus.

Comme vous pouvez le voir sur le graphique, les vidages sur le disque se produisent toutes les deux heures. Si vous modifiez le paramÚtre min-block-duration sur une heure, ces réinitialisations se produiront toutes les heures, en commençant aprÚs une demi-heure.
Si vous souhaitez utiliser ce graphique et d'autres dans votre installation Prometheus, vous pouvez utiliser ceci . Il a été conçu pour PMM mais, avec des modifications mineures, s'intÚgre dans n'importe quelle installation Prometheus.
Nous avons un bloc actif appelĂ© bloc de tĂȘte qui est stockĂ© en mĂ©moire ; les blocs avec des donnĂ©es plus anciennes sont disponibles via mmap(). Cela Ă©limine le besoin de configurer le cache sĂ©parĂ©ment, mais signifie Ă©galement que vous devez laisser suffisamment d'espace pour le cache du systĂšme d'exploitation si vous souhaitez interroger des donnĂ©es plus anciennes que ce que le bloc principal peut accueillir.
Cela signifie également que la consommation de mémoire virtuelle de Prometheus semblera assez élevée, ce qui n'est pas un sujet d'inquiétude.

Un autre point de conception intĂ©ressant est lâutilisation de WAL (write advance log). Comme vous pouvez le voir dans la documentation sur le stockage, Prometheus utilise WAL pour Ă©viter les plantages. Les mĂ©canismes spĂ©cifiques permettant de garantir la pĂ©rennitĂ© des donnĂ©es ne sont malheureusement pas bien documentĂ©s. Prometheus version 2.3.2 vide WAL sur le disque toutes les 10 secondes et cette option n'est pas configurable par l'utilisateur.
Compactages
Prometheus TSDB est conçu comme un magasin LSM (Log Structured Merge) : le bloc de tĂȘte est vidĂ© pĂ©riodiquement sur le disque, tandis qu'un mĂ©canisme de compactage combine plusieurs blocs ensemble pour Ă©viter d'analyser trop de blocs lors des requĂȘtes. Ici vous pouvez voir le nombre de blocs que j'ai observĂ©s sur le systĂšme de test aprĂšs une journĂ©e de chargement.

Si vous souhaitez en savoir plus sur le magasin, vous pouvez examiner le fichier méta.json, qui contient des informations sur les blocs disponibles et comment ils ont été créés.
{
"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
}Les compactages dans Prometheus sont liĂ©s au moment oĂč le bloc de tĂȘte est vidĂ© sur le disque. A ce stade, plusieurs opĂ©rations de ce type peuvent ĂȘtre rĂ©alisĂ©es.

Il semble que les compactages ne soient limitĂ©s dâaucune maniĂšre et peuvent provoquer dâimportants pics dâE/S disque lors de lâexĂ©cution.

Pics de charge du processeur

Bien sĂ»r, cela a un impact plutĂŽt nĂ©gatif sur la vitesse du systĂšme, et pose Ă©galement un sĂ©rieux dĂ©fi pour le stockage LSM : comment effectuer le compactage pour prendre en charge des taux de requĂȘtes Ă©levĂ©s sans entraĂźner trop de frais gĂ©nĂ©raux ?
Lâutilisation de la mĂ©moire dans le processus de compactage semble Ă©galement trĂšs intĂ©ressante.

Nous pouvons voir comment, aprÚs le compactage, la majeure partie de la mémoire passe de l'état Cached à Free : cela signifie que des informations potentiellement précieuses en ont été supprimées. Curieux de savoir si c'est utilisé ici fadvice() ou une autre technique de minimisation, ou est-ce parce que le cache a été libéré des blocs détruits lors du compactage ?
Récupération aprÚs un échec
La récupération aprÚs un échec prend du temps, et pour cause. Pour un flux entrant d'un million d'enregistrements par seconde, j'ai dû attendre environ 25 minutes pendant que la récupération était effectuée en tenant compte du disque 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."Le principal problĂšme du processus de rĂ©cupĂ©ration est la consommation Ă©levĂ©e de mĂ©moire. Bien que dans une situation normale, le serveur puisse fonctionner de maniĂšre stable avec la mĂȘme quantitĂ© de mĂ©moire, s'il tombe en panne, il risque de ne pas rĂ©cupĂ©rer Ă cause du MOO. La seule solution que j'ai trouvĂ©e Ă©tait de dĂ©sactiver la collecte de donnĂ©es, d'ouvrir le serveur, de le laisser rĂ©cupĂ©rer et de redĂ©marrer avec la collecte activĂ©e.
Ăchauffement
Un autre comportement Ă garder Ă lâesprit lors de lâĂ©chauffement est la relation entre de faibles performances et une consommation Ă©levĂ©e de ressources juste aprĂšs le dĂ©marrage. Lors de certains dĂ©marrages, mais pas de tous, j'ai observĂ© une charge importante sur le processeur et la mĂ©moire.


Des lacunes dans l'utilisation de la mémoire indiquent que Prometheus ne peut pas configurer toutes les collections dÚs le départ et que certaines informations sont perdues.
Je n'ai pas compris les raisons exactes de la charge Ă©levĂ©e du processeur et de la mĂ©moire. Je soupçonne que cela est dĂ» Ă la crĂ©ation de nouvelles sĂ©ries chronologiques dans le bloc de tĂȘte Ă haute frĂ©quence.
Augmentation de la charge du processeur
En plus des compactages, qui crĂ©ent une charge d'E/S assez Ă©levĂ©e, j'ai remarquĂ© de sĂ©rieux pics de charge CPU toutes les deux minutes. Les rafales sont plus longues lorsque le flux d'entrĂ©e est Ă©levĂ© et semblent ĂȘtre causĂ©es par le garbage collector de Go, avec au moins certains cĆurs complĂštement chargĂ©s.


Ces sauts ne sont pas si insignifiants. Il semble que lorsque cela se produit, le point d'entrĂ©e interne et les mesures de Prometheus deviennent indisponibles, provoquant des lacunes dans les donnĂ©es pendant ces mĂȘmes pĂ©riodes.

Vous pouvez Ă©galement remarquer que l'exportateur Prometheus s'arrĂȘte pendant une seconde.

Nous pouvons remarquer des corrélations avec le garbage collection (GC).

Conclusion
TSDB dans Prometheus 2 est rapide, capable de gĂ©rer des millions de sĂ©ries temporelles et en mĂȘme temps des milliers d'enregistrements par seconde en utilisant un matĂ©riel assez modeste. L'utilisation du processeur et des E/S disque est Ă©galement impressionnante. Mon exemple montrait jusqu'Ă 200 000 mĂ©triques par seconde par cĆur utilisĂ©.
Pour planifier une extension, vous devez vous rappeler d'une quantitĂ© de mĂ©moire suffisante, et celle-ci doit ĂȘtre une mĂ©moire rĂ©elle. La quantitĂ© de mĂ©moire utilisĂ©e que j'ai observĂ©e Ă©tait d'environ 5 Go pour 100 000 enregistrements par seconde de flux entrant, ce qui, avec le cache du systĂšme d'exploitation, donnait environ 8 Go de mĂ©moire occupĂ©e.
Bien sûr, il reste encore beaucoup de travail à faire pour maßtriser les pics d'E/S du processeur et des disques, et cela n'est pas surprenant compte tenu de la jeunesse de TSDB Prometheus 2 par rapport à InnoDB, TokuDB, RocksDB, WiredTiger, mais ils avaient tous des performances similaires. problÚmes au début de leur cycle de vie.
Source: habr.com
