Analisis TSDB di Prometheus 2

Analisis TSDB di Prometheus 2

Basis data deret waktu (TSDB) di Prometheus 2 adalah contoh luar biasa dari solusi teknik yang menawarkan peningkatan besar dibandingkan penyimpanan v2 di Prometheus 1 dalam hal kecepatan akumulasi data, eksekusi kueri, dan efisiensi sumber daya. Kami menerapkan Prometheus 2 di Percona Monitoring and Management (PMM) dan saya berkesempatan untuk memahami kinerja Prometheus 2 TSDB. Pada artikel kali ini saya akan membahas tentang hasil observasi tersebut.

Beban Kerja Prometheus Rata-rata

Bagi mereka yang terbiasa berurusan dengan database tujuan umum, beban kerja khas Prometheus cukup menarik. Tingkat akumulasi data cenderung stabil: biasanya layanan yang Anda pantau mengirimkan jumlah metrik yang kira-kira sama, dan perubahan infrastruktur relatif lambat.
Permintaan informasi bisa datang dari berbagai sumber. Beberapa di antaranya, seperti peringatan, juga berupaya mencapai nilai yang stabil dan dapat diprediksi. Lainnya, seperti permintaan pengguna, dapat menyebabkan lonjakan, meskipun hal ini tidak terjadi pada sebagian besar beban kerja.

Tes beban

Selama pengujian, saya fokus pada kemampuan mengumpulkan data. Saya menerapkan Prometheus 2.3.2 yang dikompilasi dengan Go 1.10.1 (sebagai bagian dari PMM 1.14) pada layanan Linode menggunakan skrip ini: Skrip Tumpukan. Untuk pembuatan beban paling realistis, gunakan ini Skrip Tumpukan Saya meluncurkan beberapa node MySQL dengan beban nyata (Sysbench TPC-C Test), yang masing-masing meniru 10 node Linux/MySQL.
Semua pengujian berikut dilakukan pada server Linode dengan delapan inti virtual dan memori 32 GB, menjalankan 20 simulasi beban yang memantau dua ratus instans MySQL. Atau, dalam istilah Prometheus, 800 target, 440 goresan per detik, 380 ribu rekaman per detik, dan 1,7 juta rangkaian waktu aktif.

Disain

Pendekatan yang biasa dilakukan pada database tradisional, termasuk yang digunakan oleh Prometheus 1.x, adalah dengan batas memori. Jika tidak cukup untuk menangani beban, Anda akan mengalami latensi tinggi dan beberapa permintaan akan gagal. Penggunaan memori di Prometheus 2 dapat dikonfigurasi melalui kunci storage.tsdb.min-block-duration, yang menentukan berapa lama rekaman akan disimpan di memori sebelum di-flush ke disk (defaultnya adalah 2 jam). Jumlah memori yang dibutuhkan akan bergantung pada jumlah deret waktu, label, dan scrap yang ditambahkan ke aliran masuk bersih. Dalam hal ruang disk, Prometheus bertujuan untuk menggunakan 3 byte per record (sampel). Di sisi lain, kebutuhan memori jauh lebih tinggi.

Meskipun dimungkinkan untuk mengonfigurasi ukuran blok, tidak disarankan untuk mengonfigurasinya secara manual, sehingga Anda terpaksa memberikan Prometheus memori sebanyak yang diperlukan untuk beban kerja Anda.
Jika tidak ada cukup memori untuk mendukung aliran metrik yang masuk, Prometheus akan kehabisan memori atau pembunuh OOM akan mengaksesnya.
Menambahkan swap untuk menunda kerusakan saat Prometheus kehabisan memori tidak terlalu membantu, karena menggunakan fungsi ini menyebabkan konsumsi memori yang sangat besar. Saya pikir ini ada hubungannya dengan Go, pengumpul sampahnya dan cara menangani swap.
Pendekatan menarik lainnya adalah mengkonfigurasi blok head untuk dipindahkan ke disk pada waktu tertentu, alih-alih menghitungnya dari awal proses.

Analisis TSDB di Prometheus 2

Seperti yang Anda lihat dari grafik, pengosongan ke disk terjadi setiap dua jam. Jika Anda mengubah parameter durasi blok-min menjadi satu jam, maka penyetelan ulang ini akan terjadi setiap jam, dimulai setelah setengah jam.
Jika Anda ingin menggunakan grafik ini dan grafik lainnya dalam instalasi Prometheus, Anda dapat menggunakan ini dasbor. Ini dirancang untuk PMM tetapi, dengan sedikit modifikasi, cocok dengan instalasi Prometheus mana pun.
Kami memiliki blok aktif yang disebut blok kepala yang disimpan dalam memori; blok dengan data lama tersedia melalui mmap(). Hal ini menghilangkan kebutuhan untuk mengonfigurasi cache secara terpisah, namun juga berarti Anda perlu menyisakan ruang yang cukup untuk cache sistem operasi jika Anda ingin menanyakan data yang lebih lama dari yang dapat ditampung oleh blok head.
Ini juga berarti konsumsi memori virtual Prometheus akan terlihat cukup tinggi, dan hal ini tidak perlu dikhawatirkan.

Analisis TSDB di Prometheus 2

Poin desain menarik lainnya adalah penggunaan WAL (write forward log). Seperti yang Anda lihat dari dokumentasi penyimpanan, Prometheus menggunakan WAL untuk menghindari kerusakan. Sayangnya, mekanisme khusus untuk menjamin kelangsungan data tidak terdokumentasi dengan baik. Prometheus versi 2.3.2 mem-flush WAL ke disk setiap 10 detik dan opsi ini tidak dapat dikonfigurasi pengguna.

