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

Durability & Persistence

ทุกอย่างที่ผ่านมาสมมติว่า broker ยังรันอยู่ แต่ broker restart ได้ — deploy, crash, kernel update คำถามที่แยก setup เล่น ๆ ออกจาก production คือ: เมื่อ RabbitMQ restart อะไรยังอยู่?

โดย default น้อยจนน่าผิดหวัง queue กับ message อยู่ใน memory และ restart จะล้างทิ้งเว้นแต่คุณขอ durability ไว้ — และนี่คือกับดักที่เกือบทุกคนพลาด: ต้องใช้ setting สอง ตัวที่เป็นอิสระต่อกัน และถ้ามีตัวเดียวโดยขาดอีกตัวก็ยังทำข้อมูลหาย

การรอด restart ต้องเป็นจริงทั้งสองข้อ:

  1. queue เป็น durable นิยาม ของ durable queue ถูกเขียนลง disk ดังนั้น queue ยังอยู่หลัง restart ตั้ง durable: true ตอน declare
  2. message เป็น persistent body ของ persistent message ถูกเขียนลง disk ตั้ง delivery_mode = 2 (persistent) ตอน publish

ขาดข้อใดข้อหนึ่งก็เสียข้อมูลตอน restart:

flowchart TB
  a["durable queue +
persistent message"] -->|restart| a2["survives"]
  b["durable queue +
transient message"] -->|restart| b2["queue stays,
MESSAGES LOST"]
  c["non-durable queue +
persistent message"] -->|restart| c2["QUEUE GONE
(messages with it)"]
  d["non-durable +
transient"] -->|restart| d2["all lost"]
เฉพาะ durable queue + persistent message เท่านั้นที่รอด restart

incident production คลาสสิก: ทีม declare durable queue รู้สึกปลอดภัย แล้วลืม publish message แบบ persistent queue รอดทุก restart อย่างซื่อสัตย์ — แบบว่าง ๆ เพราะ message ข้างในเป็น transient durable queue, transient message: queue อยู่ ข้อมูลตาย

// 1) durable queue — survives restart
await channel.assertQueue('orders', { durable: true });
// 2) persistent message — body written to disk
channel.sendToQueue('orders', Buffer.from(body), { persistent: true });

การเขียนลง disk ช้ากว่าอยู่ใน memory ดังนั้น persistence มีต้นทุน แต่สังเกตจุดละเอียดสำคัญ: การ mark message เป็น persistent ไม่ การันตีว่าอยู่บน disk ทันทีที่คุณ publish — RabbitMQ อาจ batch การเขียน เพื่อให้แน่ใจว่า message ถูกเก็บอย่างปลอดภัยก่อนคุณถือว่าส่งแล้ว ให้จับคู่ persistence กับ publisher confirm (บทเรียนก่อนหน้า): confirm จะมาถึงก็ต่อเมื่อ message ถูก persist อย่างปลอดภัยแล้วเท่านั้น

ภาพที่ซื่อสัตย์: durable queue + persistent message + publisher confirm คือคอมโบที่ปลอดภัยเต็มที่ และแลก throughput กับ latency บางส่วนเพื่อไม่ทำข้อมูลหายตอน restart สำหรับ stream ที่ volume สูงและทนการหายได้ (metrics, log) คุณอาจจงใจข้าม persistence เพื่อความเร็ว — เป็นทางเลือกที่ถูกต้อง ตัดสินใจอย่างรู้ตัว

durable queue แบบ classic รอด restart ของ หนึ่ง node — แต่ classic queue อยู่บน node เดียวทั้งหมด ดังนั้นถ้า disk ของ node นั้นพัง queue ก็ตายไปด้วย Quorum queue ยกระดับขึ้น: replicate queue ข้ามหลาย node ด้วย Raft consensus algorithm ดังนั้นข้อมูลรอดแม้เสีย node ทั้งตัว ไม่ใช่แค่ restart เป็น default สมัยใหม่สำหรับอะไรก็ตามที่ห้ามหาย — และโมดูล Operations & Scaling จะลงลึกเรื่องนี้

setting สองตัวใดที่ต้องมี *ทั้งคู่* เพื่อให้ message รอด broker restart?
คุณ declare durable queue แต่ publish transient message แล้ว broker restart เกิดอะไรขึ้น?
ทำไมต้องจับคู่ persistence กับ publisher confirm?
quorum queue เพิ่มอะไรจาก classic durable queue?