RabbitMQ消费端幂等性概念及解决方案
发布日期:2021-06-30 12:27:42 浏览次数:2 分类:技术文章

本文共 1111 字,大约阅读时间需要 3 分钟。

1 什么是幂等性

用户对于同一操作发起的一次请求或者多次请求的结果是一致的。

比如数据库的乐观锁,在执行更新操作前,先去数据库查询version,然后执行更新语句,以version作为条件,如果执行更新时有其他人先更新了这张表的数据,那么这个条件就不生效了,也就不会执行操作了,通过这种乐观锁的机制来保障幂等性.

2 Con幂等性

2.1 什么是Con幂等性

消费端实现幂等性,就意味着,我们的消息永远不会消费多次,即使我们收到了多条一样的消息。

在业务高峰期最容易产生消息重复消费问题,当Con消费完消息时,在给Pro返回ack时由于网络中断,导致Pro未收到确认信息,该条消息就会重新发送并被Con消费,但实际上该消费者已成功消费了该条消息,这就造成了重复消费.

2.2 主流幂等性实现方案

2.2.1 唯一ID+指纹码

唯一ID +指纹码机制,利用DB主键去重。

SELECT COUNT(1) FROM T_ORDER 		WHERE ID = 唯一ID +指纹码
  • 唯一ID:业务表的主键
  • 指纹码:为了区别每次正常操作的码,每次操作时生成指纹码;可以用时间戳+业务编号或者标志位(具体视业务场景而定)
  • 优势
    实现简单
  • 弊端
    高并发下有数据库写入的性能瓶颈
  • 解决方案
    根据ID进行分库分表算法路由

小结

首先我们需要根据消息生成一个全局唯一ID,然后还需要加上一个指纹码。这个指纹码它并不一定是系统去生成的,而是一些外部的规则或者内部的业务规则去拼接,它的目的就是为了保障这次操作是绝对唯一的。

将ID + 指纹码拼接好的值作为数据库主键,就可以进行去重了。即在消费消息前呢,先去数据库查询这条消息的指纹码标识是否存在,没有就执行insert操作,如果有就代表已经被消费了,就不需要管了

2.2.2 利用Redis的原子性

需要考虑的问题:

  • 是否要进行数据落库,若落库,数据库和缓存如何做到原子性
  • 若不落库,那么都存储到缓存中,如何设置定时同步策略

这里只提用Redis的原子性去解决MQ幂等性重复消费的问题

MQ的幂等性问题 根本在于的是生产端未正常接收ACK,可能是网络抖动、网络中断导致

可能的方案

Con在消费开始时将 ID放入到Redis的BitMap中,Pro每次生产数据时,从Redis的BitMap对应位置若不能取出ID,则生产消息发送,否则不进行消息发送。

但是有人可能会说,万一Con,ProRedis命令执行失败了怎么办,虽然又出现重复消费又出现Redis非正常执行命令的可能性极低,但是万一呢?

OK,我们可以在Redis命令执行失败时,将消息落库,每日用定时器,对这种极特殊的消息进行处理。

转载地址:https://javaedge.blog.csdn.net/article/details/108935099 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:RabbitMQ实战 - Confirm机制
下一篇:RocketMQ的集群模式

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月11日 08时50分27秒