Kompresi data di Apache Ignite. Pengalaman Sberbank

Saat bekerja dengan volume data yang besar, terkadang masalah ruang disk yang tidak mencukupi bisa menjadi akut. Salah satu cara untuk mengatasi masalah ini adalah kompresi, karena itu, pada peralatan yang sama, Anda dapat meningkatkan volume penyimpanan. Pada artikel ini, kita akan melihat bagaimana kompresi data bekerja di Apache Ignite. Artikel ini hanya akan menjelaskan metode kompresi disk yang diterapkan dalam produk. Metode kompresi data lainnya (melalui jaringan, dalam memori), baik yang diimplementasikan maupun tidak, akan tetap berada di luar cakupan.

Jadi, ketika mode kegigihan aktif, sebagai akibat dari mengubah data dalam cache, Ignite mulai menulis ke disk:

  1. Konten Cache
  2. Write Ahead Log (selanjutnya disebut WAL)

Suatu mekanisme yang disebut pemadatan WAL telah ada sejak lama untuk mengkompres WAL. Apache Ignite 2.8 baru-baru ini dirilis memperkenalkan dua mekanisme lagi untuk mengompresi data pada disk: kompresi halaman disk untuk mengompresi konten cache dan kompresi snapshot halaman WAL untuk mengompresi beberapa catatan WAL. Lebih lanjut tentang ketiga mekanisme di bawah ini.

Kompresi halaman disk


Bagaimana itu bekerja


Untuk memulainya, kita akan membahas secara singkat bagaimana Ignite menyimpan data. Untuk penyimpanan, memori halaman digunakan. Ukuran halaman diatur pada awal node dan tidak dapat diubah pada tahap selanjutnya, juga ukuran halaman harus kekuatan dua dan kelipatan dari ukuran blok sistem file. Halaman dimuat ke dalam RAM dari disk sesuai kebutuhan, ukuran data pada disk dapat melebihi jumlah RAM yang dialokasikan. Jika tidak ada cukup ruang dalam RAM untuk memuat halaman dari disk, halaman lama yang tidak digunakan akan dipaksa keluar dari RAM.

Data disimpan dalam disk dalam bentuk berikut: file terpisah dibuat untuk setiap partisi dari masing-masing grup cache, dalam file ini, dalam urutan indeks yang naik, halaman berjalan satu demi satu. Pengenal halaman penuh berisi pengidentifikasi grup cache, nomor partisi, dan indeks halaman dalam file. Dengan demikian, dengan pengidentifikasi halaman penuh, kami dapat secara unik mengidentifikasi file dan mengimbangi file untuk setiap halaman. Anda dapat membaca lebih lanjut tentang memori halaman dalam sebuah artikel di Apache Ignite Wiki: Ignite Persistent Store - di bawah tenda .

Mekanisme kompresi halaman disk, seperti namanya, berfungsi di level halaman. Ketika mekanisme ini dihidupkan, bekerja dengan data dalam RAM dilakukan sebagaimana adanya, tanpa kompresi apa pun, tetapi pada saat menyimpan halaman dari RAM ke disk, mereka dikompres.

Tetapi untuk mengompres setiap halaman secara terpisah bukanlah solusi untuk masalah ini, Anda perlu mengurangi ukuran file data yang dihasilkan. Jika ukuran halaman tidak lagi diperbaiki, kami tidak bisa lagi menulis halaman ke file satu per satu, karena ini dapat menimbulkan sejumlah masalah:

  • Kami tidak dapat menggunakan indeks halaman untuk menghitung offset di mana ia terletak di file.
  • , , . , . , .
  • , , , .

Agar tidak menyelesaikan masalah ini pada tingkatnya sendiri, kompresi halaman disk di Apache Ignite menggunakan mekanisme sistem file yang disebut file jarang. File jarang adalah file di mana beberapa daerah diisi dengan nol dapat ditandai sebagai lubang. Dalam hal ini, blok sistem file untuk menyimpan lubang-lubang ini tidak akan dialokasikan, akibatnya ruang disk yang disimpan.

Adalah logis bahwa untuk membebaskan blok sistem file, ukuran lubang harus lebih besar dari atau sama dengan blok sistem file, yang menerapkan batasan tambahan pada ukuran halaman Apache Ignite: untuk kompresi untuk memberikan setidaknya beberapa efek, ukuran halaman harus benar-benar lebih besar daripada ukuran blok sistem file . Jika ukuran halaman sama dengan ukuran blok, maka kita tidak akan pernah bisa membebaskan satu blok, karena untuk membebaskan satu blok kita membutuhkan halaman terkompresi untuk menempati 0 byte. Jika ukuran halaman sama dengan ukuran 2 atau 4 blok, kita sudah dapat membebaskan setidaknya satu blok jika halaman kita dikompresi masing-masing setidaknya 50% atau 75%.

