Alexey Lizunov, kepala pusat kompetensi saluran layanan jarak jauh dari Direktorat Teknologi Informasi ICD
Sebagai alternatif dari tumpukan ELK (ElasticSearch, Logstash, Kibana), kami sedang melakukan penelitian tentang penggunaan database ClickHouse sebagai gudang data untuk log.
Dalam artikel ini, kami ingin berbicara tentang pengalaman kami menggunakan database ClickHouse dan tentang hasil awal dari operasi percontohan. Harus segera dicatat bahwa hasilnya mengesankan.

Selanjutnya, kami akan menjelaskan secara lebih terperinci bagaimana sistem kami dikonfigurasikan dan terdiri dari komponen apa itu. Tetapi sekarang saya ingin berbicara sedikit tentang database ini secara keseluruhan, dan mengapa Anda harus memperhatikannya. Basis data ClickHouse adalah basis data kolom analitik kinerja tinggi dari Yandex. Ini digunakan dalam layanan Yandex, awalnya merupakan gudang data utama untuk Yandex.Metrica. Sistem open-source gratis. Dari sudut pandang pengembang, saya selalu tertarik pada bagaimana mereka mengimplementasikannya, karena ada data yang luar biasa besar. Dan antarmuka pengguna metrik itu sendiri sangat fleksibel dan cepat. Pada kenalan pertama dengan database ini, kesan: βYa, akhirnya! Dibuat "untuk orang-orang"! Mulai dari proses instalasi dan diakhiri dengan mengirim permintaan. "
Basis data ini memiliki ambang masuk yang sangat rendah. Bahkan rata-rata pengembang yang terampil dapat menginstal database ini dalam beberapa menit dan mulai menggunakannya. Semuanya bekerja dengan jelas. Bahkan orang yang baru mengenal Linux dapat dengan cepat melewati instalasi dan melakukan operasi sederhana. Sebelumnya, ketika kata Big Data, Hadoop, Google BigTable, HDFS, pengembang biasa memiliki gagasan bahwa mereka berbicara tentang beberapa terabyte, petabyte, bahwa beberapa manusia super terlibat dalam pengaturan dan pengembangan untuk sistem ini, kemudian dengan munculnya database ClickHouse yang kami dapatkan. Alat sederhana dan mudah dipahami untuk menyelesaikan berbagai tugas yang sebelumnya tidak dapat dicapai. Hanya satu mobil yang cukup rata-rata dan lima menit untuk menginstal. Yaitu, kami mendapat basis data seperti, misalnya, MySql, tetapi hanya untuk menyimpan miliaran catatan! Semacam pengawas SQL. Seolah-olah orang diberikan senjata alien.
Tentang sistem pengumpulan log kami
Untuk mengumpulkan informasi, file log IIS dari aplikasi web dengan format standar digunakan (kami juga terlibat dalam penguraian log aplikasi, tetapi tujuan utama pada tahap operasi percontohan bersama kami adalah untuk mengumpulkan log IIS).
Karena berbagai alasan, kami gagal untuk sepenuhnya meninggalkan tumpukan ELK, dan kami terus menggunakan komponen LogStash dan Filebeat, yang telah membuktikan diri dengan baik dan bekerja dengan cukup andal dan dapat diprediksi.
Skema pembalakan umum disajikan pada gambar di bawah ini:

