分布式事务一致性解决方案

一、从数据一致性谈起

  一致性问题,“万恶之源”是数据冗余和分布并通过网络交互+网络异常是常态。


1、数据一致性的情形

    • 主库、从库和缓存数据一致性,相同数据冗余,关系数据库,为保证关据库的高可用和高性能,一般会采用主从(备)架构并引入缓存。其中数据不一致性存在于数据冗余的时间窗口内。常用的解决方案见数据库之架构

    • 多副本数据之间的数据一致性,相同数据副本,大数据领域,一份数据会有多个副本并存储到不同的节点上。客户端可以访问任何一个节点进行读写操作。常用的解决方案是基于Paxos、ZAB、Raft、Quorum、Gossip等的开源实现。这里只是一提,暂不探讨。感兴趣可以自行谷歌或百度。

    • 分布式服务之间的数据一致性,相关数据分布,分布式服务,不同的服务操作不同的库(表),而且库(表)间要保持一致。常用的解决方案是分布式事务一致性解决方案。这也是本文要探讨的内容。


2、数据一致性的概念

    • 强一致性

    • 弱一致性

    • 最终一致性


3、数据一致性的原理

    • ACID

    • CAP

    • BASE


4、数据一致性的协议

    • 两阶段提交协议

    • 三阶段提交协议

    • TCC协议

    • Paxos协议

    • ZAB协议

    • Raft协议

    • Quorum协议

    • Gossip协议


二、分布式服务间的数据一致性

  640?wx_fmt=png

  所谓分布式服务,就是把之前通过本地接口交互的模块,拆分成单独的应用独立部署,并通过远程接口和网络消息交互。且不管这样说严不严密,正不正确,理解就好。本文的重点也不是这个话题。简单画一张图辅助理解,如图。集中式架构,要想保证订单表和库存表的一致性,只要一个本地事务(ACID)就能保证两者的强一致性。分布式架构,订单表由订单服务操作,库存表由库存服务操作。要想保证订单表和库存表的一致性,那么就必须保证订单服务对订单表的操作和库存服务对库存表的操作同事成功。之前的一个本地事务就变成了一个分布式事务。由于服务之间通过网络交互+网络异常是常态,就会产生服务间数据不一致的情况。这就涉及一个分布式事务一致性的问题。



三、分布式事务一致性解决方案


1、接口同步调用模式与一致性解决方案

640?wx_fmt=png

模式分析:A服务同步调用B服务的接口并等待结果返回,后续的流程会依赖B服务的返回结果。这种交互模式下,A服务得到的结果细分有三种情况。

  1. 请求发起阶段网络超时或异常,此时,B服务未收到请求,未作出相应的处理;

  2. 结果返回阶段网络超时或异常,此时,B服务已收到请求,并作出相应的处理;

  3. 正常结果返回(明确的成功或失败)。

业务场景:适用于大规模、高并发的短小操作且依赖返回值的场景。例如,交易服务和库存服务(卡券服务、红包服务等)的交互、用户登录和准入服务的交互等。

解决方案:方案一,服务调用方查询重试方案;方案二,TCC方案。

  1. 服务调用方查询重试方案,适合一个从业务服务场景。

640?wx_fmt=png

  1. :1) 查询重试后依然失败(极少),报警,人工处理或者准实时对账系统自动校准;

      2) 重试次数不宜多,甚至只重试一次;

      3) B服务处理请求要做幂等。

  2. TCC方案,适合多个从业务服务场景。TCC是阿里在二阶段提交协议的基础上提出的一种解决分布式事务一致性的协议,原理图如下。其对应的产品是DTX(老版是DTS)。DTS中有个快速开始的例子看明白了,TCC就基本OK了。在蚂蚁金服内部被广泛地应用于交易、转账、红包等核心资金链路,服务于亿级用户的资金操作。
    640?wx_fmt=jpeg

    :关于TCC,个人认为,理解原理很重要。工作中遇到吻合的场景可以根据原理自行实现,满足业务即可。


2、接口异步调用模式与一致性解决方案

640?wx_fmt=png

