消息队列-如何保证消息的不被重复消费(如何保证消息消费的幂等性)

  • 2021 年 11 月 19 日
  • 筆記

在消息传递过程中,如果出现传递失败的情况,发送会执行重试,重试可能会产生重复的消息。对系统来说,如果没有对重复消费进行处理,会导致系统数据发生错误。
比如,一个订单系统,订单创建成功后,把数据写入统计数据库,如果发生重复统计,会导致数据库数据错误。

解决消息重复消费,其实就是保证消息的消费幂等性。

幂等性的定义:

多次执行所产生的影响均与一次执行的影响相同。
所以需要从业务逻辑上设计,将消费的业务逻辑设计成幂等性。

利用数据库的唯一约束

在进行消息消费,需要取一个唯一个标识,比如 id 作为唯一约束字段,先添加数据,如果添加失败,后续做错误提示,或者不做后续操作。

Redis 设置全局唯一id

每次生产者发送消息前设置一个全局唯一id放在消息体重,并存放的 redis 里,在消费端接口上先找在redis 查看是否存在全局id,如果存在,调用消费接口并删除全局id,如果不存在,不做后续操作。

多版本(乐观锁)机制

给业务数据添加一个版本号,每次更新数据前,比如当前版本和消息中的版本是否一致,如果一致就更新数据并且版本号+1,如果不一致就不跟新。这有点类似乐观锁处理机制。

总结

设计幂等需要根据具体的业务场景,如果是并发量比较大的系统,数据库一般支撑不了这么大的并发,需要使用 Redis 缓存处理。而并发不大的系统可以选择数据库。

如果觉得文章对你有帮助的话,请点个推荐吧!