消息队列_06(如何处理消息消费过程中的重复消息)

如何处理消息消费过程中的重复消息

1.MQTT协议,三种传递消息是的服务质量标准

  1. At most once:至多一次。消息在传递时,最多会被送达一次。允许丢消息
  2. At least once:至少一次。消息在传递时,至少会被传达一次。不允许丢消息,但允许有少量重复消息
  3. Exactly once:恰好一次。消息在传递时,只会被送达一次,不允许丢失也不允许重复。
    这些服务质量标准对所有的消息队列都是适用的,RocketMQ、RabbitMQ和kafka都是At least once标准。

2. 用幂等性解决重复消息问题

在消费端,让我们消费消息的操作具备幂等性

幂等:
函数f(x)满足:f(f(x)) = f(x),则函数f(x)满足幂等性。

一个幂等操作的特点:其任意多次执行所产生的影响均匀一次执行的影响相同。

对于幂等的方法,不用担心重复执行会对系统造成任何改变。

对系统的影响结果来说:At least once + 幂等消费 = Exactly once.

3. 设计幂等操作的方法

3.1利用数据库的唯一约束实现幂等

不光可以使用关系型数据库,只要是支持类似"INSERT IF NOT EXIST" 语义的存储类系统都可以用于实现幂等,比如,可以用redis的SETNX命令来替代。

3.2 为更新的数据设置前置条件

给数据变更设置一个前置条件,如果满足条件就更新数据,否则拒绝更新数据,在更新数据的时候,同时变更前置条件中需要判断的数据。
常用方法:给数据增加一个版本号属性,比较当前数据的版本和消息中版本号是否一致。更新以后版本号+1。

3.3 记录并检查操作

a.也称为:“Token 机制或者GUID(全局唯一ID)机制”;
b.思路:在执行数据更新操作之前,先检查一下是否执行过这个更新操作。
c.具体的实现方法是,在发送消息时,给每条消息指定一个全局唯一的ID,消费是,先根据这个ID检查这条消息是否被消费国,如果没有消费才更新数据,然后将消费状态置为已消费。
d.实现起来不简单,分布式系统中比较难解决

4.问题

为什么大部分消息队列都选择只提供At least once的服务质量,而不是级别更高的Exactly once?

若消息队列实现了exactly once,会引发的问题有:①消费端在pull消息时,需要检测此消息是否被消费,这个检测机制无疑会拉低消息消费的速度。可以预想到,随着消息的剧增,消费性能势必会急剧下降,导致消息积压;②检查机制还需要业务端去配合实现,若一条消息长时间未返回ack,消息队列需要去回调看下消费结果(这个类似于事物消息的回查机制)。这样就会增加业务端的压力,与很多的未知因素。
所以,消息队列不实现exactly once,而是at least once + 幂等性,这个幂等性让给我们去处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值