简介
设想一下只有生产者,而没有消费者的时候或者消费者处理能力比生产能力弱 N 倍的时候,RabbitMQ 上就会堆积大量消息,几万、几十万、几百万。那 RabbitMQ 所在机器的内存、硬盘等硬件资源也是有限的,超过负荷就会出现崩溃的现象,导致消息丢失。
针对这个问题 RabbitMQ 提供了消息过期机制 TTL(Time to Live)。简单理解就是超过一定时间没有被消费的消息,就过期了,要扔掉。
消息 TTL
消息本身有一个过期时间,每个消息之间是不一样的。
队列 TTL
进入队列的所有消息都具有一个固定的过期时间。
如何设置 TTL
没有一个固定的时间,要根据自己的业务、系统架构等等因素来判断。有一些简单的建议:
- TTL 应该要长于服务平均重启所需要的时间: 如果 TTL 时间小于重启时间,那重启的那段时间就会丢失消息了。
- 长于业务高峰期持续的时间: 比如做的是秒杀活动,一般持续 10 ~ 20 分钟左右,那就设置 TTL 为 30 分钟,保留空余时间处理一些残余消息。
- 远长于单个消息的业务处理耗费时间: 单个消息处理需要消耗 10 秒,那总不能 TTL 设置为 8 秒吧。
注意: 在项目中不能仅仅单独使用 TTL,如果超时了,消息就丢失了,一般结合
死信队列
使用,过期的消息都存放到死信队列中,留待后续分析问题。可以查看《死信队列机制》。
使用
单条消息过期时间
// 过期时间 15 秒
AMQP.BasicProperties basicProperties = new AMQP.BasicProperties().builder().expiration("15000").build();
channel.basicPublish(EXCHANGE_NAME, KEY_NAME, basicProperties, "一只英短猫来了".getBytes(StandardCharsets.UTF_8));
队列消息过期时间
针对队列设置的参数,可以针对整个队列中的所有消息的过期时间,在 Web 管控台的新增 Queue 界面也能看到
发布到队列的消息在被丢弃之前可以存活多长时间(毫秒)。
// 配置声明队列时使用的参数
Map<String, Object> args = new HashMap<>(1);
// 设置队列中的消息过期时间
args.put("x-message-ttl", 15000);
// 声明队列
channel.queueDeclare(
// 队列名称,名称的规则:什么类型.干什么的
QUEUE_NAME,
// 持久,如果为 false,重启后队列就没了
true,
// 是否为当前 connection 独占,如果为 true,那其他 connection 就无法连接
false,
// 自动删除,如果为 true,队列中没有消息之后,队列就没了
false,
// 参数
args
);
温馨提示: 当
消息 TTL
和队列 TTL
都存在是,谁先过期就用谁。
文章评论