生产端的可靠性传递
保障消息的成功发出
保障MQ节点成功接收
发送端收到MQ节点(Broker)确认应答
完善的消息进行补偿机制(返回应答时突然断电,不知是否投递成功)
互联网大厂的解决方案
方案一
消息落库,对消息状态进行打标(发出一个标志,接收一个标志)
生产者产生消息,先持久化业务DB和消息DB,然后发送MQ,MQ返回应答,修改消息DB的发送成功标志
定时任务轮询发送没有收到应答的数据,因为无法确认是已经发送到MQ了还是为发送到MQ,有可能发送两遍,所以消费者处理的时候需要符合等幂性
在高并发场景下不适合
方案二
消息的延迟投递,做二次确认,回调检查
Upstream:生产端
Downstream:消费端
- 先入业务库,再发消息,
- 5分钟后,再发本条消息的校验消息
- 接1,将消息发送到下游Downstream
- Downstream发送确认消息给Broker
- Callback接收确认消息后,修改消息DB
- 接2,Callback接收校验消息,检查DB的该条消息是否存在,存在不做操作,不存在,通知Upstream
目的:
减少数据库操作
保障性能 (通过非持久化)
把服务分解通过异步补偿(不需要等待应答)
消费端-等幂性保障
在海量订单产出的业务高峰期,如果避免消息的重复消费问题?
消费端实现幂等性,就意味着,我们的消息永远不会消费多次,即使我们收到多条一样的消息
主流的幂等性操作
唯一ID+指纹码 ,利用数据库主键去重
好处:实现简单
坏处:高并发下有DB写入的性能瓶颈
解决方案:跟进ID进行分库分表进行算法路由
利用Redis的原子性去实现
1、我们是否进行数据落库,如果落库的话,关键解决的问题是数据库和缓存如何一直
2、如果不落库,存储到缓存中,如何设置定时同步的策略