Dengan demikian, deskripsi akhir dari mekanisme: Saat menulis halaman ke disk, upaya dilakukan untuk mengompres halaman. Jika ukuran halaman yang dikompresi memungkinkan satu atau lebih blok dari sistem file untuk dibebaskan, maka halaman tersebut ditulis dalam bentuk terkompresi, sebuah "lubang" dilubangi di tempat blok yang dirilis (panggilan sistem dibuat fallocate()dengan bendera "lubang berlubang" dibuat). Jika ukuran halaman terkompresi tidak memungkinkan pembebasan blok, halaman disimpan apa adanya, dalam bentuk terkompresi. Semua offset halaman dipertimbangkan dan tanpa kompresi, dengan mengalikan indeks halaman dengan ukuran halaman. Tidak perlu memindahkan halaman secara mandiri. Offset halaman, dan juga tanpa kompresi, jatuh pada batasan blok sistem file.



Dalam implementasi saat ini, Ignite hanya dapat bekerja dengan file yang jarang di Linux OS, jadi kompresi halaman disk hanya dapat diaktifkan ketika Ignite digunakan pada sistem operasi ini.

Algoritma kompresi yang dapat digunakan untuk kompresi halaman disk: ZSTD, LZ4, Snappy. Selain itu, ada mode operasi (SKIP_GARBAGE), di mana hanya tempat yang tidak digunakan di halaman yang dibuang tanpa menerapkan kompresi ke data yang tersisa, yang memungkinkan untuk mengurangi beban pada CPU dibandingkan dengan algoritma yang tercantum di atas.

Dampak kinerja


Sayangnya, saya tidak benar-benar mengukur kinerja pada tegakan nyata, karena kami tidak berencana untuk menggunakan mekanisme ini dalam produksi, tetapi secara teoritis kami dapat berspekulasi di mana kami akan kehilangan dan di mana kami akan menang.

Untuk melakukan ini, kita perlu mengingat cara membaca dan menulis halaman saat mengaksesnya:

  • Ketika operasi baca dilakukan, pertama kali dicari dalam RAM, jika pencarian gagal, halaman dimuat ke dalam RAM dari disk dengan aliran yang sama yang membaca.
  • Saat melakukan operasi tulis, halaman dalam RAM ditandai sebagai kotor, sementara penyimpanan fisik halaman ke disk segera dalam aliran yang melakukan perekaman tidak terjadi. Semua halaman kotor disimpan ke disk nanti dalam proses pos pemeriksaan di aliran terpisah.

Dengan demikian, efek pada operasi baca:

  • (disk IO), .
  • (CPU), sparse . IO sparse ( sparse , , ).
  • (CPU), .
  • .
  • ( ):
  • (disk IO), .
  • (CPU, disk IO), sparse .
  • (CPU), .

Skala mana yang akan lebih penting? Itu semua sangat tergantung pada lingkungan, tetapi saya cenderung percaya bahwa kompresi halaman disk lebih cenderung menurunkan kinerja pada kebanyakan sistem. Selain itu, tes pada DBMS lain menggunakan pendekatan yang sama dengan file jarang menunjukkan penurunan kinerja ketika kompresi diaktifkan.

Cara mengaktifkan dan mengkonfigurasi