模式分析:A服务调用B服务,B服务先受理请求并落库,状态是待处理。B服务处理请求很耗时,或者要依赖其他的服务。B服务处理完后通知A服务或者A服务定时去查询B服务的处理结果。这种交互模式下,对于CASE-1,第1步和第2步同接口同步调用模式,第3步同消息异步处理模式;对于CASE-2,相当于两次接口同步调用模式

业务场景:适用于非核心链路上负载较高的处理环节,这个环节经常耗时较长,并且对时效性要求不高。例如,用户提现时,账户系统和提现系统的交互(CASE-1);提现系统和三方系统(银行系统或者三方托管系统)的交互(CASE-2)。

解决方案服务被调方最大努力处理方案。由于B服务中请求有落库,所以可以用定时任务不断重试尽最大努力将请求处理出结果。处理后,将请求状态设置成对应的结果落库。然后再通知A服务或者A服务异步主动查询。

640?wx_fmt=png

:1) B服务通常都是接受请求并持久化后才返回A服务受理成功。避免服务进程被杀掉而导致请求丢失。

  2) 不管是第(1,2)两步还是CASE-2中的第(3,4)两步,如果查询重试失败,可以落库,用定时任务处理,知道成功。反正不像接口同步调用模式,A服务不需要实时的结果。


3、消息异步处理模式与一致性解决方案

640?wx_fmt=png

模式分析:A服务将B服务需要的信息通过消息中间件传递给B服务,A服务无需知道B服务的处理结果。这种交互模式下,消息生产者要确保消息发送成功;消息消费者要确保消息消费成功。

业务场景:消息异步处理模式与接口异步调用模式类似,多应用于非核心链路上负载较高的处理环节中,井且服务的上游不关心下游的处理结果,下游也不需要向上游返回处理结果。例如,在电商系统中,用户下订单支付且交易成功后,发送消息给物流系统或者账务系统进行后续的处理。

解决方案生产者最大努力通知+消费者最大努力处理方案。

  1. 非事务消息,生产者先执行本地事务并将消息落库,状态标记为待发送,然后发送消息。如果发送成功,则将消息改为发送成功。定时任务定时从数据库捞取在一定时间内待发送的消息并将消息发送。通过定时任务来保证消息的发送。为确保消息一定能消费,消费者一般采用手动ACK机制,那么消息服务器必然会重发未ACK的消息,这就要求消息消费者做好幂等。
    640?wx_fmt=png

640?wx_fmt=png

  1. 事务消息,以RocketMQ为例,下图是RocketMQ事务消息的流程。官网有示例代码。和不支持事务的消息中间相比,只是消息发送的时候,保证了和本地事务的一致。消费者实现还是不变。
    640?wx_fmt=png

:1) 定时任务重试发送消息和消息服务器重发未ACK的消息一般都是时间阶梯式的(2n*时间间隔);

  2) 支持事务消息中间件之RocketMQ:https://rocketmq.apache.org/docs/quick-start。


四、保证操作幂等性的常用方法

  1. 有业务状态,业务逻辑来保证幂等。比如接到支付成功的消息订单状态变成支付完成,如果当前状态是支付完成,则再收到一个支付成功的消息则说明消息重复了,直接作为消息成功处理。

  2. 无业务状态,业务唯一ID保证幂等。增加一个去重表(或分布式缓存)来记录有业务唯一ID的操作。比如调用充值接口,当请求过来时,会根据唯一充值ID去查充值流水表,若已经存在,则直接返回;否则继续进行充值操作。

:保证幂等性的方法很多,根据具体的业务场景,总能很容易找到保证幂等性的方法。


