ข้ามไปยังเนื้อหา

Retention กับ Compaction

Kafka ไม่ได้เก็บข้อมูลตลอดไปโดย default — cleanup policy ของ topic ตัดสินว่า record เก่าจะถูก ลบ หลังพ้น retention window หรือถูก compact ให้เหลือแค่ ค่าล่าสุดต่อ key.

ด้วย policy default cleanup.policy=delete Kafka ลบ log segment เก่าเมื่อเกิน threshold:

# Keep records for 7 days (whichever limit hits first)
cleanup.policy=delete
retention.ms=604800000
# ...or cap the partition at 50 GB
retention.bytes=53687456000

Retention บังคับที่ระดับ segment ทั้งก้อน ไม่ใช่ทีละ record และดูที่ อายุหรือขนาด — ไม่ได้ดูว่ามีใคร consume ไปแล้วหรือยัง consumer ที่ตามหลังเกิน retention window จะพลาด record ที่หมดอายุไป policy นี้เหมาะกับ event stream ที่ event เก่าหมดคุณค่า: clickstream, log, metric.

ตั้ง cleanup.policy=compact แล้ว Kafka เปลี่ยนกลยุทธ์ทั้งหมด แทนที่จะทิ้งข้อมูลเก่าตามอายุ Kafka จะเก็บ record ล่าสุดของแต่ละ key และค่อยๆ garbage-collect ค่าเก่าของ key นั้น:

before compaction: (a,1)(b,1)(a,2)(c,1)(b,2)(a,3)
after compaction: (c,1)(b,2)(a,3) ← latest value per key survives

แบบนี้เปลี่ยน topic ให้เป็น snapshot ของ state ปัจจุบันตาม key ที่ durable และ replay ได้ — เหมาะกับ changelog, config และ state store ที่ Kafka Streams เก็บ consumer ใหม่เอี่ยมอ่านทั้ง compacted topic แล้วสร้าง state ล่าสุดของทุก key ขึ้นมาใหม่ได้

flowchart TB
  topic["Topic cleanup.policy"] --> del["delete: ทิ้ง segment ที่พ้น retention.ms / retention.bytes"]
  topic --> comp["compact: เก็บ record ล่าสุดต่อ key, GC ค่าเก่า"]
  del --> use1["event stream: log, click, metric"]
  comp --> use2["state/changelog: config, snapshot, Streams store"]
delete ทิ้ง segment เก่า ส่วน compact เก็บค่าล่าสุดต่อ key

ภายใต้ compaction จะลบ key ทั้งอันยังไง? เขียน tombstone — record ที่มี key และ value เป็น null compaction มองว่า “key นี้หายไปแล้ว” เก็บ tombstone ไว้นานพอให้ consumer ทุกตัวเห็นการลบ แล้วค่อยลบทั้ง tombstone และ history ของ key นั้น

// Tombstone: null value tells a compacted topic to forget this key
await producer.send({
topic: 'user-config',
messages: [{ key: 'user-42', value: null }],
})

รวม policy ได้ด้วย cleanup.policy=compact,delete เพื่อ compact ตาม key และ ยังทยอยลบข้อมูลที่เก่ามากออกไป

  • delete — ตัว record คือประเด็น history สำคัญ ค่าล่าสุดต่อ key ไม่สำคัญ เหมาะกับ event stream.
  • compactค่าล่าสุดของ key คือประเด็น อยากได้ snapshot ที่สร้างใหม่ได้ เหมาะกับ state, changelog, config topic.
cleanup.policy=delete ทำอะไร?
log compaction เก็บอะไรไว้?
ลบ key ออกจาก compacted topic ยังไง?
topic แบบไหนเหมาะกับ cleanup.policy=compact ที่สุด?