Retensi

Retensi berbasis waktu dan ukuran, konfigurasi dinamis lewat kafka-configs, dan cara membaca data lama.

Daftar isi

Retensi menetapkan berapa lama pesan tetap tersimpan di log topic sebelum dibersihkan oleh broker. Topik ini menjelaskan dua mekanisme pembersihan yang berbasis waktu dan ukuran, konfigurasi topic yang mengaturnya, perhitungan kebutuhan penyimpanan, dan cara membaca data lama selama masa retensinya belum habis. Setelah membaca topik ini, batas retensi dapat ditetapkan dan diubah secara dinamis tanpa menghentikan broker.

Dua mekanisme retensi#

Broker membersihkan pesan lama melalui kebijakan retensi yang berbasis waktu dan berbasis ukuran. Retensi berbasis waktu menghapus data yang berumur lebih lama dari batas yang ditetapkan, sedangkan retensi berbasis ukuran menghapus data tertua sampai ukuran log berada di bawah batasnya. Keduanya bekerja pada tingkat segmen dan bukan pada pesan tunggal. Log setiap partisi terbagi menjadi segmen berukuran tertentu, dan pembersihan menghapus segmen tertua sampai seluruh segmen yang tersisa berada dalam batas retensi.

Tabel berikut merangkum konfigurasi topic yang menyertai kedua mekanisme tersebut.

KonfigurasiSatuanPerilaku
retention.msmilidetikSegmen yang datanya berumur lebih lama dari batas ini dihapus, misalnya 86400000 untuk satu hari
retention.bytesbyteSegmen tertua dihapus sampai ukuran log pada partisi berada di bawah batas ini
segment.bytesbyteBatas ukuran satu segmen sebelum digulir menjadi segmen baru
log.retention.check.interval.msmilidetikJeda antar pemeriksaan batas retensi oleh broker, dengan nilai bawaan 300000 untuk lima menit

Batas waktu dan batas ukuran dapat ditetapkan sekaligus, dan broker memberlakukan batas yang tercapai lebih dahulu. Nilai khusus -1 menandakan batas yang tidak berlaku, sehingga salah satu batas dapat dimatikan tanpa memengaruhi batas yang lain. Apabila retensi tidak ditetapkan pada topic, nilai bawaan broker yang lazim berupa tujuh hari diberlakukan. Segmen aktif yang sedang ditulis dan belum digulir tidak pernah dihapus, sehingga batas retensi dalam praktik dipenuhi dengan toleransi hingga ukuran satu segmen. Tiga nilai pertama ditetapkan pada tingkat topic, sedangkan log.retention.check.interval.ms ditetapkan pada broker karena pemeriksaannya mencakup seluruh topic sekaligus.

Mengubah retensi secara dinamis#

Retensi dapat diubah menggunakan alat kafka-configs.sh tanpa menghentikan broker. Topic demo bernama m2-retensi-demo disiapkan ulang dengan satu partisi sebelum pengaturannya diubah, sehingga keadaan topic selalu sama pada setiap eksekusi. Penghapusan topic lama diikuti jeda singkat karena proses penghapusannya berjalan tidak serentak di broker. Kegagalan penghapusan pada topic yang belum ada diabaikan karena keadaan itu wajar pada eksekusi pertama.

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

Topic baru tersebut belum membawa konfigurasi dinamis apa pun, sehingga seluruh batas retensinya masih mengikuti nilai bawaan broker. Perintah berikut menetapkan retensi satu hari melalui retention.ms, 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-retensi-demo --add-config retention.ms=86400000
  bin/kafka-configs.sh --bootstrap-server localhost:9092 --describe --entity-type topics --entity-name m2-retensi-demo
)
text Keluaran
Completed updating config for topic m2-retensi-demo.
Dynamic configs for topic m2-retensi-demo are:
  retention.ms=86400000 sensitive=false synonyms={DYNAMIC_TOPIC_CONFIG:retention.ms=86400000}

Baris pertama menyatakan pembaruan selesai dilakukan. Baris berikutnya menampilkan konfigurasi dinamis topic beserta sumber nilainya, yaitu DYNAMIC_TOPIC_CONFIG yang berarti nilai ditetapkan pada topic dan mengesampingkan nilai bawaan broker. Nilai baru berlaku pada topic segera setelah pembaruan, tanpa perpindahan partisi dan tanpa perombakan apa pun pada aplikasi yang menggunakannya. Pemeriksaan dengan --describe menjadi cara cepat untuk memastikan nilai mana yang sedang aktif pada sebuah topic.

Menghitung kebutuhan penyimpanan#

Kebutuhan penyimpanan topic dapat dihitung dari laju pesan, ukuran rata-rata pesan, durasi retensi, dan jumlah partisi. Retensi diberlakukan per partisi, sehingga hasil perhitungan satu partisi dilipatkan sebesar jumlah partisi pada topic. Skrip berikut menghitung satu partisi yang menerima 2000 pesan per detik dengan ukuran rata-rata 512 byte dan retensi tujuh hari.