五、总结

  1. 接口同步调用模式,服务调用方查询重试方案和TCC方案。

  2. 接口异步调用模式,服务被调方最大努力处理方案。

  3. 消息异步处理模式,生产者最大努力通知+消费者最大努力处理方案。

  4. 任何服务操作都需要提供一个查询接口,用来向外部输出操作执行的状态。

  5. 永远不要在本地事务中调用远程服务,在这种场景下如果远程服务出现了问题,则会拖长事务,导致应用服务器占用太多的数据库连接,让服务器负载迅速攀升,在严重情况下会压垮数据库。

  6. 最后一道防线 - 对账系统。

  7. 同步和异步的抉择:

  • 可以异步的地方,就应该异步实现。如果业务逻辑允许,则我们可以将一些耗时较长的、用户对响应没有特别要求的操作异步化,以此来减少核心链路的层级,释放系统的压力。

  • 能用同步解决的问题,不要引入异步。如果性能不是问题,或者所处理的操作是短小的轻量级处理逻辑,那么同步调用方式是最理想不过的,因为这样不需要引入异步化的复杂处理流程。

最后,来思考下,垂直分库情况的数据一致性问题,相信你已经有答案了。

注:如果,以上场景和解决方案,没能包含您工作中遇到的场景,欢迎交流,并共同讨论解决方案。

原文地址: https://www.cnblogs.com/littlecharacter/p/9341804.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hihocoder1147 时空阵(bfs树+DP)

bfs树中,边只存在于同一层或相邻层的点之间 设f[i][j][k]f[i][j][k]f[i][j][k]为前iii层一共使用jjj个节点,其中第iii层有kkk个节点的合法方案,转移枚举每一层的连边方式,做到第LLL层即可。对于LLL 层之后的边可以随便乱连。&…

牛客网【每日一题】4月21日题目精讲 糖糖别胡说,我真的不是签到题目

试题 糖糖别胡说,我真的不是签到题目 时间限制:C/C 2秒,其他语言4秒 空间限制:C/C 131072K, 其他语言262144K 64bit IO Format:%lld 题目描述 从前,有n只萌萌的糖糖,他们分成了两组一起玩游戏。…

近似乘积(jzoj 3925)

近似乘积 jzoj 3925 题目大意 给你一个集合A和n让你求不在集合A内的x、y、z,使∣n−xyz∣|n-xyz|∣n−xyz∣最小 输入样例 3 2 2 4 4 1 1 7 2 1 15 90输出样例 1 1 3 2 2 2 2 5 9数据范围 40% 的数据:1⩽m⩽10,1⩽n⩽100.1 \leqslant …

[2020.11.27NOIP模拟赛]中位数之中位数【二分,树状数组】

正题 题目链接:https://www.luogu.com.cn/problem/U142585?contestId37855 题目大意 nnn个数,求所有区间中位数的中位数。 解题思路 二分一个答案,然后如果一个区间的中位数≥mid\geq mid≥mid,那么这个区间一定是≥mid\geq mid≥mid的数比…

.net core 生成二维码

其实生成二维码的组件有很多种,如:QrcodeNet,ZKWeb.Fork.QRCoder,QRCoder等我选QRCoder,是因为小而易用、支持大并发生成请求、不依赖任何库和网络服务。既然是.net core 那当然要用依赖注入,通过构造函数注…

小雨坐地铁

链接: 时间限制:C/C 1秒,其他语言2秒 空间限制:C/C 524288K,其他语言1048576K 64bit IO Format:%lld 题目描述 小雨所在的城市一共有 m 条地铁线,分别标号为 1 号线,2 号线,……&…

计蒜客 91 地铁 HDU 5263 平衡大师(二分+网络流)

先说PPT的思路 PPT的思路源于这句话: 对每条边 (u, v),连一条 (u, v) 容量为 1,费用为 1 的边。如果 流了表示删去这条边。 流过原图上的边表示删去这条边意味着什么呢? 令dif[u]u的出度-入度 如图,灰边表示原图上的…

开关灯(jzoj 3926)

开关灯 jzoj 3926 题目大意 有一个nl的灯网,你可以把按某一列的灯的按钮,然后这一列开的关,关的开,你也可以把某一行的灯和别的行的灯调换,问从当前状态到目标状态最少按多少个按钮 输入样例 3 3 2 01 11 10 11 0…

P4254-[JSOI2008]Blue Mary开公司【李超树】

