问题背景
- 越来越多的关键业务开始使用RabbitMQ,比如支付,外卖订单,所以深入理解RabbitMQ如何保证消息的可靠性非常重要。
- 本文可靠性主要指消息接收后不丢,并且保证至少投递一次。
- 消息不丢对MQ来说消息的非常关键,但是没有一种机制能保证绝对可靠,所以深入理解RabbitMQ的保证可靠性的手段,然后尽量避免踩到可能丢消息的坑。
不同场景下的可靠性
可靠性保证级别 | 可靠级别 | 保证手段 | 行为 | 丢失消息的场景 | 缺点 | ||
---|---|---|---|---|---|---|---|
场景一 | 高 | 开启持久化开启镜像队列开启confirm | 消息同步写到双节点的磁盘才返回成功 | 两个节点同时宕机,重启后所有消息都可以恢复一个节点宕机,不会造成丢消息 | confirm是采用pipeline异步回复的,存在状态不一致风险,如果客户端同步等待confirm,性能会非常低。无法和数据库事务结合 | ||
场景二 | 高 | 开启持久化开启镜像队列 开启事务 | 消息同步写到双节点的内存队列,后台线程异步刷磁盘 | 两个节点同时宕机,没来得及持久化的消息会丢失; 一个节点宕机,不会造成丢消息 | 主要是性能损耗比较大,QPS只有confirm的一半左右,通过抓包分析也能验证这个结果。 | 当前的默认行为 | |
场景三 | 中 | 关闭持久化开启镜像队列 | 消息只同时写到两个节点的内存,不刷磁盘 | 两个节点同时宕机,所有消息都会丢失一个节点宕机,不会造成消息宕机 | 高性能,高可用,但是两个节点同时宕机会丢消息 | ||
场景四 | 低 | 关闭持久化关闭镜像队列 | 消息只同时写到一个节点的内存,不刷磁盘 | 两个节点同时宕机,所有消息都会丢失一个节点宕机,消息丢失,但是服务依然可用,queue可以切换到另外的机器 | 纯粹为高性能,可靠性低,任何一个节点宕机,都会导致消息丢失 |
参考资料
https://www.rabbitmq.com/ha.html
https://www.rabbitmq.com/confirms.html
https://www.rabbitmq.com/tutorials/tutorial-two-python.html
http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/