纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

分布式理论与解决方案 图文精讲java常见分布式事务理论与解决方案

假装懂编程   2021-11-27 我要评论
想了解图文精讲java常见分布式事务理论与解决方案的相关内容吗假装懂编程在本文为您仔细讲解分布式理论与解决方案的相关知识和一些Code实例欢迎阅读和指正我们先划重点:图文精讲java分布式事务理论,java分布式事务解决方案下面大家一起来学习吧。

如何解决某个节点故障的问题?如何解决数据一致性的问题?如何解决数据倾斜的问题?

CAP理论

先从定义开始:

C(Consistence):一致性

所有的节点访问的是最新的数据副本这是什么意思呢?我们知道在分布式系统中为了高可用往往一个节点会有若干个数据副本简称Follower节点比较常见的模式是我们的数据更新一般会写入Leader节点然后会同步给Follower节点当我们读取数据的时候不论从哪个节点读取都可以读到最新的数据这就是一致性。

A、B、C可以得到同样的数据。

A(Availability):可用性

非故障节点可以正常的操作简单来说就是客户端一直可以正常访问并得到系统的正常响应从用户角度来看就是不会出现系统操作失败或者访问超时等问题但是系统内部可能会出现网络延迟等问题。

C节点因为自身问题不可用正常情况会被剔除B节点与A节点之间可能存在同步延迟但是B节点本身没有故障所以B节点是可用的。

P(Partition tolerance):分区容错性

网络的问题错综复杂分布式系统肯定是要考虑这一点的如果出现某个节点因为网络等问题造成数据不一致或者数据延迟很久才同步过来虽然会影响部分节点数据的时效性但是服务节点依然是可用的分布式系统要能容忍这种情况的。

B对应的节点虽然和Leader断了联系但是依然可以对外服务只不过提供的是老数据。

在分布式系统中CAP是无法同时满足的首先由于存在多节点并且网络传输需要时间所以可能会存在延迟那么节点之间的数据我们无法保证某一时刻完全一致因此P(分区容错性)是要满足的。在P满足的情况下为什么说CA不能同时满足呢?我们来通过假设看一看如果CA同时满足会怎么样。

  • 假设现在要求满足C(一致性)那么就是说所有的节点在某一刻提供的数据都必须一致我们知道在P的情况是不可能保证的要保证的话就只能把其他节点全部干掉比如禁止读写那这其实就是和A是相悖的(某些节点虽然延迟但是节点本身可用)。
  • 假设现在要求满足A(可用性)那么就是说只要节点本身没什么问题就可以对外提供服务哪怕有点数据延迟很明显这肯定是和C相悖的。

在实际的业务中我们需要根据业务的场景来决定使用CP还是AP。比如对一些和钱挂钩的业务数据的一致性按道理应该是最重要的因此一般会采用CP而对于一些不影响主体功能的业务比如像新闻的阅读量不同的用户看到的阅读量不一样并不会造成什么影响可以采用AP。

BASE理论

由于CAP理论中C和A无法兼得eBay的架构师提出了BASE理论BASE理论主要是在CA之间做文章它不要求强一致性因此可以满足一定的可用性。我们还是先从定义开始:

BA(Basically Available):基本可用

注意这个和不可用不是一回事在分布式系统中出现不可预估的故障时允许损失部分可用性保证核心功能可用比如正常一个接口响应200ms在出现故障时响应超过1s虽然响应时间变长了但是接口还是可以对外提供服务的再比如对于一个视频网站在突发流量到来时把视频的弹幕服务打挂了但是视频的播放功能依然正常。

S(Soft-state):软状态

即分布式系统允许存在一个中间的状态但是这个中间状态并不会对服务造成严重的影响比如对于主从复制这种允许从节点短暂的延迟。

E(Eventually Consistent):最终一致性

由于软状态的存在系统对延迟是可以容忍的但是在一段时间后延迟的数据需要最终保持一致。

总的来说BASE理论适用性应该更广泛很多时候我们并不要求数据的强一致性只要在短暂的延时之后能达到一致性也是可以的。

一致性hash

