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

TTL & Limits

ถ้า producer เร็วกว่า consumer queue จะโตแบบไม่มีขอบเขตจนกิน memory หรือ disk ของ broker — แล้วทุกอย่างก็หยุดชะงัก TTL และ length limit คือราวกันตกที่ใส่เพดานให้การโตนั้น และให้คุณตัดสินใจว่า จะทิ้งอะไร แทนที่จะล้มทั้งระบบ

TTL (time-to-live) ทำให้ message หมดอายุหลังจากจำนวนมิลลิวินาทีที่ตั้งไว้ ตั้งได้สองแบบ:

  • ต่อ queue (x-message-ttl) — ทุก message ใน queue หมดอายุหลัง N ms
  • ต่อ message (property expiration) — message ตัวนี้โดยเฉพาะหมดอายุหลัง N ms

เมื่อ message หมดอายุ RabbitMQ จะลบออกจาก queue ที่สำคัญคือ ถ้า queue มี dead-letter exchange message ที่หมดอายุจะถูก dead-letter แทนที่จะถูกทิ้งเงียบ ๆ — ที่เป็นพื้นฐานทั้งหมดของทริค delayed-retry ด้านล่าง

Queue TTL (x-expires) ต่างออกไป: ตัวนี้ลบ ทั้ง queue หลังจาก queue ไม่ถูกใช้ (ไม่มี consumer, ไม่มี get) เป็นเวลา N ms มีประโยชน์สำหรับเก็บกวาด queue ชั่วคราว

x-max-length จำกัดจำนวน message (หรือ x-max-length-bytes จำกัดขนาดรวม) เมื่อ queue เต็มและมี message ใหม่มาถึง พฤติกรรม overflow ตัดสินว่าอะไรจะยอม:

  • drop-head (default) — ทิ้ง message ที่เก่าที่สุดเพื่อเปิดที่ให้ตัวใหม่
  • reject-publish — reject message ตัวใหม่ (บอก publisher ได้ผ่าน publisher confirms)

การเลือกระหว่างสองแบบเป็นการตัดสินใจจริง: drop-head เอาข้อมูลสดไว้ก่อน (ดีสำหรับ live metrics), reject-publish เลือกไม่ทำอะไรหายและ push back ไปที่ producer (ดีสำหรับงานที่ทิ้งไม่ได้)

await channel.assertQueue('events', {
durable: true,
arguments: {
'x-message-ttl': 60000, // messages expire after 60s
'x-max-length': 10000, // keep at most 10k messages
'x-overflow': 'reject-publish', // reject new ones when full
},
});

นี่คือเหตุผลที่ TTL สำคัญเกินกว่าการเก็บกวาด ใส่ TTL บน queue ที่ ไม่มี consumer แล้วชี้ dead-letter exchange ของตัวเองกลับไปที่ main queue ของคุณ message ที่ส่งไปที่นั่นจะนั่งรอตาม TTL หมดอายุ แล้วถูก dead-letter กลับเข้า flow หลัก — เป็น delay โดยไม่ต้องมี scheduler

flowchart LR
  main["main queue"] -->|"fail, ส่งไป retry"| retry["retry queue
(TTL 30s, ไม่มี consumer)"]
  retry -->|"TTL หมดอายุ → dead-letter"| main
  main --> worker["consumer"]
retry queue: TTL หมดอายุแล้ว dead-letter กลับไปที่ main queue

นี่คือวิธีมาตรฐานของ RabbitMQ ในการทำ retry-with-backoff และโมดูล Reliability กับ Consumer Patterns ต่อยอดจากทริคนี้โดยตรง

เกิดอะไรกับ message เมื่อ TTL หมดอายุ ถ้า queue มี dead-letter exchange?
x-max-length ที่ใช้ overflow แบบ drop-head (default) ทำอะไรเมื่อ queue เต็ม?
คุณต้องไม่ทำ message หายและอยาก push back ไปที่ producer เมื่อ queue เต็ม ควรใช้ overflow แบบไหน?
คุณสร้าง delayed retry-with-backoff ใน RabbitMQ โดยใช้ TTL อย่างไร?