05,分布式事务(可靠消息一致性)
2021-04-27 16:41:29 0 举报
可靠消息一致性方案的细节落地
作者其他创作
大纲/内容
扫描处于“待确认”状态的消息
下游服务
9,再给可靠消息服务发送个请求,通知可靠消息服务更新消息的状态为已完成
7,执行本地业务方面的数据库操作
9个步骤失败处理(1)上游服务发送一个待确认消息给可靠消息服务如果这个环节失败了,也就是上游服务就没法发送一个待确认消息给可靠消息服务,那么无所谓啊,从头儿开始就失败了,数据没有任何不一致吧(2)可靠消息服务将这个待确认的消息保存到自己本地数据库里可靠消息服务插入自己本地数据库的时候报错了,也没事啊,因为肯定会返回给上游服务一个失败的消息的,此时上游服务就不会继续往下执行了(3)上游服务操作本地数据库本地操作也会回滚,然后也不会继续发送确认消息给可靠消息服务了,本地事务回滚了之后,正常来说就会发送消息通知可靠消息服务,删除那条消息(4)上游服务通知可靠消息服务,可以确认发送消息了通知确认/删除消息的时候,服务调用失败,异常,因为此时会导致可靠消息服务的数据库里,留着一条状态为“待确认”的消息font color=\"#ff6666\
5.1,更新消息状态为“已发送”/“已删除”
5.2,将消息投递到mq
扫描“已发送”的消息,超过了10分,但未完成的状态重试投递mq消息
1,发送待确认请求
解决方案:1,如果1和2两个步骤失败了,上游服务自己应该去做的一个重试的机制3,3这个步骤,失败了,会调用可靠消息服务的接口通知一下,让人家删除消息4和5两个步骤失败了,消息在可靠消息服务的数据库里的状态是“待确认”(1)可靠消息服务得开一个后台线程,专门扫描那些数据库里处于“待确认”状态的消息,同时该消息的创建时间到现在已经超过了比如10分钟了(2)发现那种一直处于“待确认”状态的消息,还超过了一定的时间,就认为是超时了(3)对超时的消息,需要回调上游服务特意提供的查询这个操作状态的一个接口,然后上游服务自己判断一下这个操作是否执行,举个例子,比如说上游服务本来应该是将订单状态修改为“交易成功”的,此时回调过去以后,上游服务就得自己去判断下那个操作执行了没有,查下那个订单的状态(4)如果操作是还没执行,那么证明是3那个步骤失败了,就是上游服务的本地数据库操作失败了,所以导致消息一直处于“待确认”的状态,此时可靠消息服务需要将这条消息给删除即可(5)如果操作是已经执行了,那么说明是4或者5失败了,要不是上游服务没通知到可靠消息服务,要不是可靠消息服务自己没成功投递出去消息,此时可靠消息服务就是再次尝试用一个事务来更新本地消息状态为“已发送”,同时尝试再次发送消息给MQ4和5失败结果是一样的,都是导致一条消息状态一直是“待确认”如果说可靠消息服务再次尝试删除消息,或者投递消息,还是失败了呢?因为消息的状态只要一直停留在“待确认”的状态,后台线程会不停的扫描到这条消息,然后再次发送请求去回调,然后再次尝试重新处理,假如一直重试失败,发送短信通知开发人员查看bug6789出了问题此时消息的状态都是“已发送”如果是8和9出问题,那么下游数据库的操作已经执行成功了(1)可以开一个后台线程,专门监控“已发送”的消息,如果超过了10分钟,那么就需要判定为超时了(2)这个时候也是需要可靠消息服务再次重新投递消息给到MQ,让下游服务再次去消费(3)下游服务的接口一定要保证幂等性,数据库操作只能成功的执行一次如果是6和7出问题下游服务的本地数据库操作还没执行,此时重新投递了一条消息,那么正常情况下,就会执行数据库操作,反过来通知可靠消息服务变更消息状态为“已完成”如果是9出了问题呢,就是没有通知可靠消息服务更新消息的状态为“已完成”,那么通过重新投递,数据库操作不会再次执行了,但是反而会再次通知一次可靠消息服务,这个消息的状态是“已完成”MQ异步调用,时效性,问题排查都极为麻烦,所以这个方案,可靠消息最终一致性方案一般会跟TCC方案结合在一起,来实现复杂场景下的分布式事务对于服务调用链的分布式事务,可以用tcc事务来保证,但是对于一些耗时可以做成异步化的服务的调用,同时也要包裹在事务里的话呢,可以使用可靠消息最终一致性的方案来做,基于MQ来做异步化,但是因为中间加了一个可靠消息服务,可以保证上游服务执行成功了以后,一定会保证下游服务也会执行成功,实现最终一致性
4,发送确认/删除请求
上游服务
2,保存消息为“待确认”
第5步两个步骤,必须包裹在一个事务里
后台线程
数据库
下游服务要保证幂等性
本地数据库
关闭自动ack
8,对消息进行手动确认ack
可靠消息服务
3,操作本地数据库
MQ
如果本地数据库操作失败,发送删除消息如果本地数据操作成功了,发送确认消息
6,消费消息
第2种方案,rabbitmq,都有事务消息的一个实现,你可以先去投递一个prepare的消息,接着如果说数据库操作成功过了,那么就commit那个消息发送给rabbitmq,然后如果数据库操作失败了,就通知mq去rollback一条消息,但是此方案吞吐量太低,不建议使用
0 条评论
下一页