hash这个词对我们来说并不陌生以缓存服务器来说一般会在线上配置好几台服务器然后根据hash来决定请求哪台缓存服务比如常见的就是取模方式 hash(key)%num 来获取目标机器。

假设现在有3台缓存服务器并且当前有3个缓存的key分别是k0k1k2在经过hash以后它们的分布情况如下:

hash(k0)%3=0 #No.0
hash(k1)%3=1 #No.1
hash(k2)%3=2 #No.2

很幸运分布的非常均匀每台机器一个。某天由于线上要做个活动预计访问量会加大需要选择加一台服务器来分担压力于是经过hash之后k0k1k2的分布情况如下:

hash(k0)%4=0 #No.1
hash(k1)%4=1 #No.2
hash(k2)%4=2 #No.3

  • k0的目标缓存服务器由原本的No.0变成了No.1
  • k1的目标缓存服务器由原本的No.1变成了No.2
  • k2的目标缓存服务器由原本的No.2变成了No.3

可以发现因为添加了一台缓存节点导致了k0k1k2原来的缓存全部失效了这似乎有点问题类似缓存雪崩严重的话会对DB造成很大的压力造成这个问题的主要原因是因为我们加了一个节点导致hash结果发生了变动此时的hash可以说是不稳定的。

为了解决rehash不稳定的问题于是出现了一致性hash算法。一致性hash的原理比较简单首先存在一个hash圆环这个圆环可以存放 0-2^32-1 个节点。

  • 第一步就是把我们的目标服务器节点通过hash映射到这个环上
  • 第二步根据我们需要查找的key它应该也对应hash环上的某个位置

也许你会问这k0、k1、k2也没和某个缓存节点对上呀~这就是一致性hash不同的地方它此时查找的方式并不是 hash(key)=某个节点而是根据key的位置顺时针找到第一个节点这个节点就是当下这个key的目标节点。

我们再来看看在一致性hash的情况下新增一个节点会发生什么。

此时唯一的变动就是k0原本应该打到cache0节点的现在却打到了我们新加的节点cache3上而k1k2是不变的也就是说有且只有k0的缓存失效了相比之前大大降低了缓存失效的面积。

当然这样的节点分布算是比较理想的了如果我们的节点是这样分布的:

几个cache节点分布的比较集中由于顺时针查找法所以最终k0k1k2都落在cache0节点上也就是说cache1、cache2基本就是多余的所以为了解决这种数据倾斜的问题一致性hash又引入了虚拟节点的概念每个节点可以有若干个虚拟节点比如:

  • cache0->cache0#1
  • cache1->cache1#1
  • cache2->cache2#1

虚拟节点并不是真正的服务节点它只是一个影子它的目的就是站坑位让节点更加分散更加均匀。

这样通过映射出虚拟节点以后k0打到cache2k1打到cache0k2打到cache1虚拟节点越多理论分布的越均匀。

Gossip协议

集群往往是由多个节点共同组成的当一个节点加入集群或者一个节点从集群中下线的时候都需要让集群中其他的节点知道这样才能将数据信息分享给新节点而忽略下线节点。

A、B、C节点之间可以互相传递消息但是D节点在下线之后会被广播告诉其他存活节点。

这样的广播协议就是今天要说Gossip协议Gossip协议也叫Epidemic协议(流行病协议)当一个消息到来时通过Gossip协议就可以像病毒一样感染全部集群节点当然我们利用的是它这个极强的散播能力。

Gossip的过程是由一个种子节点发起的当一个种子节点有信息需要同步到网络中的其他节点时它会随机的选择周围几个节点散播消息收到消息的节点也会重复该过程直至最终网络中所有的节点都收到了消息。这个过程可能需要一定的时间所以不能保证某个时间点所有的节点都有该条消息但是理论上最终所有节点都会收到消息因此它是一个最终一致性协议。

Gossip协议的特点:

  • Gossip协议是周期性散播消息每隔一段时间传播一次
  • 被感染的节点每次可以继续散播N个节点
  • 每次散播消息时都会选择尚未发送过的节点进行散播
  • 收到消息的节点不会向发送的节点散播
  • 同一个节点可能会收到重复的消息因为可能同时多个节点正好向它散播
  • 集群是去中心化的节点之间都是平等的
  • 消息的散播不用等接收节点的ack即消息可能会丢失但是最终应该会被感染

