前言
RabbitMQ用了也有一两年了,知识点也是工作后零散的掌握,今天小小总结一下
正文
1. 高可用
高可用的通俗解释是,能够7*24小时不间断的对外提供服务。由于单机存在单点故障,随时可能发生宕机,所以一般都是通过搭建集群来保证高可用的
RabbitMQ有三种模式,单机模式就不做过多解释了,demo级别的,生产一般不可能使用单机模式,除非MQ只是用来打印日志
1.1 普通集群模式
- queue的元数据包含了queue的具体信息,例如queue放在哪台broker上,是否持久化等,但不包含发送到queue里的消息
- 单台broker只有集群中部分的queue(queue中包含消息)和集群中所有的queue元数据
- 订阅queue1的消费者若在queue2拉取,则消息会先从queue1传输到queue2,再由消费者进行消费
1.2 镜像集群模式
- 无论元数据还是 queue 里的消息都会存在于多个broker上
- 每个queue都想拥有多个镜像放在其他broker上,可以选择镜像队列的数量
- 由于每个broker上都具有近乎完整的数据,所以消费者消费的时候并不需要进行消息传输,但由于并不是想Kafka分布式消息队列那样的分片存储,所以性能并不高
小小总结一下,RabbitMQ其实并不是分布式消息队列,大厂使用的分布式消息队列,更多是RocketMQ或者Kafka,可以分布式分片存储,水平扩容性能会有明显提升
2. 高可靠
关于生产者的confirm机制和消费者的ack机制,我们这里不展开了,毕竟属于比较基础的知识
高可靠也分成三个方面,生产者高可靠、MQ高可靠和消费者高可靠
生产者的高可靠主要是依靠补偿机制来实现的,确保生产者能够将消息发送至MQ,如果发送失败,则需要进行重发
2.1 发送高可靠
2.1.1 日志记录 + 定时任务健康检查 + 消息补偿
- 发送消息前,先将消息存入消息表,状态为0
- 开启confirm机制,收到ack后,修改消息对应状态为1
- 定时轮询状态为0的消息进行重发,超过3次则标记为异常,人工补偿
2.1.2 消息延迟投递 + 二次确认 + 回调检查
关于延迟队列,可以采用死信队列或者插件机制实现,这里不展开,这里只需要关注生产者发送就好了
- 生产者发送消息的时候,同时也发送延迟消息,比如60min
- 消费者订阅到消息后,会给回调检查服务订阅的confirm queue发送消息,消息数据库生成一条记录
- 回调检查服务订阅了延迟queue,60min过后,消费延迟消息,如果数据库已经存在该消息,则什么都不做,如果数据库不存在,则表明消费者尚未消费该消息,则通知生产者重新发送消息
2.2 存储高可靠
RabbitMQ提供了持久化机制,交换器、队列、消息都可以进行持久化,具体的配置也不麻烦,大家自行查阅即可
2.3 消费高可靠
消费者高可靠,一是保证消息能够被消费者消费(消费者ack机制),二是保证消息重复消费的幂等性
关于消息消费的幂等性
- 主要是通过一个唯一的键进行查重,比如数据库主键ID
- 消息消费的时候,判断该ID是否已经被记录
- 如果未记录,则记录该ID,如果已记录,则什么都不做。
数据库唯一ID、去重表、Redis,基本都是这个思路
2.3.1 多版本(乐观锁)控制
乐观锁的方案可以参考这篇 RabbitMQ应用问题消息的可靠性保障(消息补偿机制)和幂等性问题(乐观锁解决方案)思路
参考文章
- 消息中间件系列教程(14) -RabbitMQ-自动补偿机制
- 字节跳动面试官这样问消息队列:高可用、不重复消费、可靠传输、顺序消费、消息堆积,我整理了下
- RabbitMQ应用问题消息的可靠性保障(消息补偿机制)和幂等性问题(乐观锁解决方案)思路
- 【RabbitMQ】补偿机制、消息幂等性、最终一致性、消息顺序性
- 消息队列的消费幂等性如何保证
结语
关于文章所讲的一些概念,可能还没讲清楚,留着以后复盘的时候再补充吧, 毕竟学习本身就是需要经常回顾才能沉淀下来的一件事情
还是那句话,输出倒逼输入,大家一起学习,共同进步
最后,本人所有文章不做商业用途,如若侵权,还请联系删除~