
Η βάση δεδομένων χρονοσειρών (TSDB) στο Prometheus 2 είναι ένα εξαιρετικό παράδειγμα λύσης μηχανικής που προσφέρει σημαντικές βελτιώσεις σε σχέση με τον χώρο αποθήκευσης v2 στο Prometheus 1 όσον αφορά τη συσσώρευση δεδομένων και την ταχύτητα απόδοσης ερωτημάτων και την αποδοτικότητα των πόρων. Εφαρμόζαμε το Prometheus 2 στο Percona Monitoring and Management (PMM) και είχα την ευκαιρία να κατανοήσω την απόδοση του Prometheus 2 TSDB. Σε αυτό το άρθρο θα συζητήσω τα αποτελέσματα αυτών των παρατηρήσεων.
Προμηθέας Μέσος Φόρτος Εργασίας
Για όσους έχουν συνηθίσει να ασχολούνται με βάσεις δεδομένων πρωτογενούς σκοπού, ο τυπικός φόρτος εργασίας του Prometheus είναι αρκετά ενδιαφέρον. Ο ρυθμός συσσώρευσης δεδομένων τείνει να είναι σταθερός: συνήθως, οι υπηρεσίες που παρακολουθείτε στέλνουν περίπου τον ίδιο αριθμό μετρήσεων και η υποδομή αλλάζει σχετικά αργά.
Τα αιτήματα για πληροφορίες μπορεί να προέρχονται από διαφορετικές πηγές. Ορισμένες από αυτές, όπως οι ειδοποιήσεις, τείνουν επίσης να είναι σταθερές και προβλέψιμες. Άλλα, όπως αιτήματα χρηστών, ενδέχεται να προκαλέσουν αιχμές, αν και αυτό δεν είναι τυπικό για τους περισσότερους φόρτους εργασίας.
Δοκιμή φορτίου
Κατά τη διάρκεια της δοκιμής, εστίασα στην ικανότητα συγκέντρωσης δεδομένων. Ανέπτυξα το Prometheus 2.3.2 μεταγλωττισμένο με Go 1.10.1 (ως μέρος του PMM 1.14) σε μια υπηρεσία Linode χρησιμοποιώντας αυτό το σενάριο: . Για να δημιουργήσετε φορτία όσο το δυνατόν πιο ρεαλιστικά, χρησιμοποιήστε αυτό Ξεκίνησα αρκετούς κόμβους MySQL με πραγματικό φορτίο (Sysbench TPC-C Test), καθένας από τους οποίους μιμήθηκε 10 κόμβους Linux/MySQL.
Όλες οι ακόλουθες δοκιμές πραγματοποιήθηκαν σε διακομιστή Linode με οκτώ εικονικούς πυρήνες και 32 GB μνήμης, εκτελώντας 20 προσομοιώσεις φόρτωσης που παρακολουθούν διακόσιες παρουσίες MySQL. Ή, με όρους Προμηθέας, 800 στόχοι, 440 γρατζουνιές ανά δευτερόλεπτο, 380 χιλιάδες δείγματα ανά δευτερόλεπτο και 1,7 εκατομμύρια ενεργές χρονοσειρές.
Σχέδιο
Η τυπική προσέγγιση των παραδοσιακών βάσεων δεδομένων, συμπεριλαμβανομένης αυτής που χρησιμοποιεί ο Prometheus 1.x, είναι να . Εάν δεν είναι αρκετό για να χειριστείτε το φορτίο, θα αντιμετωπίσετε υψηλή καθυστέρηση και ορισμένα αιτήματα δεν θα ικανοποιηθούν. Η χρήση της μνήμης στο Prometheus 2 ρυθμίζεται μέσω ενός κλειδιού storage.tsdb.min-block-duration, το οποίο καθορίζει πόσο χρόνο θα διατηρηθούν οι εγγραφές στη μνήμη πριν από την έκπλυση στο δίσκο (η προεπιλογή είναι 2 ώρες). Η ποσότητα της απαιτούμενης μνήμης θα εξαρτηθεί από τον αριθμό των χρονοσειρών, των ετικετών και των scrapes επιπλέον της καθαρής εισερχόμενης ροής δεδομένων. Όσον αφορά τον χώρο στο δίσκο, ο Prometheus στοχεύει στη χρήση 3 byte ανά εγγραφή (δείγμα). Από την άλλη πλευρά, οι απαιτήσεις μνήμης είναι πολύ μεγαλύτερες.
Αν και είναι δυνατό να διαμορφώσετε το μέγεθος του μπλοκ, δεν συνιστάται η μη αυτόματη ρύθμιση παραμέτρων, επομένως αναγκάζεστε να δώσετε στον Prometheus όση μνήμη ζητά για τον φόρτο εργασίας σας.
Εάν δεν υπάρχει αρκετή μνήμη για την υποστήριξη της εισερχόμενης ροής μετρήσεων, ο Προμηθέας θα διακοπεί από τη μνήμη ή θα συλληφθεί από τον δολοφόνο του OOM.
Η προσθήκη ανταλλαγής για να καθυστερήσει τη συντριβή όταν ο Prometheus εξαντληθεί η μνήμη δεν βοηθάει πολύ γιατί η χρήση του προκαλεί έκρηξη της κατανάλωσης μνήμης. Νομίζω ότι είναι το Go, ο σκουπιδοσυλλέκτης του και ο τρόπος που χειρίζεται την ανταλλαγή.
Μια άλλη ενδιαφέρουσα προσέγγιση είναι να ρυθμίσετε το μπλοκ κεφαλής που θα ξεπλυθεί στο δίσκο σε μια συγκεκριμένη στιγμή, αντί να το μετράτε από τη στιγμή που ξεκινά η διαδικασία.