Seperti disebutkan di atas, versi minimum Apache Ignite yang mendukung kompresi halaman disk: 2.8 dan hanya mendukung sistem operasi Linux. Pengaktifan dan pengaturan dilakukan sebagai berikut:

  • Kelas-path harus memiliki modul kompresi penyalaan. Secara default, ini terletak di distribusi Apache Ignite di direktori libs / opsional dan tidak termasuk dalam jalur kelas. Anda cukup memindahkan direktori satu tingkat ke atas ke lib dan kemudian ketika diluncurkan melalui ignite.sh, direktori itu akan dihidupkan secara otomatis.
  • Persistence ( DataRegionConfiguration.setPersistenceEnabled(true)).
  • ( DataStorageConfiguration.setPageSize() ).
  • , () ( CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

WAL compaction



Apa itu WAL dan mengapa itu dibutuhkan? Sangat singkat: ini adalah jurnal di mana semua peristiwa yang berubah sebagai akibat dari repositori halaman jatuh. Dia dibutuhkan terutama untuk kemungkinan pemulihan jika jatuh. Sebelum mentransfer kontrol ke pengguna, operasi apa pun harus terlebih dahulu menulis acara ke WAL, sehingga jika jatuh, ia dapat memutar log dan mengembalikan semua operasi yang menerima respons sukses pengguna, bahkan jika operasi ini tidak memiliki waktu untuk tercermin dalam penyimpanan halaman pada disk (di atas sudah telah dijelaskan bahwa penulisan aktual ke halaman toko dilakukan dalam proses yang disebut pos pemeriksaan dengan beberapa penundaan dalam utas terpisah).

Entri dalam WAL dibagi menjadi logis dan fisik. Yang logis adalah kunci dan nilai itu sendiri. Fisik - mencerminkan perubahan halaman di halaman toko. Jika catatan logis dapat berguna untuk beberapa kasus lain, catatan fisik hanya diperlukan untuk pemulihan jika jatuh dan catatan hanya diperlukan sejak saat pos pemeriksaan terakhir yang berhasil. Di sini kita tidak akan masuk ke rincian dan menjelaskan mengapa ini bekerja dengan cara ini, tetapi siapa pun yang tertarik dapat merujuk ke artikel yang sudah disebutkan di Apache Ignite Wiki: Ignite Persistent Store - di bawah tenda .

Satu catatan logis sering menjelaskan beberapa catatan fisik. Misalnya, satu operasi cache menempatkan beberapa halaman dalam memori halaman (halaman dengan data itu sendiri, halaman dengan indeks, halaman dengan daftar bebas). Pada beberapa tes sintetik, ternyata catatan fisik menempati hingga 90% dari file WAL. Selain itu, mereka membutuhkan waktu yang sangat singkat (secara default, interval antara pos-pos pemeriksaan adalah 3 menit). Adalah logis untuk menyingkirkan data ini setelah kehilangan relevansinya. Ini persis apa yang dilakukan mekanisme pemadatan WAL, menghilangkan catatan fisik dan kompres catatan logis yang tersisa dengan zip, sedangkan ukuran file menurun sangat signifikan (kadang-kadang puluhan kali).

Secara fisik, WAL terdiri dari beberapa segmen (default 10) dengan ukuran tetap (default 64 MB), yang ditimpa dalam lingkaran. Segera setelah segmen saat ini diisi, segmen berikutnya ditetapkan ke segmen saat ini, dan segmen yang diisi disalin ke arsip dalam aliran yang terpisah. Kompaksi WAL sudah berfungsi dengan segmen arsip. Selain itu, dalam aliran terpisah, ia memantau pelaksanaan pos pemeriksaan dan mulai kompresi oleh segmen arsip, yang catatan fisiknya tidak lagi diperlukan.



Dampak kinerja


Karena pemadatan WAL beroperasi sebagai utas terpisah, seharusnya tidak ada pengaruh langsung pada operasi yang dilakukan. Tetapi masih memberikan beban latar belakang tambahan pada CPU (kompresi) dan disk (membaca setiap segmen WAL dari arsip dan menulis segmen terkompresi), jadi jika sistem berjalan ke batas, itu juga akan menyebabkan penurunan kinerja.

Cara mengaktifkan dan mengkonfigurasi


Anda dapat mengaktifkan pemadatan WAL menggunakan properti WalCompactionEnabledc DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Selain itu, menggunakan metode DataStorageConfiguration.setWalCompactionLevel (), Anda dapat mengatur rasio kompresi jika Anda tidak puas dengan nilai default (BEST_SPEED).

Kompresi snapshot halaman WAL


Bagaimana itu bekerja


Kami telah menemukan bahwa dalam WAL, entri dibagi menjadi logis dan fisik. Untuk setiap perubahan setiap halaman dalam memori halaman, catatan WAL fisik dihasilkan. Catatan fisik, pada gilirannya, juga dibagi menjadi 2 subspesies: catatan snapshot halaman dan catatan delta. Setiap kali kami mengubah sesuatu pada halaman dan mengubahnya dari keadaan bersih ke yang kotor, salinan lengkap halaman ini disimpan dalam WAL (catatan foto halaman). Bahkan jika kita mengubah hanya satu byte di WAL, catatan dengan ukuran yang sedikit lebih besar dari ukuran halaman akan disimpan. Jika kita mengubah sesuatu pada halaman yang sudah kotor, maka catatan delta terbentuk di WAL, yang hanya mencerminkan perubahan dibandingkan dengan keadaan halaman sebelumnya, tetapi tidak seluruh halaman. Karena mengatur ulang status halaman dari kotor ke bersih dilakukan selama proses pemeriksaan,segera setelah dimulainya pos pemeriksaan, hampir semua catatan fisik hanya terdiri dari snapshot halaman (karena semua halaman segera setelah dimulainya pos pemeriksaan kosong), maka ketika Anda mendekati pos pemeriksaan berikutnya, proporsi catatan delta mulai bertambah dan direset lagi di awal pos pemeriksaan berikutnya. Pengukuran pada beberapa tes sintetis menunjukkan bahwa bagian dari snapshot halaman dalam volume total catatan fisik mencapai 90%.

Gagasan di balik kompresi snapshot halaman WAL adalah untuk mengompresi snapshot halaman menggunakan alat kompresi halaman yang tidak tersedia (lihat kompresi halaman disk). Pada saat yang sama, di WAL, catatan disimpan secara berurutan dalam mode append-only dan tidak perlu untuk mengikat catatan ke batas blok sistem file, oleh karena itu, di sini, tidak seperti mekanisme kompresi halaman disk, kami sama sekali tidak memerlukan file yang jarang, sehingga mekanisme ini akan bekerja tidak hanya pada OS Linux Selain itu, kami tidak lagi peduli seberapa besar kami dapat mengompres halaman. Bahkan jika kita membebaskan 1 byte, ini sudah merupakan hasil positif dan kita dapat menyimpan data terkompresi di WAL, tidak seperti kompresi halaman disk, di mana kita menyimpan halaman terkompresi hanya jika lebih dari 1 blok sistem file dibebaskan.

Halaman adalah data yang dapat dikompresi dengan baik, bagiannya dalam total volume WAL sangat tinggi, jadi tanpa mengubah format file WAL, kita bisa mendapatkan pengurangan yang signifikan dalam ukurannya. Kompresi catatan logis, antara lain, akan memerlukan perubahan dalam format dan kehilangan kompatibilitas, misalnya, untuk konsumen eksternal yang mungkin tertarik pada catatan logis, tanpa secara signifikan mengurangi ukuran file.

Sedangkan untuk kompresi halaman disk untuk kompresi snapshot halaman WAL, algoritma kompresi ZSTD, LZ4, Snappy, serta mode SKIP_GARBAGE dapat digunakan.

Dampak kinerja


Tidak sulit untuk memperhatikan bahwa penyertaan langsung kompresi snapshot halaman WAL hanya memengaruhi stream yang menulis data ke memori halaman, yaitu stream yang mengubah data dalam cache. Membaca dari catatan fisik WAL hanya terjadi sekali, pada saat menaikkan node setelah jatuh (dan hanya dalam kasus jatuh selama pos pemeriksaan).

Ini mempengaruhi aliran data sebagai berikut: kami mendapatkan efek negatif (CPU) karena kebutuhan untuk mengompres halaman setiap kali sebelum menulis ke disk dan efek positif (disk IO) dengan mengurangi jumlah data yang sedang ditulis. Dengan demikian, semuanya sederhana di sini, jika kinerja sistem bertumpu pada CPU, kami mendapatkan sedikit degradasi, jika dalam disk I / O, kami mendapatkan peningkatan.

Secara tidak langsung, mengurangi ukuran WAL juga mempengaruhi aliran (positif) yang menjatuhkan segmen WAL ke dalam arsip dan aliran pemadatan WAL.

Tes kinerja nyata di lingkungan kita pada data sintetis menunjukkan peningkatan kecil (throughput meningkat 10% -15%, latensi menurun 10% -15%).

Cara mengaktifkan dan mengkonfigurasi


Versi minimum Apache Ignite adalah 2.8. Pengaktifan dan pengaturan dilakukan sebagai berikut:

  • Kelas-path harus memiliki modul kompresi penyalaan. Secara default, ini terletak di distribusi Apache Ignite di direktori libs / opsional dan tidak termasuk dalam jalur kelas. Anda cukup memindahkan direktori satu tingkat ke atas ke lib dan kemudian ketika diluncurkan melalui ignite.sh, direktori itu akan dihidupkan secara otomatis.
  • Kegigihan harus diaktifkan (Diaktifkan melalui DataRegionConfiguration.setPersistenceEnabled(true)).
  • DataStorageConfiguration.setWalPageCompression(), ( DISABLED).
  • DataStorageConfiguration.setWalPageCompression(), javadoc .


Mekanisme kompresi data yang dibahas dalam Apache Ignite dapat digunakan secara independen satu sama lain, tetapi kombinasi keduanya juga valid. Memahami prinsip-prinsip pekerjaan mereka akan menentukan bagaimana mereka sesuai dengan tugas Anda di lingkungan Anda dan apa yang harus Anda korbankan saat menggunakannya. Kompresi halaman disk dirancang untuk mengompresi penyimpanan utama dan dapat memberikan kompresi sedang. Kompresi snapshot halaman WAL akan memberikan tingkat kompresi rata-rata file WAL yang sudah ada, sementara itu kemungkinan akan meningkatkan kinerja. Pemadatan WAL tidak akan mempengaruhi kinerja secara positif, tetapi akan meminimalkan ukuran file WAL dengan menghapus catatan fisik.

All Articles