我们来看个例子:

  • 种子节点是A
  • A节点选择B、C节点进行散播
  • C散播到DB散播D和E可以发现D收到两次
  • D散播到F最终整个网络都同步到了消息

Gossip有点类似图的广度优先遍历算法一般用于网络拓扑结构信息的分享和维护像redis、consul都有使用到。

Raft算法

分布式协议的难点之一就是数据的一致性当由多个节点组成的集群中只有一个节点收到数据我们就算成功的话风险太大当要求所有节点都收到数据才响应成功性能又太差所以一般会在数据的安全和性能之间做个折中只要保证绝大部分节点同步数据成功我们就算成功Raft算法作为比较知名的一致性算法被广泛应用于许多中间件中比如像etcd接下来我们就看看Raft算法是如何工作的。

首先介绍下在Raft算法中几种情况下每个节点对应的角色:

Leader节点:同大多数分布式中的Leader节点一样数据的变更都是通过它的

Follower节点:Leader节点的追随者负责复制数据并且在选举时候投票的节点

Candidate候选节点:参与选举的节点就是Follower节点参与选举时会切换的角色

Raft算法将一致性问题分解为两个的子问题Leader选举和状态复制。

选举

首先我们来看看Leader的选举系统在刚开始的时候所有节点都为Follower节点这时大家都有机会参与选举也就是把自己变成Candidate但是如果每个Follower节点都变成Candidate那么就会陷入无限的死循环于是每个Follower都一个定时器并且定时器的时间是随机的当某个Follower的定时器时间走完之后会确认当前是否存在Leader节点如果不存在就会把自己变成Candidate这时会投自己1票同时告诉其它节点让它们来投票当拿到超过半数以上的投票时当前的Candidate就会变成Leader节点。

  • 由于A节点的定时器时间最短(10ms)所以A会成为Candidate
  • A投自己一票同时B、C也投出自己的同意票因此A会变成Leader节点同时会记录是第M任。这个M是做版本校验的比如一个编号是10的节点收到了一个编号是9的节点的投票请求那么就会拒绝这个请求。

在Leader节点选举出来以后Leader节点会不断的发送心跳给其它Follower节点证明自己是活着的其他Follower节点在收到心跳后会清空自己的定时器并回复给Leader因为此时没必要触发选举了。

如果Leader节点在某一刻挂了那么Follower节点就不会收到心跳因此在定时器到来时就会触发新一轮的选举流程还是一样但是如果恰巧两个Follower都变成了Candidate并且都得到了同样的票数那么此时就会陷入僵局为了打破僵局这时每个Candidate都会随机推迟一段时间再次请求投票当然一般情况下就是先来先得优先跑完定时器的Candidate理论成为Leader的概率更大。

好的选举流程大致如上接下来我们来看看数据的复制。

复制

当Leader节点收到Client的请求变更时会把变更记录到log中然后Leader会将这个变更随着下一次的心跳通知给Follower节点收到消息的Follower节点把变更同样写入日志中然后回复Leader节点当Leader收到大多数的回复后就把变更写入自己的存储空间同时回复client并告诉Follower应用此log。至此集群就变更达成了共识。

最后Raft算法是能够实现分布式系统强一致性的算法每个系统节点有三种状态Leader、Follower、Candidate实现Raft算法两个最重要的事是:主的选举和日志的复制。

分布式事务

事务相信大家不陌事务的本质是要么一起向前冲要么一起保持不动。对于MySQL的InnoDB来说我们只需要执行begin、commit就行有时候我们可能需要回滚rollback。但是这是在同一数据库的前提下如果我们的数据表分库了或者说我们要操作的资源在不同的网络节点上该怎么办?这就得用到我们今天要说的分布式事务了分布式事务有2PC、3PC、TCC等 但是无论哪种都无法保证完美的ACID我们来一起看看是怎么回事吧。

2PC

