RabbitMQ学习(三)——保证消息不被重复消费/保证消息消费幂等性

 MQ 有个基本原则:

        数据不能多一条,也不能少一条。不能多,就是这一篇-----不能重复消费和保证消息幂等性,不能少,就是下一篇的保证消息可靠性传输

重复消费消息的场景:
     场景1:消费者干的事是拿一条数据往数据库写一条,如果消息重复两次就写了两条,导致数据出错。

     解决场景1:同一条消息消息到第二次时判断一下是否已消费过,若是则直接扔掉,一条数据出现两次但是数据库只有一条,这就保证了系统的幂等性。

何为幂等性?(官方定义):一次和多次请求某资源对于资源本身应该有相同的结果(网络超时除外)。也就是,任意多次执行对资源本身产生的影响均与一次执行的结果相同

如何保证消息队列消费的幂等性?(要结合业务):

业务场景1:从生产者拿到个数据后要写库,先根据主键查一下,如果这个数据有了就别插了直接update

业务场景2:如果是写redis的都没问题,因为每次都是set,redis天然的幂等性

业务场景3:需要让生产者发送每条数据的时候加上一个全局唯一的id,消费的时候先根据id去比如redis查一下判断是否消费过,若没有则处理然后这个id写redis,若消费过就不处理

业务场景4:如果数据库有唯一建约束了,插入只会报错,不会导致数据库出现脏数据,本身幂等了

两种方式可解决幂等性操作:

(1)唯一ID + 指纹码机制,利用数据库主键去重

思路:根据消息生成一个全局唯一ID,然后加上一个指纹码。指纹码可以系统生成也可以根据某些规则自定义拼接,目的是确定本次才做唯一,将ID+指纹码作为拼接好的值作为主键就可以去重了,在消费消息前先去数据库查看这条消息指纹码是否存在,没有就插入有就忽视。

高并发写数据库性能瓶颈:可以跟进ID进行分库分表策略,采用一些路由算法进行分流,要保证ID通过这种算法消息即使投递多次都落在同一数据库分片上,这样就由单台数据库幂等变成多库的幂等。

(2)利用Redis的原子性去实现

redis是单线程的,但是性能好也有很多原子性的命令,比如setnx命令,在接收到消息后将消息ID作为key去执行setnx命令,如果执行成功则表示没有执行过这条消息,可以进行消费(setnx命令特点:当且仅当key不存在,将key值设为value值;若key已存在该命令不做任何操作)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值