1、使用MVCC原理
使用mysql的乐观锁,在数据库中加一个版本号的字段,每次都带上版本号处理。版本号一致才进行消费处理,不一致则不处理,说明是重复消息。
例:
比如说我现在有一张用户表,每次MQ在消费都需要去修改 phone 电话这个字段,sql语句如下,
update user_info set phone = 123456 where id = 1;
为了解决重复消费的问题现在对这张表加个version 的字段,每次修改后 version 版本号加一。假如当前的version版本号为 1 ,然后需要修改这个这个表的 phone字段,执行的sql如下:
update user_info set phone = 654321 , version = version + 1 where id = 1 and version = 1
执行完后,version字段的值更改为 2 了,
加了版本号之后,如果有重复消息,这时候带着version = 1的条件进来,那么在消费的时候根据 where 后面的查 询条件,就查询不出数据(经过第一条消息执行完后,version字段的值已经是2了),当然也修改不了数据,这样就解决了重复消费的问题。
2、做幂等性处理(增加去重表的方案)
首先,创建一张 A 表,A表里只保存 id,并且这个 id必须是唯一的。有消息进来时,就往A 表里插入相应的数据 Id,然后进行相应的消费逻辑。如果有重复的消息进来,再插入A表数据的时候,数据库会报主键冲突的异常,就说明这个消息是重复消息,不做任何处理或执行相应的重复消息的处理逻辑即可。伪代码如下:
try {
//往A表插入Id
add A;
//todo 执行相应的消费逻辑
......
} catch (DuplicateKeyException e) {
//发生异常 把主键冲突的异常或 唯一键冲突的异常 捕获住,说明是重复消息
// 是重复消息的话就不做任何处理或 执行相应的 重复消息的处理逻辑
}