TTL 看起来简单——到时间就删。但过期是在什么时刻真正发生的?队列 TTL 和消息 TTL 谁说了算?expiration=0 是什么意思?队列自己的 TTL 又怎么算?这篇一项项在 RabbitMQ 4.3.6 上量。
(秒, ready): [(0.0, 10), (0.62, 10), (1.26, 0), (1.91, 0)]
消息 TTL 到点后从队列里移除(走死信或丢弃),消费者不会收到;实测 1000 ms 约 1 秒时整批过期。
3 秒后 ready = 11(11 条:队头没有过期,后面已经过期的 10 条不会被清掉) basic_get 取空,实际拿到: ['head-no-ttl'](已过期的 10 条在到达队头时被丢掉,消费者看不到)
过期检查只在队头进行:队头没过期时,后面过期的消息继续占用队列,到达队头时才被丢弃,消费者看不到它们。
exp500(队列 TTL 2000):[(0.0, 1), (0.9, 0), (1.8, 0), (2.7, 0)] exp5000(队列 TTL 2000):[(0.0, 1), (0.9, 1), (1.8, 0), (2.7, 0)]——较小的 2000 ms 生效
队列的 x-message-ttl 与消息的 expiration 同时存在时取较小的。
无消费者 + expiration=0:队列里 ready = 0 有一个空闲消费者 + expiration=0:消费者收到 ['with-consumer']
expiration=0 表示只在能立即投递给消费者时保留,否则立刻丢弃。
声明后什么都不做,用 rabbitmqctl list_queues(不算“使用”)每 0.5 s 看一次: [(0.0, True), (0.9, True), (1.9, True), (2.8, False), (3.7, False), (4.7, False)] 每秒做一次 passive 声明: [(1, True), (2, True), (3, True), (4, True), (5, True), (6, True)]——passive 声明也重置了计时,队列一直在 有一个消费者连着时,5 秒后队列还在: True 消费者断开后,每 0.5 s 看一次: [(0.0, True), (0.9, True), (1.8, True), (2.8, False), (3.7, False), (4.6, False)]
x-expires 是队列无人使用多久后被删除。消费者连着、basic_get、重新声明(包括 passive)都算使用。
重启后队列 t6 的 ready = 0
过期时间从发布时刻起算,broker 停机期间也在走,重启后已过期的消息不再出现。