Fitur penulisan data ke database ClickHouse adalah penyisipan catatan yang jarang (sekali per detik) dalam kumpulan besar. Ini, tampaknya, adalah bagian paling "bermasalah" yang Anda temui ketika Anda pertama kali bekerja dengan database ClickHouse: skema ini agak rumit.
Plugin LogStash banyak membantu di sini, yang secara langsung memasukkan data ke dalam ClickHouse. Komponen ini digunakan pada server yang sama dengan database itu sendiri. Jadi, secara umum, tidak disarankan untuk melakukannya, tetapi dari sudut pandang praktis, agar tidak menghasilkan server yang terpisah saat digunakan di server yang sama. Kami tidak melihat adanya kegagalan atau konflik sumber daya dengan database. Selain itu, perlu dicatat bahwa plugin memiliki mekanisme retray jika terjadi kesalahan. Dan jika terjadi kesalahan, plugin menulis ke disk paket data yang tidak dapat dimasukkan (format file nyaman: setelah diedit, Anda dapat dengan mudah memasukkan paket yang diperbaiki menggunakan clickhouse-client).
Daftar lengkap perangkat lunak yang digunakan dalam skema disajikan dalam tabel:
Daftar perangkat lunak yang digunakan Konfigurasi server dengan database ClickHouse disajikan dalam tabel berikut:
Seperti yang Anda lihat, ini adalah workstation biasa.
Struktur tabel untuk menyimpan log adalah sebagai berikut:
log_web.sqlCREATE TABLE log_web ( logdate Date, logdatetime DateTime CODEC(Delta, LZ4HC), fld_log_file_name LowCardinality( String ), fld_server_name LowCardinality( String ), fld_app_name LowCardinality( String ), fld_app_module LowCardinality( String ), fld_website_name LowCardinality( String ), serverIP LowCardinality( String ), method LowCardinality( String ), uriStem String, uriQuery String, port UInt32, username LowCardinality( String ), clientIP String, clientRealIP String, userAgent String, referer String, response String, subresponse String, win32response String, timetaken UInt64 , uriQuery__utm_medium String , uriQuery__utm_source String , uriQuery__utm_campaign String , uriQuery__utm_term String , uriQuery__utm_content String , uriQuery__yclid String , uriQuery__region String ) Engine = MergeTree() PARTITION BY toYYYYMM(logdate) ORDER BY (fld_app_name, fld_app_module, logdatetime) SETTINGS index_granularity = 8192;
Kami menggunakan nilai default untuk mempartisi (berdasarkan bulan) dan rincian indeks. Semua bidang praktis sesuai dengan entri log IIS untuk mendaftarkan permintaan http. Secara terpisah, bidang terpisah untuk menyimpan tag utm (mereka diuraikan pada tahap penyisipan ke tabel dari bidang string kueri).
Juga dalam tabel ditambahkan beberapa bidang sistem untuk menyimpan informasi tentang sistem, komponen, server. Lihat tabel di bawah ini untuk deskripsi bidang ini. Dalam satu tabel, kami menyimpan log untuk beberapa sistem.
Ini memungkinkan Anda membangun grafik secara efektif di Grafana. Misalnya, melihat permintaan dari frontend sistem tertentu. Ini mirip dengan penghitung situs di Yandex.Metrica.
Berikut adalah beberapa statistik tentang penggunaan basis data selama dua bulan.
Jumlah catatan berdasarkan sistem dan komponen SELECT fld_app_name, fld_app_module, count(fld_app_name) AS rows_count FROM log_web GROUP BY fld_app_name, fld_app_module WITH TOTALS ORDER BY fld_app_name ASC, rows_count DESC ββfld_app_nameββββββ¬βfld_app_moduleββ¬βrows_countββ β site1.domain.ru β web β 131441 β β site2.domain.ru β web β 1751081 β β site3.domain.ru β web β 106887543 β β site3.domain.ru β svc β 44908603 β β site3.domain.ru β intgr β 9813911 β β site4.domain.ru β web β 772095 β β site5.domain.ru β web β 17037221 β β site5.domain.ru β intgr β 838559 β β site5.domain.ru β bo β 7404 β β site6.domain.ru β web β 595877 β β site7.domain.ru β web β 27778858 β ββββββββββββββββββββ΄βββββββββββββββββ΄βββββββββββββ Totals: ββfld_app_nameββ¬βfld_app_moduleββ¬βrows_countββ β β β 210522593 β ββββββββββββββββ΄βββββββββββββββββ΄βββββββββββββ 11 rows in set. Elapsed: 4.874 sec. Processed 210.52 million rows, 421.67 MB (43.19 million rows/s., 86.51 MB/s.)
Jumlah data pada disk SELECT formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed, formatReadableSize(sum(data_compressed_bytes)) AS compressed, sum(rows) AS total_rows FROM system.parts WHERE table = 'log_web' ββuncompressedββ¬βcompressedββ¬βtotal_rowsββ β 54.50 GiB β 4.86 GiB β 211427094 β ββββββββββββββββ΄βββββββββββββ΄βββββββββββββ 1 rows in set. Elapsed: 0.035 sec.
Tingkat kompresi data dalam kolom SELECT name, formatReadableSize(data_uncompressed_bytes) AS uncompressed, formatReadableSize(data_compressed_bytes) AS compressed, data_uncompressed_bytes / data_compressed_bytes AS compress_ratio FROM system.columns WHERE table = 'log_web' ββnameββββββββββββββββββββ¬βuncompressedββ¬βcompressedββ¬βββββcompress_ratioββ β logdate β 401.53 MiB β 1.80 MiB β 223.16665968777315 β β logdatetime β 803.06 MiB β 35.91 MiB β 22.363966401202305 β β fld_log_file_name β 220.66 MiB β 2.60 MiB β 84.99905736932571 β β fld_server_name β 201.54 MiB β 50.63 MiB β 3.980924816977078 β β fld_app_name β 201.17 MiB β 969.17 KiB β 212.55518183686877 β β fld_app_module β 201.17 MiB β 968.60 KiB β 212.67805817411906 β β fld_website_name β 201.54 MiB β 1.24 MiB β 162.7204926761546 β β serverIP β 201.54 MiB β 50.25 MiB β 4.010824061219731 β β method β 201.53 MiB β 43.64 MiB β 4.617721053304486 β β uriStem β 5.13 GiB β 832.51 MiB β 6.311522291936919 β β uriQuery β 2.58 GiB β 501.06 MiB β 5.269731450124478 β β port β 803.06 MiB β 3.98 MiB β 201.91673864241824 β β username β 318.08 MiB β 26.93 MiB β 11.812513794583598 β β clientIP β 2.35 GiB β 82.59 MiB β 29.132328640073343 β β clientRealIP β 2.49 GiB β 465.05 MiB β 5.478382297052563 β β userAgent β 18.34 GiB β 764.08 MiB β 24.57905114484208 β β referer β 14.71 GiB β 1.37 GiB β 10.736792723669906 β β response β 803.06 MiB β 83.81 MiB β 9.582334090987247 β β subresponse β 399.87 MiB β 1.83 MiB β 218.4831068635027 β β win32response β 407.86 MiB β 7.41 MiB β 55.050315514606815 β β timetaken β 1.57 GiB β 402.06 MiB β 3.9947395692010637 β β uriQuery__utm_medium β 208.17 MiB β 12.29 MiB β 16.936148912472955 β β uriQuery__utm_source β 215.18 MiB β 13.00 MiB β 16.548367623199912 β β uriQuery__utm_campaign β 381.46 MiB β 37.94 MiB β 10.055156353418509 β β uriQuery__utm_term β 231.82 MiB β 10.78 MiB β 21.502540454070672 β β uriQuery__utm_content β 441.34 MiB β 87.60 MiB β 5.038260760449327 β β uriQuery__yclid β 216.88 MiB β 16.58 MiB β 13.07721335008116 β β uriQuery__region β 204.35 MiB β 9.49 MiB β 21.52661903446796 β ββββββββββββββββββββββββββ΄βββββββββββββββ΄βββββββββββββ΄βββββββββββββββββββββ 28 rows in set. Elapsed: 0.005 sec.
Deskripsi komponen yang digunakan
FileBeat. Transfer File Log
Komponen ini memonitor perubahan dalam file log pada disk dan mentransfer informasi ke LogStash. Itu diinstal pada semua server di mana file log ditulis (biasanya IIS). Ini bekerja dalam mode ekor (mis., Hanya mentransfer catatan yang ditambahkan ke file). Namun secara terpisah, Anda dapat mengonfigurasi seluruh transfer file. Ini berguna ketika Anda perlu mengunduh data dari bulan-bulan sebelumnya. Cukup masukkan file log dalam folder dan dia akan membacanya secara keseluruhan.
Ketika layanan berhenti, data tidak lagi ditransfer ke penyimpanan.
Contoh konfigurasi adalah sebagai berikut:
filebeat.yml filebeat.inputs: - type: log enabled: true paths: - C:/inetpub/logs/LogFiles/W3SVC1
LogStash Pengumpul log
Komponen ini dimaksudkan untuk menerima entri log dari FileBeat (atau melalui antrian RabbitMQ), mem-parsing dan menyisipkan bundel ke dalam database ClickHouse.
Untuk memasukkan ke dalam ClickHouse, plugin Logstash-output-clickhouse digunakan. Plugin Logstash memiliki mekanisme untuk mengambil permintaan, tetapi dengan shutdown reguler, lebih baik menghentikan layanan itu sendiri. Ketika Anda berhenti, pesan akan terakumulasi dalam antrian RabbitMQ, jadi jika Anda berhenti untuk waktu yang lama, maka lebih baik menghentikan Filebeats di server. Dalam skema di mana RabbitMQ tidak digunakan (pada jaringan lokal, Filebeat mengirim log langsung ke Logstash), Filebeats bekerja dengan cukup dapat diterima dan aman, sehingga bagi mereka ketidaktercapaian output tidak akan berdampak.
Contoh konfigurasi adalah sebagai berikut:
log_web__filebeat_clickhouse.conf input { beats { port => 5044 type => 'iis' ssl => true ssl_certificate_authorities => ["/etc/logstash/certs/ca.cer", "/etc/logstash/certs/ca-issuing.cer"] ssl_certificate => "/etc/logstash/certs/server.cer" ssl_key => "/etc/logstash/certs/server-pkcs8.key" ssl_verify_mode => "peer" add_field => { "fld_server_name" => "%{[fields][fld_server_name]}" "fld_app_name" => "%{[fields][fld_app_name]}" "fld_app_module" => "%{[fields][fld_app_module]}" "fld_website_name" => "%{[fields][fld_website_name]}" "fld_log_file_name" => "%{source}" "fld_logformat" => "%{[fields][fld_logformat]}" } } rabbitmq { host => "queue.domain.com" port => 5671 user => "q-reader" password => "password" queue => "web_log" heartbeat => 30 durable => true ssl => true
ClickHouse. Penyimpanan log
Log untuk semua sistem disimpan dalam satu tabel (lihat bagian awal artikel). Ini dimaksudkan untuk menyimpan informasi tentang permintaan: semua parameter serupa untuk format yang berbeda, misalnya, log IIS, apache, dan log nginx. Untuk log aplikasi yang, misalnya, kesalahan, pesan informasi, peringatan dicatat, tabel terpisah akan disediakan dengan struktur yang sesuai (sekarang pada tahap desain).
Saat mendesain tabel, sangat penting untuk menentukan kunci utama (dimana data akan diurutkan selama penyimpanan). Tingkat kompresi data dan kecepatan kueri bergantung pada ini. Dalam contoh kita, kuncinya adalah
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Yaitu, dengan nama sistem, nama komponen sistem dan tanggal acara. Tanggal asli acara berada di tempat pertama. Setelah memindahkannya ke tempat terakhir, kueri mulai bekerja sekitar dua kali lebih cepat. Mengubah kunci utama akan membutuhkan pembuatan ulang tabel dan memuat ulang data sehingga ClickHouse akan mengurutkan kembali data pada disk. Ini adalah operasi yang sulit, sehingga disarankan untuk memikirkan sebelumnya apa yang harus dimasukkan dalam kunci sortir.
Juga harus dicatat bahwa dalam versi terbaru jenis data LowCardinality telah muncul. Saat menggunakannya, ukuran data terkompresi berkurang tajam untuk bidang-bidang yang memiliki kardinalitas rendah (beberapa opsi).
Sekarang versi 19.6 digunakan, dan kami berencana untuk mencoba memperbarui versi ke yang terbaru. Mereka termasuk fitur luar biasa seperti Adaptive Granularity, Melewati indeks dan codec DoubleDelta, misalnya.
Secara default, selama instalasi, level log konfigurasi diatur untuk dilacak. Log diputar dan diarsipkan, tetapi diperluas hingga satu gigabyte. Jika tidak perlu, maka Anda dapat mengatur tingkat peringatan, maka ukuran log berkurang tajam. Pengaturan pencatatan diatur dalam file config.xml:
<level>warning</level>
Beberapa perintah yang bermanfaat Debian, Linux Altinity. : https://www.altinity.com/blog/2017/12/18/logstash-with-clickhouse sudo yum search clickhouse-server sudo yum install clickhouse-server.noarch 1. sudo systemctl status clickhouse-server 2. sudo systemctl stop clickhouse-server 3. sudo systemctl start clickhouse-server ( ";") clickhouse-client
LogStash Router log FileBeat ke antrian RabbitMQ
Komponen ini digunakan untuk merutekan log yang berasal dari FileBeat ke antrian RabbitMQ. Ada dua poin:
- Sayangnya, FileBeat tidak memiliki plugin output untuk menulis langsung ke RabbitMQ. Dan fungsi seperti itu, dilihat dari ish pada github mereka, tidak direncanakan untuk implementasi. Ada plugin untuk Kafka, tetapi karena alasan tertentu kita tidak bisa menggunakannya di rumah.
- Ada persyaratan untuk mengumpulkan log di DMZ. Berdasarkan pada mereka, log pertama-tama harus ditambahkan ke antrian dan kemudian LogStash dari luar membaca entri dari antrian.
Oleh karena itu, justru untuk kasus lokasi server di DMZ bahwa Anda harus menggunakan skema yang sedikit rumit. Contoh konfigurasi adalah sebagai berikut:
iis_w3c_logs__filebeat_rabbitmq.conf input { beats { port => 5044 type => 'iis' ssl => true ssl_certificate_authorities => ["/etc/pki/tls/certs/app/ca.pem", "/etc/pki/tls/certs/app/ca-issuing.pem"] ssl_certificate => "/etc/pki/tls/certs/app/queue.domain.com.cer" ssl_key => "/etc/pki/tls/certs/app/queue.domain.com-pkcs8.key" ssl_verify_mode => "peer" } } output {
RabbitMQ. Antrian pesan
Komponen ini digunakan untuk buffer entri log di DMZ. Perekaman dilakukan melalui sekelompok Filebeat β LogStash. Membaca dilakukan dari luar DMZ melalui LogStash. Saat beroperasi melalui RabboitMQ, sekitar 4 ribu pesan diproses per detik.
Perutean pesan dikonfigurasikan sesuai dengan nama sistem, yaitu berdasarkan data konfigurasi FileBeat. Semua pesan terbagi dalam satu antrian. Jika, karena alasan apa pun, layanan antrian dihentikan, ini tidak akan menyebabkan hilangnya pesan: FileBeats akan menerima kesalahan koneksi dan menunda pengiriman sementara. Dan LogStash, yang dibaca dari antrian, juga akan menerima kesalahan jaringan dan menunggu koneksi untuk melanjutkan. Data, tentu saja, tidak akan lagi ditulis ke dalam basis data.
Instruksi berikut digunakan untuk membuat dan mengonfigurasi antrian:
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin declare exchange
Grafana Dasbor
Komponen ini digunakan untuk memvisualisasikan data pemantauan. Dalam hal ini, Anda harus menginstal sumber data ClickHouse untuk plugin Grafana 4.6+. Kami harus mengubah sedikit untuk meningkatkan efisiensi pemrosesan filter SQL pada dashboard.
Misalnya, kami menggunakan variabel, dan jika tidak disetel di bidang filter, kami ingin agar tidak menghasilkan kondisi dalam formulir WHERE (uriStem = `` AND uriStem! = ''). Dalam hal ini, ClickHouse akan membaca kolom uriStem. Secara umum, kami mencoba berbagai opsi dan akhirnya memperbaiki plugin (macro $ valueIfEmpty) sehingga jika ada nilai kosong, ia akan mengembalikan 1, tanpa menyebutkan kolom itu sendiri.
Dan sekarang Anda dapat menggunakan kueri ini untuk bagan
$columns(response, count(*) c) from $table where $adhoc and $valueIfEmpty($fld_app_name, 1, fld_app_name = '$fld_app_name') and $valueIfEmpty($fld_app_module, 1, fld_app_module = '$fld_app_module') and $valueIfEmpty($fld_server_name, 1, fld_server_name = '$fld_server_name') and $valueIfEmpty($uriStem, 1, uriStem like '%$uriStem%') and $valueIfEmpty($clientRealIP, 1, clientRealIP = '$clientRealIP')
yang dikonversi ke SQL tersebut (perhatikan bahwa bidang uriStem kosong dikonversi menjadi hanya 1)
SELECT t, groupArray((response, c)) AS groupArr FROM ( SELECT (intDiv(toUInt32(logdatetime), 60) * 60) * 1000 AS t, response, count(*) AS c FROM default.log_web WHERE (logdate >= toDate(1565061982)) AND (logdatetime >= toDateTime(1565061982)) AND 1 AND (fld_app_name = 'site1.domain.ru') AND (fld_app_module = 'web') AND 1 AND 1 AND 1 GROUP BY t, response ORDER BY t ASC, response ASC ) GROUP BY t ORDER BY t ASC
Kesimpulan
Munculnya database ClickHouse telah menjadi peristiwa penting di pasar. Sulit membayangkan bahwa gratis dalam sekejap, kami dipersenjatai dengan alat yang kuat dan praktis untuk bekerja dengan data besar. Tentu saja, dengan meningkatnya kebutuhan (misalnya, sharding dan replikasi ke beberapa server), skema ini akan menjadi lebih kompleks. Tetapi pada kesan pertama, bekerja dengan database ini sangat bagus. Dapat dilihat bahwa produk tersebut dibuat "untuk manusia."
Dibandingkan dengan ElasticSearch, biaya penyimpanan dan pemrosesan log, menurut perkiraan awal, dikurangi dari lima menjadi sepuluh kali lipat. Dengan kata lain, jika untuk jumlah data saat ini kita harus mengkonfigurasi sekelompok beberapa mesin, maka ketika menggunakan ClickHouse kita hanya perlu satu mesin berdaya rendah. Ya, tentu saja, ElasticSearch juga memiliki mekanisme untuk mengompresi data pada disk dan fitur lain yang dapat secara signifikan mengurangi konsumsi sumber daya, tetapi dibandingkan dengan ClickHouse, ini akan mahal.
Tanpa optimasi khusus untuk bagiannya, pada pengaturan default, memuat data dan mengambil data dari database bekerja dengan kecepatan luar biasa. Sejauh ini kami memiliki sedikit data (sekitar 200 juta catatan), tetapi server itu sendiri lemah. Di masa mendatang, kita dapat menggunakan alat ini untuk tujuan lain yang tidak terkait dengan penyimpanan log. Misalnya, untuk analitik ujung ke ujung, di bidang keamanan, pembelajaran mesin.
Pada akhirnya, sedikit tentang pro dan kontra.
Cons
- Mengunduh catatan dalam bundel besar. Ini, di satu sisi, adalah fitur, tetapi Anda masih harus menggunakan komponen tambahan untuk merekam buffer. Tugas ini tidak selalu sederhana, tetapi masih bisa dipecahkan. Dan saya ingin menyederhanakan skema.
- Beberapa fungsionalitas eksotis atau fitur baru sering rusak dalam versi baru. Ini menimbulkan kekhawatiran, mengurangi keinginan untuk meningkatkan ke versi baru. Misalnya, mesin tabel Kafka adalah fitur yang sangat berguna yang memungkinkan Anda untuk langsung membaca acara dari Kafka, tanpa penerapan konsumen. Namun dilihat dari banyaknya Isu pada github, kami masih khawatir menggunakan mesin ini dalam produksi. Namun, jika Anda tidak membuat gerakan tajam ke samping dan menggunakan fungsionalitas dasar, maka itu berfungsi secara stabil.
Pro
- Itu tidak melambat.
- Ambang entri rendah.
- Sumber terbuka
- Ini gratis.
- Timbangan dengan baik (sharding / replikasi out-of-box)
- Ini termasuk dalam daftar perangkat lunak Rusia yang direkomendasikan oleh Kementerian Komunikasi.
- Kehadiran dukungan resmi dari Yandex.