自己对 RabbitMQ 的理解
最基本的几种模式
MQ 的特点
削锋:减少高峰时期对服务器的压力
异步:对于不是特别重要的一些请求。假如说有一个操作,要调用三个服务,A 服务 200ms,B 服务 300ms,C 服务 200ms,如果不使用 mq 的话,用户至少要等 700ms,使用 mq 的话,直接发送 3 条消息到 mq 里,大大减少了耗时时间,同时用户体验也上个档次
解耦:一个系统调用多个模块。互相调用的关系很复杂很麻烦。如果没有消息队列,每当一个新业务接入,我们都要在主系统调用新接口。使用消息队列,我们只需要关心是否送达。服务自己订阅想要的信息即可
消息基于什么传输?
由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。
消息确认机制和消息重发机制
如何防止消息丢失
首先消息丢失可能出现在生产者,mq 和消费者中。我们分情况讨论
生产者丢失
首先来说一下生产者丢失,生产者丢失就是数据发送到 mq 的时候,可能数据在半路就丢失了,比如网络问题。这个时候有 2 中解决方案。第一种是使用 rabbitmq 提供的事务功能,就是生产者发送数据之前开启事务 channel.txselect。这样如果消息没有被 mq 接到,生产者就会异常报错,此时可以回滚事务 channel.txrollback,然后重发消息。如果成功收到了消息,可以提交事务 channel.txcommit 但这样太耗性能并且吞吐量相对来说比较低。第二种是可以使用 confirm 模式,每次都会分配一个唯一 id,如果成功写入 mq,返回一个 ack 信息,如果没有西入禁区,回调一个 nack 接口、事务和 confirm 机制的最大不同在于事务是同步的,会阻塞在那里,但 confirm 是异步的。所以我们一般使用 confirm
Mq丢失
Mq 本身丢失了数据。我们可以使用持久化解决这个问题。也就是将消息写入磁盘。这样就算挂了,恢复之后也会自动读取之前持久化的数据 首先我们开启队列持久化,创建队列的时候设置为 true,然后将消息的 deliveryMode 设置为 2 这个是消息持久化。这两个设置下来后,哪怕 mq 宕机了,重启之后,也会从磁盘上恢复队列,恢复队列的数据
消费者丢失
假如说,我们消费某一条消息的时候,消费到一半,mq 宕机了,或者 mq 重启了。这条消息不就没了。我们怎么处理呢 我们可以使用 mq 提供的 ack 机制,设置为手动签收。这样的话,每次处理完之后,我们用代码手动的签收一下就可以了。