从名字可以看出它是分两个阶段的所以它也叫做二阶段提交即准备和提交2PC要求有个事务的协调者相比常规的事务我们的请求是发给这个协调者的然后由协调者帮我们协调各个节点资源的提交。

  • 准备阶段:协调者会让各个参与事务的参与者把除了提交之外所有的事情都干好也就是就等着提交了
  • 提交阶段:协调者收到各个参与者的准备消息后根据准备情况通知各个参与者提交(commit)或者回滚(rollback)

可以发现整个过程非常依赖协调者如果协调者挂了那么整个分布式事务就不可用所以一般建议协调者至少有个备份节点。

如果协调者在收到所有节点的ok之后在准备发送commit消息的时候由于网络问题导致其中一个节点始终收不到消息那么收不到消息的节点就会一直占着资源不释放出现这种情况的时候建议协调者有个重试功能在commit失败之后不停的重试直至成功。2PC协议是一种强一致性协议它是同步阻塞的所以在高并发的场景它的性能可能还会有问题。

3PC

2PC存在一些问题比如协调者从挂了到恢复后并不知道当前节点的状态现在应该做什么(是该提交还是回滚等等)还有就是当发生网络问题的时候无法通信的节点只会傻傻的等待造成资源一直处于锁定状态。鉴于这些问题出现了3PC。

首先3PC顾名思义会分为3个阶段分别是准备阶段、预提交阶段和提交阶段。

  • 准备阶段:主要是询问参与者自身的状况比如你的负载情况如何?能参与接下来的任务吧?
  • 预提交阶段:除了commit之外的所有准备工作就等着commit了
  • 提交阶段:执行真正的commit或者rollback

如果在事务期间有新的协调者顶替进来它就可以根据一个参与者的状态来判断当前应该干嘛比如如果一个参与者处于提交阶段那么表明当前的事务正处于提交阶段。当因为网络问题某个节点一直收不到提交信息那么此时也不会傻等了会有超时时间当超时时间过去了节点可以自动提交但是这里有个问题对于参与者节点来说当前应该是commit还是rollback呢?

其实2PC和3PC都无法保证绝对的一致性因为某个参与者节点可能就是因为网络问题收不到消息但是其他参与者节点已经提交了事务一般为了预防这种问题最好加一个报警比如监控到事务异常的时候通过脚本自动补偿差异的信息。

TCC

TCC事务的全程是Try、Commit、CancelTCC事务使用场景更贴近实际应用因此它的使用也更广泛。

Try:Try这个过程一般表示锁定资源的过程比如常见的下单在try阶段我们不是真正的减库存而是把下单的库存给锁定住。

Commit:真正的执行业务逻辑了带提交的。

Cancel:撤销如果Commit失败可以把锁定的资源释放回来

TCC对应用的侵入性强。业务逻辑的每个分支都需要实现try、confirm、cancel三个操作代码改造成本高。在出现网络或者其他系统故障时TCC要根据实际业务场景实现对应的回滚逻辑。Commit或者Cancel有可能会重试因此对应的部分最好支持幂等。

最后其实上面3种分布式事务理论上都无法保证绝对的一致性因为无法解决网络等带来的意外因素要解决它要么只能无限重试但是这个无限重试最好通过消息队列+守护进程的方式来自动补数据前提还是得保证消息队列不丢失数据。总之不仅仅是分布式事务会带来这些问题分布式本身也会带来许许多多的问题没有绝对的解决方案只有更好的解决方案。


相关文章

猜您喜欢

  • atoi 函数简介 C++中的atoi 函数简介

    想了解C++中的atoi 函数简介的相关内容吗猿说编程在本文为您仔细讲解atoi 函数简介的相关知识和一些Code实例欢迎阅读和指正我们先划重点:C++atoi 函数,atoi 函数下面大家一起来学习吧。..
  • 小区后台管理系统html页面模板 小区后台管理系统项目前端html页面模板实现示例

    想了解小区后台管理系统项目前端html页面模板实现示例的相关内容吗qq_2557717688在本文为您仔细讲解小区后台管理系统html页面模板的相关知识和一些Code实例欢迎阅读和指正我们先划重点:小区后台管理系统项目前端示例模板,html前端页面模板示例下面大家一起来学习吧。..

网友评论

Copyright 2020 www.ducttapegames.com 【环球游戏网】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式