消息防重和幂等
当同一消息被重复投递或消费时,能保证消息消费的幂等性。那什么是防重与幂等呢?
防重:保证相同的消息只最多只执行一次 。
幂等:保证相同的消息,每次执行时结果相同。
为什么需要做消息的防重或幂等
- 主流的消息中间件都只保证消息最少被投递一次,不保证只投递一次。
- 消息发送时重复发送。当消息已被服务器持久化,但因网络闪断、服务器宕机等原因导致消息生产者认为消息发送失败,尝试再次发送消息。
- 中间件投递消息时重复投递消息中间件在对集群做缩、扩容时触发Rebalance,消费者可能收到重复消息 网络闪断、客户端重启时消息中间件在网络恢复后,会对消息尝试重新投递。
常见解决方案
- 通过数据库唯一索引防重: 可使用消息的id或业务id做为数据库中表的主键或唯一索引,通过数据库进行防重。
- 通过redis防重: 使用消息的id或业务id作为redis的防重key,通过redis防重。
- 通过业务状态控制做到消费幂等。 通过在sql语句中加入状态过滤条件,只执行指定状态的sql语句,达到幂等性。
- 使用redis防重时,由于redis与数据库之间可能 存在状态不一致,无法做到绝对的防重。如对防重 要求高,可使用数据库进行防重。