Όπως μπορείτε να δείτε από το γράφημα, οι εκπλύσεις δίσκου γίνονται κάθε δύο ώρες. Εάν αλλάξετε την παράμετρο min-block-duration σε μία ώρα, αυτές οι επαναφορές θα πραγματοποιούνται κάθε ώρα, ξεκινώντας μετά από μισή ώρα.
Εάν θέλετε να χρησιμοποιήσετε αυτό και άλλα γραφήματα στην εγκατάσταση του Prometheus, μπορείτε να το χρησιμοποιήσετε . Σχεδιάστηκε για PMM, αλλά με μικρές τροποποιήσεις ταιριάζει σε οποιαδήποτε εγκατάσταση του Prometheus.
Έχουμε ένα ενεργό μπλοκ που ονομάζεται head block, το οποίο είναι αποθηκευμένο στη μνήμη. μπλοκ με παλαιότερα δεδομένα είναι διαθέσιμα μέσω mmap(). Αυτό καταργεί την ανάγκη να ρυθμίσετε τις παραμέτρους της κρυφής μνήμης χωριστά, αλλά σημαίνει επίσης ότι πρέπει να αφήσετε αρκετό χώρο για την προσωρινή μνήμη του λειτουργικού συστήματος, εάν θέλετε να υποβάλετε ερωτήματα σε δεδομένα παλαιότερα από αυτά που μπορεί να χωρέσει το μπλοκ κεφαλής.
Αυτό σημαίνει επίσης ότι η κατανάλωση εικονικής μνήμης του Prometheus θα φαίνεται αρκετά υψηλή, κάτι που δεν προκαλεί ανησυχία.