Pemadatan

Prometheus TSDB dirancang seperti penyimpanan LSM (Log Structured Merge): blok kepala dipindahkan secara berkala ke disk, sementara mekanisme pemadatan menggabungkan beberapa blok untuk menghindari pemindaian terlalu banyak blok selama kueri. Di sini Anda dapat melihat jumlah blok yang saya amati pada sistem pengujian setelah seharian memuat.

Analisis TSDB di Prometheus 2

Jika Anda ingin mempelajari lebih lanjut tentang penyimpanan tersebut, Anda dapat memeriksa file meta.json, yang berisi informasi tentang blok yang tersedia dan bagaimana blok tersebut terbentuk.

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

Pemadatan di Prometheus terikat pada waktu blok kepala dipindahkan ke disk. Pada titik ini, beberapa operasi serupa dapat dilakukan.

Analisis TSDB di Prometheus 2

Tampaknya pemadatan tidak dibatasi dengan cara apa pun dan dapat menyebabkan lonjakan I/O disk yang besar selama eksekusi.

Analisis TSDB di Prometheus 2

Lonjakan beban CPU

Analisis TSDB di Prometheus 2

Tentu saja, hal ini memiliki dampak yang agak negatif pada kecepatan sistem, dan juga menimbulkan tantangan serius bagi penyimpanan LSM: bagaimana melakukan pemadatan untuk mendukung tingkat permintaan yang tinggi tanpa menyebabkan terlalu banyak overhead?
Penggunaan memori pada proses pemadatan juga terlihat cukup menarik.

Analisis TSDB di Prometheus 2

Kita dapat melihat bagaimana, setelah pemadatan, sebagian besar memori berubah status dari Cached menjadi Free: ini berarti informasi yang berpotensi berharga telah dihapus dari sana. Penasaran apakah itu digunakan di sini fadvice() atau teknik minimalisasi lainnya, atau karena cache telah dibebaskan dari blok yang dihancurkan selama pemadatan?

Pemulihan setelah kegagalan

Pemulihan dari kegagalan membutuhkan waktu, dan untuk alasan yang bagus. Untuk aliran masuk sejuta rekaman per detik, saya harus menunggu sekitar 25 menit hingga pemulihan dilakukan dengan mempertimbangkan drive 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."

Masalah utama dari proses pemulihan adalah konsumsi memori yang tinggi. Meskipun dalam situasi normal server dapat bekerja secara stabil dengan jumlah memori yang sama, jika crash, server mungkin tidak dapat pulih karena OOM. Satu-satunya solusi yang saya temukan adalah menonaktifkan pengumpulan data, membuka server, membiarkannya pulih, dan melakukan boot ulang dengan pengumpulan diaktifkan.

Pemanasan

Perilaku lain yang perlu diingat selama pemanasan adalah hubungan antara kinerja rendah dan konsumsi sumber daya yang tinggi segera setelah permulaan. Selama beberapa, tetapi tidak semua permulaan, saya mengamati beban serius pada CPU dan memori.

Analisis TSDB di Prometheus 2

Analisis TSDB di Prometheus 2

Kesenjangan dalam penggunaan memori menunjukkan bahwa Prometheus tidak dapat mengonfigurasi semua koleksi dari awal, dan beberapa informasi hilang.
Saya belum menemukan alasan pasti atas tingginya beban CPU dan memori. Saya menduga hal ini disebabkan oleh pembuatan deret waktu baru di head block dengan frekuensi tinggi.

Beban CPU melonjak

Selain pemadatan, yang menghasilkan beban I/O yang cukup tinggi, saya melihat lonjakan serius pada beban CPU setiap dua menit. Semburan tersebut lebih lama ketika aliran input tinggi dan tampaknya disebabkan oleh pengumpul sampah Go, dengan setidaknya beberapa inti terisi penuh.

Analisis TSDB di Prometheus 2

Analisis TSDB di Prometheus 2

Lompatan ini tidak terlalu signifikan. Tampaknya ketika hal ini terjadi, titik masuk dan metrik internal Prometheus menjadi tidak tersedia, sehingga menyebabkan kesenjangan data selama periode waktu yang sama.

Analisis TSDB di Prometheus 2

Anda juga dapat melihat bahwa eksportir Prometheus mati selama satu detik.

Analisis TSDB di Prometheus 2

Kita dapat melihat korelasinya dengan pengumpulan sampah (GC).

Analisis TSDB di Prometheus 2

Kesimpulan

TSDB di Prometheus 2 cepat, mampu menangani jutaan rangkaian waktu dan pada saat yang sama ribuan catatan per detik menggunakan perangkat keras yang cukup sederhana. Pemanfaatan CPU dan I/O disk juga mengesankan. Contoh saya menunjukkan hingga 200 metrik per detik per inti yang digunakan.

Untuk merencanakan perluasan, Anda perlu mengingat jumlah memori yang cukup, dan ini harus berupa memori nyata. Jumlah memori yang digunakan yang saya amati adalah sekitar 5 GB per 100 catatan per detik aliran masuk, yang bersama dengan cache sistem operasi memberikan sekitar 000 GB memori yang terisi.

Tentu saja, masih banyak pekerjaan yang harus dilakukan untuk menjinakkan lonjakan CPU dan I/O disk, dan hal ini tidak mengherankan mengingat betapa mudanya TSDB Prometheus 2 dibandingkan dengan InnoDB, TokuDB, RocksDB, WiredTiger, namun semuanya memiliki kesamaan. masalah di awal siklus hidupnya.

Sumber: www.habr.com

Tambah komentar