Log compaction

Log compaction untuk menyimpan nilai terkini per key dan pola changelog pada topic terkompaksi.

Daftar isi

Log compaction adalah mekanisme pembersihan yang menyimpan nilai terkini untuk setiap key dan menghapus nilai-nilai lama untuk key yang sama. Topik ini menjelaskan cara kerja compaction pada log berkunci, simulasi sederhananya, aktivasi pada topic melalui cleanup.policy, dan pola changelog yang menjadi kegunaan utamanya. Setelah membaca topik ini, topic terkompaksi dapat dipilih secara sadar sebagai penyimpanan keadaan terkini.

Cara kerja log compaction#

Topic yang dibersihkan dengan compaction menerapkan aturan yang berbeda dari retensi biasa. Compaction memindai log per key dan menyimpan pesan dengan offset terbesar untuk setiap key, sedangkan pesan-pesan dengan key sama yang lebih tua dihilangkan. Pesan yang tersimpan tetap menempati posisi offset aslinya, sehingga urutan pembacaan tidak berubah dan hanya jarak antar offset yang muncul. Sebagai akibatnya, bagian log yang sudah dikompaksi berisi tepat satu pesan terkini untuk setiap key yang pernah muncul.

Pembersihan tidak berjalan seketika setiap ada pesan baru. Broker menunggu hingga rasio bagian kotor, yaitu bagian log yang berisi duplikat key sejak pembersihan sebelumnya, melampaui min.cleanable.dirty.ratio. Dengan nilai bawaan 0.5, compaction baru berjalan apabila separuh log berisi data yang dapat dikompaksi. Nilai yang lebih kecil membuat pembersihan lebih sering dan penggunaan diska lebih hemat, sedangkan nilai yang lebih besar menunda biaya pembersihan dengan imbalan penggunaan diska yang lebih besar.

Compaction hanya menyentuh segmen yang sudah tertutup, sedangkan segmen aktif yang sedang ditulis dibiarkan utuh. Karena itu, consumer yang membaca dari ujung log masih dapat menemukan pesan duplikat pada bagian terbaru sebelum pembersihan berikutnya berjalan. Pola ini wajar karena compaction menghasilkan log yang bersih untuk pembacaan dari awal, bukan kebersihan yang berlaku seketika di seluruh log.

Simulasi compaction#

Perilaku compaction dapat diamati tanpa broker melalui simulasi sederhana. Log pada skrip berikut memuat pembacaan suhu dua ruangan yang ditulis lima kali, dengan key berupa identitas ruangan dan nilai berupa suhu terbaru. Skrip menyimulasikan pembersihan compaction menggunakan Python murni dan mencetak log sebelum serta sesudahnya.

python simulasi-kompaksi.py
# log mentah satu partisi topic berkunci: pasangan (offset, key, nilai)
log = [
    (0, "ruang-1", "24.1"),
    (1, "ruang-2", "21.0"),
    (2, "ruang-1", "24.7"),
    (3, "ruang-1", "24.3"),
    (4, "ruang-2", "21.5"),
]

# compaction menyimpan kemunculan terakhir untuk setiap key
terkini = {}
for offset, key, nilai in log:
    terkini[key] = (offset, nilai)

print("Log sebelum compaction:")
for offset, key, nilai in log:
    print(f"  offset={offset} key={key} nilai={nilai}")

print("Log setelah compaction:")
for key in sorted(terkini):
    offset, nilai = terkini[key]
    print(f"  offset={offset} key={key} nilai={nilai}")
text Keluaran
Log sebelum compaction:
  offset=0 key=ruang-1 nilai=24.1
  offset=1 key=ruang-2 nilai=21.0
  offset=2 key=ruang-1 nilai=24.7
  offset=3 key=ruang-1 nilai=24.3
  offset=4 key=ruang-2 nilai=21.5
Log setelah compaction:
  offset=3 key=ruang-1 nilai=24.3
  offset=4 key=ruang-2 nilai=21.5

Compaction menyimpan offset 3 untuk key ruang-1 karena pesan itu adalah tulisan terakhir untuk key tersebut, dan menyimpan offset 4 untuk key ruang-2. Pesan pada offset 0, 1, dan 2 hilang karena nilai-nilainya sudah digantikan oleh tulisan yang lebih baru. Log hasil compaction mulai dari offset 3 sehingga tampak jarak pada urutan offset, tetapi pesan yang tersisa tetap berurutan sesuai penulisan aslinya. Consumer yang membaca dari awal log setelah pembersihan hanya menerima satu suhu terkini untuk setiap ruangan.