正题 题目链接:https://www.luogu.com.cn/problem/P4254 题目大意 要求支持操作 插入一条直线。询问一个纵坐标最高的在直线上的点。 解题思路 李超树的模板题,大概就是标记永久化,对于一个位置midmidmid,我们看一下它与标记点在midmidmi…

asp.net core 外部认证多站点模式实现

PS:之前因为需要扩展了微信和QQ的认证,使得网站是可以使用QQ和微信直接登录。github 传送门 。然后有小伙伴问,能否让这个配置信息(appid, appsecret)按需改变,而不是在 ConfigureServices 里面…

牛客网【每日一题】4月22日 K-th Number

链接: 时间限制:C/C 1秒,其他语言2秒 空间限制:C/C 65536K,其他语言131072K 64bit IO Format:%lld 题目描述 Alice are given an array A[1…N] with N numbers. Now Alice want to build an array B by a parameter K…

纪中B组模拟赛总结(2020.2.09)

成绩 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3666lyflyflyf120120120303030000909090 总结 T1敲了个并查集,然后被卡了,正解是dfs,十分难懂,好在洛谷有原题(有一点差别),看…

P6030-[SDOI2012]走迷宫【高斯消元,tarjan,期望dp】

正题 题面链接:https://www.luogu.com.cn/problem/P6030 题目大意 nnn个点的一张有向图,求起点到终点的期望步数。保证每个强连通分量大小不超过100100100。 解题思路 显然如果是强连通分量那么显然需要用高斯消元。 先把强连通用tarjantarjantarjan缩起来&#…

如何让敏捷软着陆?

背景当前,敏捷已经成为了2018的热词,执行敏捷研发模式的项目多数都是从瀑布模型转型过来的,瀑布模型是一套根深蒂固的传统流程,如果硬着陆的话,很容易折翼。笔者在各类项目敏捷实施过程中,总结了一些接地气…

牛客网【每日一题】4月24日 子序列

链接: 时间限制:C/C 1秒,其他语言2秒 空间限制:C/C 262144K,其他语言524288K 64bit IO Format:%lld 题目描述 小美有一个由n个元素组成的序列{a1,a2,a3,…,an},她想知道其中有多少个子序列{ap1,ap2,…,apm}…

[AGC031E] Snuke the Phantom Thief(网络流)

考虑枚举偷的珠宝的个数k,且假设它们按照坐标大小排好了序(x坐标排一次,y坐标排一次)。 那么可以将条件转化一下, 在珠宝按x坐标排好序时, x坐标大于等于aia_iai​的最多取bib_ibi​个可以转化为取的前k−…

YL杯超级篮球赛(jzoj 1325)

YL杯超级篮球赛 jzoj1325 题目大意 给n个点,每一个点都有一个值(aia_iai​),现在让你找出一个点,使∑i1n(∣X−xi∣∣Y−yi∣)ai\sum_{i1}^{n} (|X-x_i||Y-y_i|)a_i∑i1n​(∣X−xi​∣∣Y−yi​∣)ai​最小,输出此…

P6088-[JSOI2015]字符串树【可持久化Trie,LCA】

正题 题面链接:https://www.luogu.com.cn/problem/P6088 题目大意 nnn个点的一棵树,每条边上有一个字符串,求一条路径上有多少以询问字符串为前缀的字符串。 解题思路 建立一个可持久化TrieTrieTrie,然后每个点继承父亲插入字符串。 然后询…

牛妹的游戏

链接: 时间限制:C/C 1秒,其他语言2秒 空间限制:C/C 262144K,其他语言524288K 64bit IO Format: %lld题目描述 UPD:数据保证不会有两条控制链控制的据点完全相同,也保证不会有某条控制链两端控制的据点相同…

.NET Core使用NLog通过Kafka实现日志收集

一、前言NET Core越来越受欢迎,因为它具有在多个平台上运行的原始.NET Framework的强大功能。Kafka正迅速成为软件行业的标准消息传递技术。这篇文章简单介绍了如何使用.NET(Core)和Kafka实现NLog的Target。在日常项目开发过程中,Java体系下Spring Boot …