消息队列本身不能保证消息不重复
mqtt消息传递的服务质量标准
- at most onece:至多一次 消息传递没有质量保证,允许丢消息
- at least onece:至少一次 不允许丢消息,但允许可能会有少量重复消息
- exactly onece:恰好一次 只会被送达一次,不允许丢失也不允许重复
这种服务质量标准不仅适用mqtt,对所有消息队列都是适用的,也就是说消息队列很难保证不重复
解决消息重复问题
用幂等解决消息重复问题
幂等操作
其任意多次执行所产生的影响均和一次执行的影响一样
At least once + 幂等消费 = 恰好一次,Exactly onece
从业务逻辑设计上入手,将消费的业务逻辑设计成具备幂等性的操作
常用的幂等操作
- 1、数据库的唯一索引、redis的setnx等来实现幂等操作
- 2、更新数据增加前置判断,乐观锁
乐观锁
乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做;
乐观锁实现方式
即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据
- 3、token机制或者GUID(全局ID)机制
具体的实现方法是
在发送消息时,给每条消息指定一个全局唯一的 ID,消费时,先根据这个 ID 检查这条消息是否有被消费过,如果没有消费过,才更新数据,然后将消费状态置为已消费。
内容来源说明:文章中的部分内容以及图片来自《极客时间-消息队列高手课》,写文章目的只是作为学习后的总结和整理