Ένα άλλο ενδιαφέρον σημείο σχεδίασης είναι η χρήση του WAL (εγγραφή καταγραφής εκ των προτέρων). Όπως μπορείτε να δείτε από την τεκμηρίωση αποθήκευσης, ο Prometheus χρησιμοποιεί το WAL για να αποφύγει απώλειες κατά τη διάρκεια ατυχημάτων. Οι συγκεκριμένοι μηχανισμοί για τη διασφάλιση της διατήρησης των δεδομένων δυστυχώς δεν είναι επαρκώς τεκμηριωμένοι. Η έκδοση 2.3.2 του Prometheus ξεπλένει το WAL στο δίσκο κάθε 10 δευτερόλεπτα και αυτή η παράμετρος δεν μπορεί να ρυθμιστεί από το χρήστη.
Συμπυκνώσεις
Το Prometheus TSDB έχει σχεδιαστεί σαν χώρος αποθήκευσης δομημένης συγχώνευσης καταγραφής (LSM): το μπλοκ κεφαλής ξεπλένεται περιοδικά στο δίσκο, ενώ ένας μηχανισμός συμπύκνωσης συγχωνεύει πολλά μπλοκ μεταξύ τους για να αποφύγει τη σάρωση πάρα πολλών μπλοκ κατά τη διάρκεια των ερωτημάτων. Εδώ μπορείτε να δείτε τον αριθμό των μπλοκ που παρατήρησα στο σύστημα δοκιμής μετά από 24 ώρες φόρτωσης.

Εάν θέλετε να μάθετε περισσότερα για το αποθετήριο, μπορείτε να δείτε το αρχείο meta.json, το οποίο περιέχει πληροφορίες σχετικά με τα διαθέσιμα μπλοκ και πώς προέκυψαν.
{
"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
}Οι συμπιέσεις στον Prometheus συνδέονται με τη στιγμή που το μπλοκ κεφαλής ξεπλένεται στο δίσκο. Αρκετές τέτοιες λειτουργίες μπορούν να εκτελεστούν αυτή τη στιγμή.

Φαίνεται ότι οι συμπιέσεις δεν περιορίζονται με κανέναν τρόπο και μπορούν να προκαλέσουν μεγάλες αιχμές στην είσοδο/εξόδου του δίσκου κατά την εκτέλεση.

Αιχμές φορτίου CPU

Φυσικά, αυτό έχει αρκετά αρνητικό αντίκτυπο στην απόδοση του συστήματος και είναι επίσης μια σοβαρή πρόκληση για την αποθήκευση LSM: πώς να συμπυκνώσετε για να υποστηρίξετε υψηλούς ρυθμούς ερωτημάτων χωρίς να προκαλείτε υπερβολικά έξοδα;
Η χρήση της μνήμης κατά τη συμπύκνωση φαίνεται επίσης αρκετά ενδιαφέρουσα.

Μπορούμε να δούμε πώς μετά τη συμπύκνωση, το μεγαλύτερο μέρος της μνήμης αλλάζει κατάσταση από προσωρινή αποθήκευση σε δωρεάν, πράγμα που σημαίνει ότι δυνητικά πολύτιμες πληροφορίες έχουν αφαιρεθεί από εκεί. Αναρωτιέμαι αν χρησιμοποιείται εδώ fadvice() ή κάποια άλλη τεχνική ελαχιστοποίησης, ή προκαλείται από την απελευθέρωση της κρυφής μνήμης από μπλοκ που καταστρέφονται κατά τη συμπύκνωση;
Αποκατάσταση ανακαίνισης
Η ανάκαμψη από τις αποτυχίες απαιτεί χρόνο και για καλό λόγο. Για μια εισερχόμενη ροή ενός εκατομμυρίου εγγραφών ανά δευτερόλεπτο, έπρεπε να περιμένω περίπου 25 λεπτά για να πραγματοποιηθεί η ανάκτηση, λαμβάνοντας υπόψη τη μονάδα 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."Το κύριο πρόβλημα με τη διαδικασία ανάκτησης είναι η υψηλή κατανάλωση μνήμης. Παρόλο που ο διακομιστής μπορεί κανονικά να λειτουργεί σταθερά με την ίδια ποσότητα μνήμης, ενδέχεται να αποτύχει να ανακτήσει εάν διακοπεί λόγω OOM. Η μόνη λύση που βρήκα ήταν να απενεργοποιήσω τη συλλογή δεδομένων, να εμφανίσω τον διακομιστή, να τον αφήσω να ανακτήσει και να επανεκκινήσει με ενεργοποιημένη τη συλλογή.
Ζέσταμα
Μια άλλη συμπεριφορά που πρέπει να προσέχετε κατά την προθέρμανση είναι η αναλογία χαμηλής απόδοσης προς υψηλή κατανάλωση πόρων αμέσως μετά την εκκίνηση. Κατά τη διάρκεια ορισμένων, αλλά όχι όλων, εκτελέσεων παρατήρησα σημαντικό φορτίο CPU και μνήμης.


