什么是消息幂等性
消息被消费者消费一次和多次的结果是相同的,并且消费多次不会对系统产生其他副作用。
消息重复的原因
- 发送时重复
生产者将消息成功发送到Broker,由于网络或生产者宕机导致broker发送ACK失败。生产者未收到响应认为消息发送失败并进行重试,导致broker出现两条完全相同的消息
- 消费时重复
消费者正确消费完消息后,由于网络等异常未能将消费成功的状态信息传递到Broker。Broker为了保证消息至少被消费一次,会重新投递此消息。
总结:由于网络异常、消费者异常等原因导致ACK丢失,消息被重新发送或投递。
如何实现消息幂等性
由消费端在消费消息时实现去重。
- 根据业务唯一主键是否存在判断是否消费过
业务唯一主键应由消息发送方生成,通过消息key属性传递给消息消费者
- 通过缓存Redis存储消费过的业务主键
判断业务主键的key是否存在,已存在代表消费过,不存在代表没消费过并在业务处理完后将此业务主键加入缓存
- 通过数据库表存储消费过的业务主键
-
通过业务表或消息表的状态判断是否消费过
-
业务主键添加唯一索引
-
引入乐观锁或分布式锁
-
消息记录表
消息记录表可记录消息的Topic、Tag、消息实体类Json串、消息状态、业务唯一主键等,可根据此消息表进行相关补偿。
在高并发的场景下,一定要通过持久化存储的唯一索引以及引入锁机制作为共同保障数据准确性和完整性的最后一道防线!