背景
微服务场景下需要同步信息的场景。
还是前文的栗子: 如下微服务
此时产品上有个需求,在支付管理端根据是否出账搜索支付流水,而出账是账单服务的功能。所以这里涉及到信息的同步,那么,我们怎么保证同步一定能成功呢(最终一致性)。
保证在队列中的消息,一定会被消费。用白话来讲,就是不停消费直到成功。
方式比较简单:消息队列都使用手动提交。处理完了,再保证提交。尽量遵循触发-查询机制,提供可重入性,即消息队列只传递id这种非实质信息,收到之后再通过rpc查询拉取完整数据来更新。
主要是发送消息到队列这步的可靠性考量
以递增的时间间隔重试5次。如果失败了,上报到日志和告警,人工介入。同时,具体业务准备好重试的脚本。根据实时的情况进行处理。优点:
缺点:
失败之后,内存维护一个重试队列,先由5,10,20, 40, 80, 160, 320s的间隔重试。之后以5分钟一次的间隔请求。同时,也要打入日志系统,告警通知。
优点:可靠性会比一高很多,在消息队列故障30分钟这种场景下,也能自动恢复。可以做成package的方式,方便接入。
缺点:
限制:
失败之后,内存维护一个重试队列,先由5,10,20, 40, 80,160, 320s的间隔重试。然后append到本地文件,同时以5分钟一次的频率做重试。重试完成之后,从磁盘中删除对应信息。当服务重启,从磁盘把数据导入内存即可。
优点:
缺点:
限制:
实现任务重试微服务,该服务通过维护一张任务表,重试任务直到成功。相当于是消息队列这个可靠中间件有问题,就丢给这个重试服务这个自己实现的“中间件”。
优点:
缺点:
限制:
以上方案中,三,四基本能解决重试阶段写入消息队列的可靠性问题。但针对另一个场景:正想写本身服务就没了的情况(比如oom导致服务被系统kill了) 还是不行。
要做变更之前,先写入到消息同步微服务,告诉他要做什么事(把什么消息放入消息队列),和流程最长执行时间,以及发给谁。该服务维护一张任务表,任务初始处于未激活状态。
等业务做完要同步的时候,再rpc请求触发激活。
任务管理微服务如果发现一个任务,超过最长执行时间没有激活。就说明激活rpc失败了,或者是服务崩溃,本身就没做变更。此时,自动激活即可。
优点:完全可靠(事务可能还是会失败,可靠指数据一定最终一致)。
缺点:
限制:
推荐:方案三
推荐理由:成本不高,可靠性较强。可靠度99.99%。(此处不论代码本身bug)