Οι πτώσεις χρήσης μνήμης υποδεικνύουν ότι ο Prometheus δεν μπορεί να διαμορφώσει όλες τις συλλογές από την αρχή και ότι ορισμένες πληροφορίες χάνονται.
Δεν έχω καταλάβει τους ακριβείς λόγους για το υψηλό φορτίο της CPU και της μνήμης. Υποψιάζομαι ότι αυτό οφείλεται στη δημιουργία νέων χρονοσειρών στο head block σε υψηλή συχνότητα.
Αιχμές φορτίου CPU
Εκτός από τις συμπαγές, που δημιουργούν ένα αρκετά υψηλό φορτίο I/O, παρατήρησα σημαντικές αιχμές στο φορτίο της CPU κάθε δύο λεπτά. Οι αιχμές είναι μεγαλύτερες σε υψηλή εισερχόμενη ροή και φαίνεται να προκαλούνται από τον συλλέκτη απορριμμάτων της Go, με τουλάχιστον ορισμένους πυρήνες να είναι πλήρως φορτωμένοι.


Αυτά τα άλματα δεν είναι και τόσο ασήμαντα. Φαίνεται ότι όταν εμφανίζονται, το εσωτερικό σημείο εισόδου και οι μετρήσεις του Προμηθέα δεν είναι διαθέσιμα, προκαλώντας κενά δεδομένων κατά τις ίδιες χρονικές περιόδους.

Μπορείτε επίσης να παρατηρήσετε ότι ο εξαγωγέας Prometheus κολλάει για ένα δευτερόλεπτο.

Μπορούμε να δούμε συσχετίσεις με τη συλλογή απορριμμάτων (GC).

Συμπέρασμα
Το TSDB στο Prometheus 2 είναι γρήγορο, ικανό να χειριστεί εκατομμύρια χρονοσειρές και ταυτόχρονα χιλιάδες εγγραφές ανά δευτερόλεπτο, χρησιμοποιώντας αρκετά μέτριο υλικό. Η χρήση της CPU και του δίσκου I/O είναι επίσης εντυπωσιακή. Το παράδειγμά μου έδειξε έως και 200 μετρήσεις ανά δευτερόλεπτο ανά χρησιμοποιούμενο πυρήνα.
Όταν σχεδιάζετε την επέκταση, πρέπει να θυμάστε ότι έχετε επαρκή μνήμη και πρέπει να είναι πραγματική μνήμη. Η ποσότητα της χρησιμοποιούμενης μνήμης που παρατήρησα ήταν περίπου 5 GB ανά 100 εγγραφές ανά δευτερόλεπτο εισερχόμενης κίνησης, η οποία, όταν συνδυάστηκε με την προσωρινή μνήμη του λειτουργικού συστήματος, έδωσε συνολικά περίπου 000 GB χρησιμοποιούμενης μνήμης.
Φυσικά, υπάρχει ακόμη πολλή δουλειά να γίνει για να τιθασεύσετε τις αιχμές I/O της CPU και του δίσκου, και αυτό δεν προκαλεί έκπληξη δεδομένου του πόσο νεαρό είναι το Prometheus 2 TSDB σε σύγκριση με τα InnoDB, TokuDB, RocksDB, WiredTiger, αλλά όλοι είχαν παρόμοια προβλήματα στην αρχή του κύκλου ζωής τους.
Πηγή: www.habr.com
