分布式事物 - 基于RPC调用 - 补偿模式
前提
- 所有服务均有独立的事物管理机制,相互间没有任何关联.
- 所有业务接口都有对应的补偿方法,用于将已经更新的数据还原到上一次的状态.
- 本次实例为同步业务,理想状态下,只有全部成功或全部失败两种情况.
正式开始
正常流程

一切安好.
中途异常 - 补偿成功

虽然发生了失败,但所有补偿都成功了.没有什么问题
中途异常 - 补偿失败

此时,主服务有三种处理方法
- 主服务无限重试补偿方法,直到补偿成功.
这里有很麻烦的问题,如果下游的服务器已经停机,此时主服务的无限重试已经没有意义.在最坏的情况下,如果主服务访问量过大,而因为业务相同,主服务的线程池中的全部线程将全部处于阻塞状态,失去处理新请求的能力.
同时,访问主服务的客户端有可能会放弃本次的连接,导致正在重试中的线程被回收,丢失所有状态 - 主服务尽可能调用补偿方法,并回滚自身事物,同时通知备用方案
这里依靠备用方案对失败的补偿调用进行异步异步调用,已达到"最终一致"的效果.备用方案一般需要集成"可靠消息系统" - 主服务直接放弃补偿与自身的回滚,并通知备用方案
与2基本相同.在调用链比较长的情况下且补偿随机性失败,从上层看,2方案的调用结果(备用方案未执行时)将成锯齿状.而本方案,其对应
的消费者直接以级联方式进行补偿的调用,最终完成全部补偿调用与主方法数据回滚,同样从上层看,方案3的调用结果(备用方案未执行时)将是平整的(只有失败处断裂).
方案1直接pass
方案2,3可以使用消息队列与对应的消费者进行实现.但是会有短暂的数据不一致问题
中途异常(伪) - 触发补偿

这种情况具体描述如下
- 正常远程调用
- 下游业务接收并进行处理
- 主服务认为网络超时(如等待数据库锁释放)或发生其他意外,从而触发补偿流程
- 下游业务完成请求处理
- 主服务发起并执行补偿流程(不包含4涉及的服务)
解决方法
- 记录全局唯一识别码,当主服务发起补偿时,所有下游业务应该得知,并出发各自的补偿方法.
需要注意,在尝试解决过程中,如果主服务过早推送回滚通知,涉及独自提交的服务早于对应业务处理完成进行补偿,将会导致回滚通知失效.
在这种情况下,上游业务回滚,下游业务独自完成了业务处理,造成数据问题. 会有短暂的数据不一致问题
同样的,在这种情况下,调用补偿也有可能发生调用失败的情况.并且会更复杂,因为此时主服务会发出全局的回滚消息,需要处理补偿消息与回滚消息的顺序问题
主服务断电 - 正常运行,补偿中,补偿失败中