python estimasi-penyimpanan.py
# estimasi kebutuhan penyimpanan log satu partisi
pesan_per_detik = 2000    # laju pesan pada partisi
ukuran_rata = 512         # ukuran rata-rata pesan dalam byte
retensi_hari = 7          # batas retensi berbasis waktu

detik_per_hari = 24 * 60 * 60
total_byte = pesan_per_detik * ukuran_rata * retensi_hari * detik_per_hari
total_gb = total_byte / (10 ** 9)

print(f"penyimpanan per partisi : {total_byte:,} byte")
print(f"kira-kira               : {total_gb:.1f} GB")
print(f"segmen 1 GiB per partisi: {round(total_byte / 1073741824)} segmen")
text Keluaran
penyimpanan per partisi : 619,315,200,000 byte
kira-kira               : 619.3 GB
segmen 1 GiB per partisi: 577 segmen

Satu partisi menempati sekitar 619.3 GB untuk retensi tujuh hari, dan angka itu dilipatkan sebesar jumlah partisi pada topic yang bersangkutan. Angka 577 segmen diperoleh dengan membagi total ukuran oleh satuan GiB karena segment.bytes berukuran 1 GiB (1.073.741.824 byte), sehingga nilainya lebih kecil daripada pembagian langsung dalam gigabyte desimal. Perhitungan ini belum memasukkan ukuran indeks, header pesan, dan salinan replika, sehingga kebutuhan nyata lebih besar daripada hasilnya. Estimasi semacam ini cukup untuk menetapkan retention.ms, retention.bytes, dan segment.bytes sebelum topic diisi data sungguhan.

Membaca data lama#

Consumer membaca dari posisi offset mana pun selama data masih tersimpan. Consumer yang baru bergabung dapat memulai dari awal log dan menemukan pesan yang ditulis berhari-hari sebelumnya, selama segmen pesan tersebut belum dihapus oleh retensi. Pada console consumer, posisi awal tersebut dipilih dengan opsi --from-beginning, sedangkan klien pemrogram yang belum memiliki offset tersimpan menetapkannya melalui auto.offset.reset=earliest. Dengan demikian, aplikasi yang memproses ulang sejarah kejadian hanya bergantung pada retensi topic dan tidak membutuhkan mekanisme tambahan dari Kafka. Pembacaan juga tidak mempercepat pembersihan karena umur data dihitung dari waktu penulisannya dan bukan dari status pembacaannya.

Data yang sudah dihapus oleh retensi tidak dapat dibaca ulang dalam bentuk apa pun, sehingga retensi bukan pengganti cadangan data. Apabila sejarah panjang perlu tersedia untuk pemrosesan ulang yang jarang, durasi retensi diperpanjang dan biaya penyimpanannya bertambah, atau data disalin ke penyimpanan lain yang lebih murah. Topic yang mengalirkan data musiman, misalnya log sensor suhu harian, lazim menetapkan retensi singkat dan menyalin rekapnya ke penyimpanan jangka panjang.

Kesalahan umum#

Dua kesalahan berikut paling sering terjadi saat retensi dipraktikkan. Keduanya berakar pada anggapan bahwa pembersihan bekerja pada tingkat yang lebih halus daripada mekanisme sebenarnya.

  1. Mengira pesan terhapus setelah dibaca consumer. Pembersihan hanya mengikuti retention.ms dan retention.bytes, sehingga consumer baru yang membaca dari awal tetap menemukan data lama yang tidak diharapkan. Tetapkan retensi yang sesuai bila data lama memang tidak diperlukan, dan perlakukan retensi sebagai satu-satunya mekanisme penghapusan.
  2. Mengira log tepat berada di bawah batas retensi. Pembersihan bekerja pada segmen utuh, sehingga ukuran log dapat melebihi retention.bytes hingga ukuran satu segmen. Sediakan ruang cadangan saat menghitung penyimpanan dan pilih segment.bytes yang tidak terlalu besar agar selisihnya tetap kecil.

Ringkasan#

  • Retensi berbasis waktu melalui retention.ms dan retensi berbasis ukuran melalui retention.bytes membersihkan pesan lama pada tingkat segmen, bukan pada pesan tunggal.
  • Nilai retensi diubah secara dinamis dengan kafka-configs.sh dan berlaku segera tanpa menghentikan broker.
  • Kebutuhan penyimpanan dihitung dari laju pesan, ukuran rata-rata, durasi retensi, dan jumlah partisi, ditambah ruang untuk indeks dan replika.
  • Consumer dapat membaca data lama sejak awal log selama segmennya belum dihapus, dan pembacaan tidak mempercepat pembersihan.

Referensi#