
Salam habr.
Jika seseorang menjalankan sistem grafit-web dan dihadapkan dengan masalah kinerja penyimpanan yang berbisik (IO, konsumsi ruang disk), maka peluang ClickHouse digunakan sebagai pengganti harus ditujukan pada satu. Pernyataan ini menyiratkan bahwa implementasi pihak ketiga, seperti carbonwriter atau go-carbon, sudah digunakan sebagai metrik penerima daemon.
ClickHouse memecahkan masalah yang dijelaskan dengan baik. Misalnya, setelah mentransfer data 2TiB dari bisikan, mereka masuk ke dalam 300GiB. Saya tidak akan membahas perbandingan secara rinci, ada cukup artikel tentang topik ini. Selain itu, hingga saat ini, semuanya sempurna dengan penyimpanan ClickHouse kami.
Masalah konsumsi
Pada pandangan pertama, semuanya harus bekerja dengan baik. Mengikuti dokumentasi , kami membuat konfigurasi untuk skema penyimpanan metrik (selanjutnya disebut retention
), kemudian membuat tabel sesuai dengan rekomendasi backend yang dipilih untuk web grafit: carbon-clickhouse + graphite-clickhouse atau graphouse , tergantung pada tumpukan mana yang digunakan. Dan ... bom waktu menyala.
Untuk memahami yang mana, Anda perlu tahu bagaimana memasukkan dan jalur kehidupan lebih lanjut dari data dalam tabel keluarga mesin * MergeTree ClickHouse (diagram diambil dari presentasi Alexei Zatelepin):
data dimasukkan. Dalam kasus kami, metrik telah tiba.

- Setiap blok tersebut sebelum menulis ke disk diurutkan sesuai dengan kunci
ORDER BY
ditentukan saat membuat tabel. - Setelah mengurutkan,
data ditulis ke disk.

- Server memantau di latar belakang bahwa tidak ada banyak potongan seperti itu, dan memulai
latar belakang ( merge
, selanjutnya
).


- Server berhenti mulai bergabung sendiri begitu data tidak lagi aktif
partition
, tetapi Anda dapat memulai proses secara manual dengan perintah OPTIMIZE
. - Jika hanya ada satu bagian yang tersisa di partisi, maka Anda tidak dapat memulai penggabungan dengan perintah biasa, Anda harus menggunakan
OPTIMIZE ... FINAL
Jadi, metrik pertama tiba. Dan mereka menempati ruang tertentu. Peristiwa selanjutnya dapat sedikit bervariasi tergantung pada banyak faktor:
- Kunci partisi dapat berupa sangat kecil (hari) atau sangat besar (beberapa bulan).
- Konfigurasi retensi dapat mengakomodasi beberapa ambang batas agregasi data yang signifikan di dalam partisi aktif (di mana catatan metrik pergi), atau mungkin tidak.
- Jika ada banyak data, maka bagian paling awal, yang karena penggabungan latar belakang sudah bisa sangat besar (ketika memilih kunci partisi suboptimal), tidak akan bisa bermain-main dengan potongan-potongan kecil yang segar.
Dan semuanya selalu berakhir sama. Tempat yang ditempati oleh metrik di ClickHouse hanya tumbuh jika:
- tidak berlaku
OPTIMIZE ... FINAL
secara manual atau - jangan masukkan data ke semua partisi secara berkelanjutan untuk memulai penggabungan latar belakang cepat atau lambat
Metode kedua tampaknya paling mudah diterapkan dan, oleh karena itu, dia salah dan diuji terlebih dahulu.
Saya menulis skrip python yang cukup sederhana yang mengirim metrik dummy untuk setiap hari dalam 4 tahun terakhir dan dijalankan setiap jam oleh mahkota.
Karena semua pekerjaan ClickHouse DBMS didasarkan pada kenyataan bahwa sistem ini akan melakukan semua pekerjaan latar belakang cepat atau lambat, tetapi tidak diketahui kapan, saya tidak bisa menunggu sampai potongan-potongan besar yang besar berkenan untuk mulai bergabung dengan yang baru. Menjadi jelas bahwa kami harus mencari cara untuk mengotomatiskan optimasi yang dipaksakan.

Lihatlah struktur tabel system.parts . Ini adalah informasi yang komprehensif tentang setiap bagian dari semua tabel di server ClickHouse. Ini berisi, antara lain, kolom-kolom berikut:
- Nama DB (
database
); - nama tabel (
table
); - Nama dan ID
partition
( partition
& partition_id
); - ketika karya itu dibuat (
modification_time
); - tanggal minimum dan maksimum dalam
min_date
(partisi dilakukan berdasarkan hari) ( min_date
& max_date
);
Ada juga tabel system.graphite_retentions , dengan bidang-bidang menarik berikut:
- Nama DB (
Tables.database
); - nama tabel (
Tables.table
); - usia metrik saat agregasi berikutnya (
age
) harus diterapkan;
Jadi:
- Kami memiliki daftar potongan-potongan dan daftar aturan agregasi.
- Gabungkan persimpangan mereka dan dapatkan semua tabel * GraphiteMergeTree.
- Kami mencari semua partisi di mana:
- lebih dari satu potong
- atau waktunya telah tiba untuk menerapkan aturan agregasi berikut, dan
modification_time
lebih tua dari saat itu.
Implementasi
Permintaan ini SELECT concat(p.database, '.', p.table) AS table, p.partition_id AS partition_id, p.partition AS partition,
mengembalikan masing-masing partisi tabel * GraphiteMergeTree yang penggabungannya akan membebaskan ruang disk. Yang tersisa adalah hal kecil: lakukan semuanya dengan OPTIMIZE ... FINAL
permintaan OPTIMIZE ... FINAL
. Implementasi akhir juga memperhitungkan momen bahwa tidak perlu menyentuh partisi dengan catatan aktif.
Inilah yang dilakukan oleh proyek pengoptimal grafit-ch-pengoptimal . Mantan kolega dari Yandex.Market mengujinya di prod, hasil karya bisa dilihat di bawah.

Jika Anda menjalankan program di server dengan ClickHouse, maka itu hanya akan mulai bekerja dalam mode daemon. Sekali satu jam, permintaan akan dieksekusi, memeriksa apakah ada partisi baru yang lebih tua dari tiga hari yang dapat dioptimalkan.
Dalam waktu dekat - untuk menyediakan setidaknya paket deb, dan jika mungkin - juga rpm.
UPD: paket tersedia pada rilis github , dan gambar yang berfungsi dapat ditemukan pada docker-hub di repositori innogames / graphite-ch-optimizer.
Alih-alih sebuah kesimpulan
Selama 9 bulan terakhir, saya menghabiskan banyak waktu di perusahaan InnoGames saya di persimpangan ClickHouse dan graphite-web. Itu adalah pengalaman yang baik, yang memungkinkan untuk dengan cepat beralih dari bisikan ke ClickHouse sebagai gudang metrik. Saya harap artikel ini seperti permulaan siklus tentang perbaikan apa yang telah kami lakukan untuk berbagai bagian tumpukan ini dan apa yang akan dilakukan di masa mendatang.
Beberapa liter bir dan admin dihabiskan untuk pengembangan permintaan bersama dengan v0devil , yang ingin saya sampaikan terima kasih kepadanya. Dan juga untuk meninjau artikel ini.
Halaman proyek di github