此时主服务状态全部丢失且下游业务状态错乱
只能借用可靠消息对进行中的操作进行记录,并在再次开启后进行恢复
总结
- 在必须要使用RPC进行远程调用且事物复杂的情况下,应使用一个可靠的消息系统保证在各方断电,断网,回滚时能够即使恢复"状态".
- 同时,应保证严格的幂等性,对于非幂等消息,根据实际情况,进行保留会消耗.
- 所有经由消息系统的恢复性调用,均为异步操作,此时各方数据会出现不同步的问题.
- 对于复杂性,即使是只有2步,也会产生意外,且补偿方法并不可靠.必须使用"可靠消息"系统进行保证(就是说,不要想要有"方便"这两个字).
- 对于调用消息,进行两步验证,要做xxx与完成xxx,同时保证复苏用的业务数据即可.对于全局回滚消息,进行通用,同时保证复苏消息与回滚消息的幂等
- 主服务自身的业务逻辑也应做成远程调用的模式,即有常规与补偿方法.而主方法本身不包含事物,以此进行统一管理
- 基于上述的内容,已经很靠近TCC模式了,且需要扩展很多框架级代码与补偿代码.
分布式事物 - 基于RPC调用 - 补偿模式的更多相关文章
- 分布式事物 - 基于RPC调用 - TCC模式
前提 前端业务(主服务)可以以同步或异步调用TCC框架,或者TCC框架本身就是同步异步兼备的. 假定TCC框架拥有断电后的自动恢复能力.同时,在下游业务出现无限失败的情况下,也会进行无限的重试,以达到 ...
- Solon rpc 之 SocketD 协议 - RPC调用模式
Solon rpc 之 SocketD 协议系列 Solon rpc 之 SocketD 协议 - 概述 Solon rpc 之 SocketD 协议 - 消息上报模式 Solon rpc 之 Soc ...
- C#中的异步调用及异步设计模式(三)——基于事件的异步模式
四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: · ...
- 《精通并发与Netty》学习笔记(07 - 基于Thrift实现Java与Python的RPC调用)
上节我们介绍了基于Thrift实现java与java的RPC调用,本节我们基于Thrift实现Java与Python的RPC调用 首先,修改data.thirft文件,将命名空间由java改为py n ...
- storm drpc分布式本地和远程调用模式讲解
一.drpc 的介绍 1.rpc RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. 2.drpc drp ...
- 在这个应用中,我使用了 MQ 来处理异步流程、Redis 缓存热点数据、MySQL 持久化数据,还有就是在系统中调用另外一个业务系统的接口,对我的应用来说这些都是属于 RPC 调用,而 MQ、MySQL 持久化的数据也会存在于一个分布式文件系统中,他们之间的调用也是需要用 RPC 来完成数据交互的。
在这个应用中,我使用了 MQ 来处理异步流程.Redis 缓存热点数据.MySQL 持久化数据,还有就是在系统中调用另外一个业务系统的接口,对我的应用来说这些都是属于 RPC 调用,而 MQ.MySQ ...
- Atomikos和GTS-Fescar和TCC-Transaction和TX-LCN分布式事物的比较
什么是分布式事物 分布式系统中保证不同节点之间的数据一致性的事物,叫做分布式事物. 为什么要用分布式事物 微服务,SOA等服务架构模式,一个是service产生多个节点,另一个是resource产生多 ...
- Zookeeper——基本使用以及应用场景(手写实现分布式锁和rpc框架)
文章目录 Zookeeper的基本使用 Zookeeper单机部署 Zookeeper集群搭建 JavaAPI的使用 Zookeeper的应用场景 分布式锁的实现 独享锁 可重入锁 实现RPC框架 基 ...
- 闲话RPC调用
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 自SOA架构理念提出以来,应用程序间如何以最低耦合度通信的问题便呈现在所有架构师面前. 互联网系统的复杂度让我们不 ...
随机推荐
- 【NHOI2018】黑格覆盖
[题目描述] 在一张由 M * N 个小正方形格子组成的矩形纸张上,有 k 个格子被涂成了黑色.给你一张由 m * n 个同样小正方形组成的矩形卡片,请问该卡片最多能一次性覆盖多少个黑格子? [输入数 ...
- CCNA 之 四 管理和配置CISCO设备
管理和配置CISCO设备 路由器组件 cpu 执行操作系统的指令 随机访问存储器RAM - RAM中内容断电丢失 - 运行操作系统: - 运行配置文件: - IP 路由表: - ARP 缓存; - 数 ...
- NER
写在前面:在初学nlp时的第一个任务——NER,尝试了几种方法,cnn+crf.lstm+crf.bert+lstm+crf,毫无疑问,最后结果时Bert下效果最好. 1.关于NER: NER即命名实 ...
- Android DataBinding不能自动生成ViewDataBinding类的解决方法
如果Build.gradle和Layout文件配置正确,仍无法生成ViewDataBinding类. 经测试,Gradle的sync无效,clean project无效,invalidate and ...
- 利用tp5开发智慧软文发布系统中遇到的一些坑
1. PHP 计算两个时间戳之间相差的时间 假设你两个时间戳为$a,$b; 你可以用$c=$a-$b;(反正就是大的减小的),这时$c就是两个时间间隔的秒数了. 想求两个时间间隔的天数就用:$c/(6 ...
- Spring 核心技术与产品理念剖析(上)
IT 技术发展太快了,就像浪潮一样一波接着一波,朝你迎面扑来,稍不留神就会被巨浪卷至海底而不得翻身.我们必须要学会抓住那些不变的本质或规律,只有这样才能屹立潮头而不倒,乘风破浪,做这个巨变时代的弄潮儿 ...
- Jest测试框架入门
近年来,随着前端工程化的发展,前端发生了翻天覆地的变化.jQuery已经慢慢淡出了我们的视野,React.Vue和anglur三驾马车急速驶来.从此,前端进入了数据驱动的时代,也有了清晰的模块化开发的 ...
- shell脚本exercise2
通过文件里面的网址,判断是否访问成功网址 #!/bin/bash check(){ code=`curl -I -m -o /dev/null -s -w %{http_code} http://$u ...
- ThinkPHP5——route(路由)的详解
路由在框架中的作用打个比方的话,路由好比是WEB应用的总调度室,对于访问的URL地址,路由可以拒绝或者接受某个URL请求,并进行分发调度,而且还有一个副作用是因为路由规则可以随意定义,因此可以让你的U ...
- css练习——两列左窄右kuan型
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...