《消息队列高手课》课程笔记(五)

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

消息重复的情况必然存在

  • 在 MQTT 协议中,给出了三种传递消息时能够提供的服务质量标准,这三种服务质量从低到高依次是:
    • At most once: 至多一次。
      • 消息在传递时,最多会被送达一次。
      • 换个说法就是,没什么消息可靠性保证,允许丢消息。
      • 一般都是一些对消息可靠性要求不太高的监控场景使用,比如每分钟上报一次机房温度数据,可以接受数据少量丢失。
    • At least once: 至少一次。
      • 消息在传递时,至少会被送达一次。
      • 也就是说,不允许丢消息,但是允许有少量重复消息出现。
    • Exactly once:恰好一次。
      • 消息在传递时,只会被送达一次,不允许丢失也不允许重复,这个是最高的等级。
  • 我们现在常用的绝大部分消息队列提供的服务质量都是 At least once,包括 RocketMQ、RabbitMQ 和 Kafka 都是这样。也就是说,消息队列很难保证消息不重复。

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

  • 一般解决重复消息的办法是,在消费端,让我们消费消息的操作具备幂等性。
    • 一个幂等操作的特点是,其任意多次执行所产生的影响均与一次执行的影响相同。
    • At least once + 幂等消费 = Exactly once。
  • 如何实现幂等操作
    • 从业务逻辑设计上入手,将消费的业务逻辑设计成具备幂等性的操作。
    • 利用数据库的唯一约束实现幂等
      • 不光是可以使用关系型数据库,只要是支持类似 “INSERT IF NOT EXIST” 语义的存储类系统都可以用于实现幂等。
      • 可以用 Redis 的 SETNX 命令来替代数据库中的唯一约束,来实现幂等消费。
    • 为更新的数据设置前置条件
      • 另外一种实现幂等的思路是,给数据变更设置一个前置条件,如果满足条件就更新数据,否则拒绝更新数据;
      • 在更新数据的时候,同时变更前置条件中需要判断的数据。
      • 这样,重复执行这个操作时,由于第一次更新数据的时候已经变更了前置条件中需要判断的数据,不满足前置条
        件,则不会重复执行更新数据操作。
      • 更加通用的方法是,给你的数据增加一个版本号属性,每次更数据前,比较当前数据的版本号是否和消息中的版本号一致,如果不一致就拒绝更新数据,更新数据的同时将版本号 +1,一样可以实现幂等更新
    • 记录并检查操作
      • 记录并检查操作,也称为 “Token 机制或者 GUID(全局唯一 ID)机制”,实现的思路特别简单:在执行数据更新操作之前,先检查⼀下是否执行过这个更新操作。
      • 具体的实现方法是,在发送消息时,给每条消息指定一个全局唯一的 ID,消费时,先根据这个 ID 检查这条消息是否有被消费过,如果没有消费过,才更新数据,然后将消费状态置为已消费。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值