Rabbit MQ 幂等性(处理消息重复消费问题的思路)


 

1、什么是幂等性

 
借助数据库的乐观锁机制举例:

我们在执行一条更新库存操作的SQL语句时,在高并发的情况下,如何避免库存 count  = 0了,还在减少的情况发生?

解决方案:加上版本号。
每次更新库存前,先根据主键查询 版本号
select count from t_rep where 主键 = **;
假设此时的版本号version = 1, 然后再根据版本号+主键作为条件去更新
update t_reps set count = count - 1,version = version +1 where version = 1 and 主键 = **.

这样当多个人查询到相同的版本号时,只有一个人能修改库存。

 
总结什么是幂等性:

       可能你要对一件事进行一个操作,这个操作你可能要执行一百次或一千次,那么我们最终操作的结果,这一百次一千次的结果都是相同的。

2、消费端的幂等性保障

 
举例:在海量订单产生的业务高峰期,如何避免消息的重复消费问题?

       在高并发的情况下,可能会有很多消息到达MQ,然后我们的消费端要监听大量的消息。这个时候难免会遇到消息的重复投递,或者网络不稳定的原因导致闪断,进而导致 Broker 重发消息,这个时候不去做幂等,就会出现重复消费的问题。

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

3、业界主流的幂等性操作

3.1、唯一ID + 指纹码 机制

扫描二维码关注公众号,回复: 13142028 查看本文章
  • 唯一ID + 指纹码 机制,利用数据库主键去重
  • select count(1) from t_order where id = 唯一ID + 指纹码
  • 好处:实现简单
  • 坏处:高并发下有数据库写入的性能瓶颈。
  • 解决方案:跟进ID进行分库分表进行算法路由

       这里的指纹码可能是我们的一些业务规则,时间戳加上银行返回的唯一码,这个指纹码并不一定是我们系统生成的,而是一些外部的规则或者是我们内部的业务规则去拼接起来的。
 
       指纹码的目的就是为了保障这次操作是绝对唯一的。

       具体的实现过程中,我们要保证 唯一ID + 指纹码在数据库中是唯一的 。在进行具体操作时,我们先通过 唯一ID + 指纹码 去数据库查询,如果没有数据我们就insert插入,如果有数据则证明已经被操作了,我们就不做任何操作。

3.2、利用 Redis 原子特性实现

  • 使用 Redis 进行幂等,需要考虑的问题。
     
  • 第一:我们是否要进行数据落库,如果落库的话,关键解决的问题是数据库和缓存如何做到原子性?
     
  • 第二: 如果不进行落库,那么都存储到缓存中,如何设置定时同步的策略?

 
 
 
 
 
 
 
 
 
 
.

猜你喜欢

转载自blog.csdn.net/weixin_41922349/article/details/108960800