Mengaktifkan compaction pada topic#

Mode pembersihan dipilih lewat konfigurasi cleanup.policy. Nilai delete memberlakukan pembersihan berbasis waktu pada segmen, nilai compact memberlakukan log compaction, dan kombinasi delete,compact menjalankan keduanya pada topic yang sama. Topic demo bernama m2-kompaksi-demo disiapkan ulang dengan satu partisi sebelum mode pembersihannya diubah, sehingga konfigurasi dinamisnya selalu dimulai dari keadaan kosong.

bash
(
  cd /home/kal/my-project/kafka-runtime/kafka
  bin/kafka-topics.sh --bootstrap-server localhost:9092 --delete --if-exists --topic m2-kompaksi-demo 2>/dev/null
  sleep 2
  bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic m2-kompaksi-demo --partitions 1
)
text Keluaran
Created topic m2-kompaksi-demo.

Topic tersebut mengikuti mode bawaan broker delete sampai mode pembersihannya diganti. Perintah berikut menetapkan cleanup.policy=compact, kemudian menampilkan konfigurasi dinamisnya.

bash
(
  cd /home/kal/my-project/kafka-runtime/kafka
  bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --entity-type topics --entity-name m2-kompaksi-demo --add-config cleanup.policy=compact
  bin/kafka-configs.sh --bootstrap-server localhost:9092 --describe --entity-type topics --entity-name m2-kompaksi-demo
)
text Keluaran
Completed updating config for topic m2-kompaksi-demo.
Dynamic configs for topic m2-kompaksi-demo are:
  cleanup.policy=compact sensitive=false synonyms={DYNAMIC_TOPIC_CONFIG:cleanup.policy=compact, DEFAULT_CONFIG:log.cleanup.policy=delete}

Baris terakhir memuat kolom synonyms yang memperlihatkan rantai nilai, yaitu nilai dinamis pada topic yang mengesampingkan nilai bawaan broker log.cleanup.policy=delete. Perubahan mode pembersihan berlaku secara dinamis seperti perubahan nilai retensi. Topic terkompaksi lazim juga menetapkan min.cleanable.dirty.ratio sesuai pola aksesnya, misalnya nilai yang lebih kecil untuk topic yang dibaca ulang dari awal setiap saat. Konfigurasi tersebut ditetapkan pada perintah yang sama melalui daftar nilai pada opsi --add-config.

Pola changelog#

Penggunaan utama compaction adalah pola changelog, yaitu log perubahan yang mencatat keadaan terkini untuk setiap key. Layanan yang menyimpan keadaan aplikasi menulis setiap perubahan ke topic terkompaksi dengan key berupa identitas entitasnya, misalnya catatan-42 untuk satu catatan pada aplikasi pengolah teks. Karena compaction menjaga satu nilai terkini per key, pembacaan ulang log dari awal menghasilkan keadaan terkini seluruh entitas tanpa menumpuk data lama. Pola inilah yang secara internal digunakan oleh state store pada Kafka Streams, dan berlaku sama untuk aplikasi yang dibangun sendiri di atas topic terkompaksi.

Penghapusan entitas ditandai dengan tombstone, yaitu pesan dengan nilai kosong untuk sebuah key. Tombstone diberi masa tunggu melalui delete.retention.ms sebelum key itu dihilangkan dari log, sehingga consumer yang sedang berjalan sempat menerima sinyal penghapusannya. Setelah masa tunggu berlalu, compaction menghilangkan tombstone beserta nilai terakhir untuk key tersebut. Dengan aturan ini, log terkompaksi menyajikan keadaan yang benar, baik bagi consumer lama yang membaca secara sekuensial maupun consumer baru yang membangun ulang keadaannya dari awal.

Ringkasan#

  • Log compaction menyimpan pesan dengan offset terbesar untuk setiap key dan menghapus duplikat yang lebih tua tanpa mengubah urutan offset.
  • Pembersihan berjalan ketika rasio bagian kotor melampaui min.cleanable.dirty.ratio, dan hanya menyentuh segmen yang sudah tertutup.
  • Mode pembersihan dipilih lewat cleanup.policy yang dapat diubah secara dinamis, dengan nilai delete, compact, atau kombinasinya.
  • Pola changelog menggunakan topic terkompaksi sebagai penyimpanan keadaan terkini per key, dengan tombstone sebagai sinyal penghapusan entitas.

Referensi#