一、 状态机

前提条件

  1. 在消费者业务表中存在状态字段,并在消费消息后是变更状态
  2. 状态流转是单向不可逆的。例如:​​status :[1 → 2 → 3 → 4...]​

实现方式

​ 基于数据库乐观锁​​CAS​​​方式。例如: ​​update table set status = 2... where status = 1​

二、 数据库唯一约束

前提条件

  1. 消息消费者在业务表中需要存储​​上游业务唯一id​

实现方式

​ 在消息这业务表中加入​​上游业务唯一id​​并设置为唯一约束。

三、消息去重表

前提条件

  1. 消息消费者必须存在数据库持久化操作
  2. 保证消费者对其业务表数据增删改和去重表入库在同一个​​Connection​​​的同一个​​Transaction​​中

实现方式

  1. 每个库都需要建立一个消息去重表
  2. 对​​上游业务唯一id​​设置唯一约束
  3. 设置消费时间字段,根据业务场景设置记录有效时间​​5d​​​、​​7d​​​、​​10d​​,使用定时任务定时清除过期消费记录
  4. 在消息消费前,根据​​上游业务唯一id​​​查询消息去重表,存在则直接​​ACK​​;在消费者操作完自身业务后,同时保存消息信息到消息去重表

优化方式

​ 可以加入​​redis​​​缓存层,在查询时查询redis是否存在该​​上游唯一id​​​,在消息消费者消息同时存入​​redis​​中,并设置有效期

优点

​ 相对于方法一、方法二可以使用​​注解 ​​​+ ​​AOP​​从业务中解耦,无侵入、统一处理的方案