rabbitMQ消息丢失、重复消费解决方案

  • Post author:
  • Post category:其他

消息丢失

在这里插入图片描述

生产者端丢失

RabbitMQ 事务机制(同步)
开启 confirm 模式(异步效率高)
设置开启 confirm 模式之后,你每次写的消息都会分配一个唯一的 id,然后如果写入了 RabbitMQ 中,RabbitMQ 会给你回传一个 ack 消息,告诉你说这个消息 ok 了。如果 RabbitMQ 没能处理这个消息,会回调你的一个 nack 接口,告诉你这个消息接收失败,你可以重试。而且你可以结合这个机制自己在内存里维护每个消息 id 的状态,如果超过一定时间还没接收到这个消息的回调,那么你可以重发。
事务机制和 cnofirm 机制最大的不同在于,事务机制是同步的,你提交一个事务之后会阻塞在那儿,但是 confirm 机制是异步的,你发送个消息之后就可以发送下一个消息,然后那个消息 RabbitMQ 接收了之后会异步回调你的一个接口通知你这个消息接收到了。
所以一般在生产者这块避免数据丢失,都是用 confirm 机制的。

RabbitMq宕机丢失

开启 RabbitMQ 的持久化
默认会先缓存到oscache中,再异步持久化到磁盘。
如果缓存到oscache中还未来得及持久化磁盘就宕机,也可能造成丢失。因此可以开启同步刷盘+主从备份
在这里插入图片描述

消费者端丢失

消息刚发给消费者,业务逻辑尚未处理完,此时已经自动确认,消费者宕机,会造成消息丢失。
关闭自动ack,在业务逻辑处理完之后,手动进行ack确认

总结:

在这里插入图片描述

重复消费

消息幂等表

在这里插入图片描述
可以采用mysql主键唯一索引,或者redis做消息幂等表。

单一、普通、镜像、远程双活、多活

**单一模式:**即单机情况不做集群,就单独运行一个 rabbitmq 而已。
**普通模式:**默认模式,以两个节点(rabbit01、rabbit02)为例来进行说明。对于 Queue 来说,消息实体只存在于其中一个节点 rabbit01(或者 rabbit02),rabbit01 和 rabbit02 两个节点仅有相同的元数据,即队列的结构。当消息进入 rabbit01 节点的 Queue 后,consumer 从 rabbit02 节点消费时,RabbitMQ 会临时在 rabbit01、rabbit02 间进行消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer。所以 consumer 应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理 Queue。否则无论 consumer 连 rabbit01 或 rabbit02,出口总在 rabbit01,会产生瓶颈。当 rabbit01 节点故障后,rabbit02 节点无法取到 rabbit01 节点中还未消费的消息实体。如果做了消息持久化,那么得等 rabbit01 节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。
**镜像模式:**把需要的队列做成镜像队列,存在与多个节点属于 RabbitMQ 的 HA 方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。
远程模式:远程模式可以实现双活的一种模式,简称Shovel模式,所谓Shovel就是我们可以把消息进行不同数据中心的复制工作,我们可以跨地域的让两个MQ集群互联,比如说一个集群,我们都会放在一个机房里面,那么如果北京的机房出现了一些事故停电,或者自然灾害,那么这个集群都会宕机了,那么在我们对数据要求极高的大型应用我们需要设置多活或者双活的模式,也就是要搭建多个数据中心,或者多套集群,那么这些集群可以一个会放在上海,一个放在北京,还有应放在广州,三个集群数据都是同步的,中间有任何一个集群出现了问题,马上灵活的切换,那么这三个集群都是可以访问的话,我们可能会按照距离,或者访问速度来进行优先选择哪组集群,或者数据中心进行访问,所有多活模式,在银行开发的时候一般也叫做容灾的机制,至少构建两套集群放在不同的地域,一个有问题了,立马进行切换,不至于整个系统宕机,这就是多活模式,在多活模式中MQ也提供了相应的实现方式,早期使用的Shovel模式,这个模式是mq自带的一种模式,主要就是可以把消息在不同的数据中心进行负载分发,主要就是可以实现跨地域的让两个mq集群进行互联。
那么这个shovel模式需要统一的版本,网络达到一个什么样的水平,配置的话也是有些复杂,这种的话目前已经淘汰了,在真正的数据复制的情况下,会使用多活模式。
**多活模式:**这种模式也是实现异地数据复制的主流模式,这种模式是依赖rabbimq的fedrtation插件的模式
本身不是mq自带的东西,是在mq上进行了扩展,而这种扩展是实现的可靠的AMQP的数据通信,因此配置起来也比较容易,相当于配置简单化之后的shovel


版权声明:本文为m0_37712622原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。