在《消息可靠性保证》篇章中,我通过生产者确认机制保障了消息会发送到MQ中,但是在生产者与MQ建立过程的时候出现了网络抖动,连接建立失败,生产者就感知不到MQ返回的ack/nack,无法完全保障消息投递到MQ中,因此这里介绍如何保障生产者百分百将消息投递到MQ。
status
来记录消息的投递状态。将status
设为0,表示还未被投递status
设为1,表示投递成功status=0
的消息进行重新投递 retry sendstatus
标记为2,交给人工解决(或者把这些记录到一张失败表中)通过以上步骤就能保障消息的百分百投递成功!!!
step2 网络抖动没有投递成功,并不会照成重复消费问题,因为消息并没有投递到MQ中。而step3 此时MQ已经接收到该消息,返回ack时出现网络抖动,导致生产者接收不到MQ返回的ack,就误以为没有投递成功,将消息又重新投递一遍。造成消费者重复消费!!!
解决消息重复消费问题,需要在消费端考虑消息的幂等性。
幂等性:对一个接口调用一次和调用多次得到的结果是一样的
解决方案有两套
setnx
使用雪花算法、Tinyid 等生成唯一ID给消息标识和指纹码,消息入库时作为主键进行保存,因此保证消息唯一性
优点:实现简单
缺点:
1、高并发业务下游数据库有写入性能瓶颈
2、需要本地ID生成服务,确保外部统一生成ID服务无法使用时可以进行兜底
**解决方案:**数据库进行分库分表,对消息ID使用算法解析路由到不同的数据库中
利用redis的setnx
命令,天然具有幂等性,从而实现不重复消费
**优点:**性能高,AOF模式数据不丢失
缺点:
1. 数据同步入库需要考虑到数据库和Redis之间的原子性
2. 消息不同步入库,Redis定时同步到数据库的策略需要具体设计
**
**