我们每天都在说分布式,那么我们知道什么是分布式,会遇到什么问题,有什么理论支持,有什么经典的解决方案,业界是如何设计和保证分布式系统的高可用性的吗?
1.架构设计本节将从一些经典的开源系统架构设计开始,看看如何设计一个高质量的分布式系统;
一般的设计起点无非是
冗余:简单理解为找一个备胎,现任挂机后,备胎会在上面拆分:一个人承担不了所有的重任,拆分之下,大家承担一部分,压力平均分担。
1.1活动/备用架构为现有服务构建备用服务。两者的功能完全一致,不同的是只有主应用可以对外提供服务。备用应用只需要保证和主应用一致,可以随时袖手旁观,不对外提供服务;当主应用出现故障时,备用应用切换到主应用,原主应用离线;主备快速切换可以有效缩短故障时间。
基于以上描述,活动和备用架构的特征是清楚的。
采用冗余方案和增加备用服务的缺点是浪费资源。
其次,在这个架构模型中最需要考虑的是如何实现主备切换。
人工虚拟IP保持激活机制
1.2主从架构主从也叫读写分离。主设备提供读写能力,从设备只提供阅读能力。
以目前的互联网应用来看,大部分都是多读少写的场景;读取更容易成为性能瓶颈,因此读写分离可以有效提高整个集群的响应能力。
主从架构可以分为:一主多从,一主多从。以mysql的主从架构模型为例来说明。
MySql主从
主从模式的主要特征是
再加一层,来源还是数据冗余的读写分离:主端负责读写,从端只负责读,可以看作是一种负载均衡策略,将数据从需要同步到主端。如果所有从机都和主机同步,主机的压力可能还是很大的;于是就有了主从模式。
关键问题是
主从延迟大师写瓶颈后如何选择大师
1.3多主多从架构一主多从面临单主节点的瓶颈问题,所以考虑多主多从策略,主节点也负责提供读写,从节点提供读取;
但是这里的核心点是多主之间的数据同步,如何保证数据的一致性是这种架构模型的重点。
比如MySql的双主双从,可以说是典型的应用场景。除了以上的一致性,实际使用中还需要考虑主键id的冲突。
1.4普通集群模式没有主节点,集群中的所有应用功能都是平等的,没有主次之分(目前大部分业务服务都属于这一类),一个请求可以被集群中的任何一个服务响应;
这种设计模式也可以称为去中心化,比如redis的集群模式和eureka注册中心,以可用性为首要目标。
对于常见的集群模式,需要考虑的要点是
资源竞争:如何保证一个资源同时只能被一个业务操作,比如同时请求退款和发货。如果这个订单没有被锁定,两个请求会同时响应,导致发货和退款,导致货与货的数据一致性丧失。如何确保所有实例数据一致,或者最终一致?如果应用服务使用jvm缓存,如何保证所有实例的jvm缓存一致?比如尤里卡的分区导致不同分区的注册信息表不一致。
1.5数据碎片架构对这种碎片模型的描述
比如redis的集群模式就是通过hash slot进行分区的。
例如es的索引分片存储。
1.6一个灰色的总结本节主要从架构设计层面对当前分布式系统所采用的解决方案做一个简单的分类和总结,不一定全面。欢迎留言指正。
基于冗余的思想:
主从多主从无中心集群
基于分裂的思想:
数据碎片
对于拆分件,我们常说的分库、分表也体现了这个思路。
2.理论基础部分将介绍分布式系统中的经典理论,如CAP/BASE理论、paxios、raft、信息交换的Gossip协议、两阶段和三阶段理论等。
本节的主要内容参考自
一致性算法-Gossip协议详解-腾讯云开发者社区-腾讯云[1] P2P网络核心技术:Gossip协议-Zhihu [2]从Paxos到Raft,分布式一致性算法分析_mb5fdb0a87e2fa1 _51CTO的技术博客[3][理论]分布式中CAP、BASE、2PC、3PC、Paxos的分析。
2.1 CAP定理CAP定理指出分布式系统不可能同时提供以下三个需求:
一致性:一致性操作更新返回客户端后,所有节点的数据完全一致。可用性:可用性服务始终可用。分区容错:当一个节点或网络分区失效时,分布式系统仍然可以提供满足一致性和可用性的服务。
一般来说,P很难保证服务部署到多个实例时,节点异常和网络故障都是正常的,根据不同的业务场景来选择。
对于服务有限的应用,优先选择AP,保证高可用性,即使部分机器异常,也不会导致整个服务不可用;比如大部分前台应用都是这样的。
对于数据一致性要求高的场景,比如涉及金钱的支付结算,CP可能更重要。
CAP的三种组合描述如下。
挑选
解释
加拿大
放弃分区容错,加强一致性和可用性,其实就是传统的单机场景。
美国联合通讯社(Associated Press)
放弃一致性(这里的一致性是强一致性),追求分区容错和可用性,是很多分布式系统设计中的选择,比如很多NoSQL系统。
大脑性麻痹
放弃可用性,追求一致性和分区容错,基本不选,网络问题会直接让整个系统不可用
2.2基础理论作为cap的延伸,基础理论的核心特征是放弃强一致性,追求最终一致性。
基本可用性:基本可用性是指当分布式系统出现故障时,允许失去部分可用性,即保证核心可以使用,比如软状态:软状态允许系统有一个中间状态,不会影响系统的整体可用性。MySQL异步模式下的主从同步,主从数据之间可能存在的不一致最终一致性:最终一致性最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。
基于以上描述,我们可以看到,BASE理论适用于大规模高可用、可扩展的分布式系统。
注意,它不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内不一致,但最终达到一致状态。
2.3 PACELEC定理我没听说过,以下内容来自:
分布式系统设计模式|作者Nishant | Medium [5]
如果有分区(' P '),分布式系统可以在可用性和一致性之间进行权衡(即' A '和' C ');否则(' e '),当系统在没有分区的情况下正常运行时,系统可以在延迟(' l ')和一致性(' c ')之间进行权衡。
定理的第一部分(PAC)与CAP定理相同,ELC是它的扩展。整个论点假设我们通过复制保持高可用性。因此,当它失败时,CAP定理占优势。但如果不是,我们仍然必须考虑复制系统的一致性和延迟之间的权衡。
2.4 Paxos一致性算法Paxos算法解决的是分布式一致性问题,即分布式系统中的每个进程如何在某个值(分辨率)上达成一致。
基于以上描述,可以看出非常适合选举;其工作流程
一个或多个提议者可以发起一个提议,Paxos算法使所有提议中的一个提议在整个过程中达成一致。系统内多数人同时认可该提议,即达成一致意见。
角色划分:
提议者:提出提议,包括数值接受者:参与决策,回应提议者的提议;当一个提议被半数以上的接受者接受时,它就被批准了。每个接受者只能批准一个建议。学习者:不参与决策,获取最新提案值。
2.5 Raft算法推荐感兴趣的伙伴,查看一下。
Raft算法动画演示[6] Raft算法详解-知乎[7]
为了解决paxos的复杂性,raft算法提供了一套更易理解的算法基础,其核心流程在于:
领导者接受请求并将其转发给追随者。大部分跟帖回复后,领导通知所有跟帖提交请求,同时自己提交请求,告诉打电话的人ok。
角色划分:
领导者:领导者接受客户的请求,并将其与追随者同步。当数据同步到大多数节点时,他告诉跟随者提交日志。跟随:接受并持久化领导同步的数据。领导通知可以提交日志后,提交候选人:领导在选举过程中的临时角色,从其他节点拉选票,大部分提升为领导。选举之后,这个角色就不存在了。
Raft共识过程
2.6 ZAB协议ZAB(ZooKeeper Atomic Broadcast)协议是专门为分布式协调服务ZooKeeper设计的支持崩溃恢复的一致性协议。基于该协议,Zookeeper实现了一个主从系统架构来维护集群中副本之间的数据一致性。
动物园管理员核心的ZAB协议就是这么简单![8]
主要用在zk的数据一致性场景中,其核心思想是:领导者收到事务请求后,半数以上的追随者返回ACK后,领导者提交提议,并向追随者发送提交信息。
角色分工负责人:整个Zookeeper集群工作机制中负责核心事务请求的唯一调度者和处理者,保证集群事务处理的顺序。跟随者,集群中每个服务器的调度者:领导者的跟随者处理客户端的非物理请求。将交易请求转发给领导服务器,参与交易请求提案的投票。参与领袖选举投票观察员:是zookeeper从3.3.0开始引入的角色。不参与交易请求议案的投票,也不参与领导人选举投票。它只提供非事务性服务(查询),通常在不影响其事务处理能力的情况下,提高集群的非事务处理能力。
ZAB信息广播
2.7 2PC协议两阶段提交协议,一个两阶段提交协议,主要是解决强一致性和集中式强一致性协议。
角色分工协调人:集中参与节点:多个。
执行流协调节点接收请求,然后向参与者节点提交预提交。当所有参与者回复ok时,协调节点向所有参与者节点提交提交,当所有参与者都返回ok时,数据被确认提交。
当一个参与者在第一阶段失败时,所有的参与者节点都会回滚。
2pc流程
其优点是实现简单。
缺点也很明显。
第一阶段协调节点单点故障正常时,第二阶段部分参与节点异常时,可能存在不一致性。
2.8 3PC协议分布式事务:两阶段提交和三阶段提交-SegmentFault [9]
在两个阶段的基础上,第一阶段分为两部分,cancommit预提交,第三阶段为docommit。
第一阶段,cancommit,协调人会询问参与者是否可以正常执行交易,参与者会根据自身情况回复一个估计值,相对于交易的真实执行是轻的。
第二阶段预提交该阶段的协调者将根据第一阶段的查询结果采取相应的行动。如果所有参与者返回ok,协调人将向参与者提交交易执行(单笔不提交)通知;否则,通知参与者中止回滚。
第三阶段docommit如果第二阶段的事务没有中断,该阶段的协调器将根据事务执行返回的结果决定提交或回滚事务,如果所有参与者都正常执行,则提交;否则,协调参与者回滚。
在这个阶段,如果参与者因为协调器或网络问题而无法接收到来自协调器的提交或回滚请求,那么参与者不会像两阶段提交中那样被卡住,而是等待超时继续提交。与两阶段提交相比,虽然减少了同步阻塞,但不能完全避免数据不一致。
特点减少拥塞和单点故障:参与者在返回CanCommit请求的响应后等待第二阶段指令,如果等待超时/协调器停机则自动中止,从而减少拥塞;在参与者返回对预提交请求的响应后,他们等待第三阶段的指令。如果它们等待超时/协调器停机,它们会自动提交事务,这也减少了拥塞。数据不一致的问题依然存在。比如第三阶段的协调者发送了中止请求,然后有些参与者没有收到中止,就会自动提交,导致数据不一致。
2.9八卦协议Gossip Protocol顾名思义,就像八卦一样,用一种随机的、具有传染性的方式将信息传播到整个网络,并使系统中所有节点的数据在一定时间内保持一致。Gossip协议可以通过上述特性保证系统在极端情况下(比如集群中只有一个节点在运行)也能运行。
P2P网络核心技术:Gossip协议-Zhihu [10]
它主要用于分布式数据库系统中同步各个副本节点的数据。这种场景最大的一个特点就是网络的节点都是对等节点,是非结构化网络。
工作流周期性地传播消息,通常周期时间为1s的被感染节点随机选择N个邻居节点。spread message每次传播消息时,选择未发送的节点传播获取消息,不会传播到向其发送消息的节点。
流言传播图
特点:扩展性:允许节点动态增减,新增加的节点状态最终与其他节点容错一致:网络中任何节点停机重启都不会影响消息传播的分散性:不需要中心节点,所有节点都是平等的,任何节点都不需要知道整个网络的状态。只要网络是连通的,一个节点的消息最终会传播到整个网络并一致收敛:协议中的消息会以一传十,十传百的相同指数速度在网络中迅速传播,所以消息传播的速度就像LOGN一样简单:Gossip协议的过程极其简单,实现上几乎没有太多的复杂性。
缺点:消息延迟:节点只会随机向少数节点发送消息,消息经过多轮传播最终到达全网。因此,使用Gossip协议会造成不可避免的消息延迟和消息冗余:节点会每隔一段时间随机选择周围的节点发送消息,接收消息的节点会重复这一步,造成消息冗余。
2.10一个灰色的总结本节主要介绍分布式系统设计中一些常见的理论基石,比如如何保证分布式系统中的一致性,如何对一个提案达成共识。
Base、CAP和PACELEC理论:构建稳定的分布式系统需要考虑的方向Paxos,RAFT共识算法zab一致性协议Gossip消息同步协议
3.算法本节将主要介绍分布式系统中的经典算法,如分区中常用的一致性哈希算法、适用于一致性的法定NWR算法、PBFT拜占庭容错算法、区块链广泛使用的工作量证明PoW算法等。
3.1一致性哈希算法一致性哈希算法主要用于数据碎片化场景,有效降低添加或删除服务对数据复制的影响。
通过散列数据项的关键字以映射其在环上的位置,然后顺时针遍历环以找到其位置大于该项的位置的第一个节点,由关键字标识的每个数据被分配给散列环中的一个节点。
一致散列算法
统一散列的主要优点是增加了稳定性;对于整个集群来说,节点的添加和删除只影响其直接邻居,其他节点不受影响。
注:Redis集群实现了一套哈希槽机制,其核心思想类似于一致哈希。
3.2法定人数NWR算法是一种投票算法,用于确保数据冗余和最终一致性。它的主要数学思想来源于鸽巢原理。
分布式系统的法定(NRW)算法——阿里云开发者社区[11]
n代表拷贝数,也称为复制因子。也就是说,n代表簇w中相同数据有多少个副本,也称为写一致性水平,也就是说成功写入w个副本将被视为本次写操作成功,r也称为读一致性水平,也就是说在读取一个数据对象时需要读取r个副本,这将被视为本次读操作成功。
Quorum NWR算法要求每个数据副本对象可以投一票,每个操作的执行需要获得最小的读票和写票数;一般来说,写投票数w一般需要超过N/2,也就是我们通常说的拿到一半以上的投票就意味着数据写成功了。
事实上,当W=N,R=1时,它叫做WARO(写全读一)。这是CAP理论中CP模型的场景
3.3 PBFT拜占庭算法拜占庭算法主要针对分布式场景下无响应或响应不可靠情况下的容错。其核心分为三个过程,如下所示。
拜占庭算法
假设集群节点数为n,f个故障节点(无响应)和f个问题节点(无响应或响应错误),f个正常节点,即3f1=n。
客户端向主节点发起请求,主节点接受请求后,向其他节点广播预准备消息;节点接受预准备消息后,如果同意请求,则向其他节点广播准备消息;当节点接收到2f 1准备新消息时,它进入提交阶段并广播提交消息。当它接收到2f 1 commit消息(包括自身)时,说明大部分节点已经进入提交阶段,并且这个阶段已经达成共识,那么节点就会执行请求,写数据。
相对于Raft算法完全不适合有人作恶的场景,PBFT算法可以容忍(n-1)/3个恶意节点(也可以是故障节点)。另外,与PoW算法相比,PBFT的优点是不消耗计算能力。PBFT算法是一种消息复杂度为O (n 2)的算法,所以随着消息数量的增加,网络延迟对系统运行的影响会更大,这就限制了运行PBFT算法的分布式系统的规模,也决定了PBFT算法适用于中小型分布式系统。
3.4工作证明(pow)算法同样适用于分布式一致性场景,不同于raft、pbft、paxos采用投票机制达成共识方案,PoW采用工作负载证明。
客户端需要做一些困难的工作才能得到一个结果,但是验证者可以很容易地通过结果检查客户端是否做了相应的工作。通过消耗一些工作波,增加了消息伪造的成本。在区块链,粉末因其广泛应用而广为人知。下面就和区块链简单说一下PoW的算法应用场景。
以BTC的转移为例。如果A转N个BTC给B,如何保证这N个币不会同时转到C?
a向B转账,交易信息记录在一个块1中。a向C转账,交易信息记录在另一块2。当块1被矿工成功提交到链上,并被大多数认可时(通过检查区块链上的哈希值是否准确,这个哈希值反映了矿工的工作量),此时未提交的块2将被丢弃。
如果提交了区块1,又提交了区块2,有些人互相认同,就会导致分歧。在区块链中,选取最长的一条链作为主链,舍弃分叉的部分(这属于区块链的知识点,有兴趣的伙伴可以展开相关知识点,这里就不展开了)。
PoW的算法主要应用于以上区块提交验证,通过哈希值的计算消耗计算能力,从而证明矿工确实付出了,并且可以达成多数人的共识。
3.5一灰一灰的总结本节主要介绍当前分布式环境下的常用算法。
分区的一致性哈希算法:基于哈希环,减少节点的动态增加,降低对整个集群的影响;适用于数据碎片化场景的法定人数NWR算法适用于一致性:投票算法,定义了如何对一个提案达成共识;PBFT拜占庭容错算法:PoW算法适用于集群中节点失效或工作负载证明广泛应用于不可信场景区块链:通过工作负载证明批准节点提交。
4.与前面的相比,这一节技术思想的内容不容易明确分类;主要包括一些高质量分布式系统实践中推荐的设计思路和技术细节。
4.1 CQRS的那些模式DDD-cqrs-zhi Hu[12]cqrs架构模式详解_架构_基斯利维尔马_InfoQ精选文章[13]
命令查询责任分离就是我们通常理解的读写分离。其核心思想是将两个不同的操作分开,在独立的服务中实现。
cqrs
目的是将领域模型从查询功能中分离出来,使一些复杂的查询可以摆脱领域模型的限制,以更简单的DTO形式呈现查询结果。同时,不同的数据存储结构被分离,允许开发人员根据查询的功能和需求更自由地选择数据存储引擎。
4.2复制负载均衡服务的分布式系统设计:服务模式下的复制负载均衡服务——知乎[14]负载均衡调度算法大全|新手教程[15]
复制负载均衡服务(RLBS)可以简单理解为我们常说的负载均衡。多个相同的服务实例构建一个集群,每个服务可以响应请求。负载平衡器负责将请求分发到不同的实例。常见的加载算法。
算法
解释
特性
投票
请求按顺序分发到相应的服务器。
优点很简单,缺点是没有考虑不同服务器的实际性能。
加权轮询
更多的请求被分配给那些具有较高权重的请求。
优点:充分利用机器的性能。
最小连接数
找到请求分发的连接数最少的服务器。如果所有服务器都有相同数量的连接,则找到第一个服务器。
目的是让空闲的机器优先响应请求。
启动时间慢,连接少
在新启动的服务器中,连接数是有限的,并且在一段时间内缓慢增加。
避免因大量请求在线分发而导致的过载。
加权最小联系
平衡服务性能的最小连接数
基于代理的自适应负载平衡
主计算机包含自适应逻辑,以定期监控服务器的状态和服务器的重量。
源地址散列法
获取客户端的IP地址,通过哈希函数映射到对应的服务器。
相同的源请求被转发到相同的服务器。
随意
随机算法选择服务器。
固定重量
最高权重仅在其他服务器的权重值较低时使用。但是,如果权重最高的服务器退出,下一个优先级最高的服务器将为该客户端提供服务。
每个真实服务器的权重需要根据服务器优先级进行配置。
加权响应
服务器响应越小,其权重越高,通常根据心跳来判断机器的速度
4.3心跳机制在分布式环境下,如何判断一个服务是否活着,目前最常见的解决方案就是心跳。
例如,raft算法中的领导者向所有follow发送心跳,表示他还活着,避免新的选举;
比如redis的sentinel机制也是通过ping/pong的心跳来判断一个节点是否离线或者需要选择新的主节点。
再比如我们日常业务需要健康监测来判断服务是否正常。
4.4租赁机制租赁就像一把锁,但即使客户离开也能起作用。客户端请求一段有限时间的租约,然后租约到期。如果客户希望延长租约,可以在租约到期前续订。
租赁主要是为了避免一个资源被一个对象长期持有,一旦对方挂机不会主动释放的问题;在实际场景中,有两个典型的应用
一般情况下,case1分布式锁服务获得的分布式锁是有有效期的。如果在有效期内没有主动释放,锁还是会被释放,其他服务也可以抢占锁。所以对于持有锁的业务方来说,如果到期前发现业务逻辑没有处理,可以续约,让自己继续持有锁。
典型的实现是redisson的看门狗机制。
情况2 raft算法的任期在raft算法中,每个领导者都有一个任期,任期结束后会重新选举。为了避免连任,领导一般会每隔一段时间给下属发一个心跳来续约。
4.5 Leader Follow很好理解,上面很多系统都采用了这种方案,特别是在共识算法中,Leader负责代表整个集群做决策,并将决策传播给所有其他服务器。
服务器启动时会进行领导者选举。当每个服务器启动时,它将启动领导者选举,并尝试选举领导者。除非选择了领导者,否则系统不会接受任何客户请求。
4.6击剑在领袖-追随者模式下,当领袖失败时,无法确定领袖已经停止工作。例如,慢速网络或网络分区可能会触发新的领导者选举,即使先前的领导者仍在运行并认为其仍是活动的领导者。
Fencint是指在以前活跃的领导者周围设置围栏,使他们无法访问群集资源,从而停止为任何读/写请求提供服务。
资源屏蔽:该系统将阻止以前活跃的领导者访问执行基本任务所需的资源。节点屏蔽:系统将阻止之前活动的领导者访问所有资源。一种常见的方法是关闭节点电源或重置节点。
4.7法定人数法定人数常用于选举和共识算法。当确认超过法定人数的节点数时,提案通过(数据更新成功)。通常,该法定人数是节点1的一半。
4.8高水位线高水位线跟踪领导者上的最后一个日志条目,并且该条目已成功复制到仲裁的Follow,这意味着该日志被整个集群接受。
日志中此项的索引称为高水位线索引。领导只透露数据到高水位线指数。
例如Kafka:为了处理不可重复的读取并确保数据一致性,Kafka broker跟踪高水位线,这是特定分区的最大偏移量。用户只能看到高水位线之前的消息。
4.9 Phi累积故障检测,利用历史检测信号信息使阈值自适应。
一般的累积故障检测器不会判断服务器是否活动,而是输出关于服务器的可疑级别。
例如,Cassandra(脸书开源分布式NoSql数据库)使用Phi accrual故障检测器算法来确定集群中节点的状态。
4.10预写日志预写日志是解决操作系统中文件系统不一致问题的高级解决方案。当我们提交写入操作系统的文件缓存时,业务会认为已经提交成功;但是,文件缓存和实际磁盘写入之间会有时间差。如果此时机器宕机,缓存中的数据将会丢失,从而导致完整性的丧失。
为了解决这个问题,mysql,es等。都采用预写日志的机制来避免这个问题。
MySql:
事务提交过程中,先写redolog预提交,再写binlog,最后写redolog提交;是书面的;当重做日志记录成功时,事务执行成功;因此,当发生上述停机恢复时,将加载redologo,然后重放相应的命令来恢复非持久数据。
弹性搜索:
在内存中的数据生成段写入操作系统文件缓存之前,会先写入事务日志,当出现异常时,也会从事务日志中恢复。
4.11分段日志将日志拆分成几个较小的文件,而不是单个大文件,以便于操作。
当在启动时读取单个日志文件时,它可能会增长并成为性能瓶颈。较旧的日志会定期清理,很难清理单个大文件。
单个日志被分割成多个段。日志文件在达到指定的大小限制后滚动。使用日志分段需要一种简单的方法来将逻辑日志偏移量(或日志序列号)映射到日志段文件。
这其实很常见。比如我们实际业务应用配置的日志,一般都是按天拆分的,大小固定,不会把所有的日志都放在一个日志文件里。
另一个例子是es的分段存储。段是一个小的存储文件。
4.12校验和验证在分布式系统中,当在组件之间移动数据时,从节点获得的数据可能会被损坏。
计算校验和,并将其与数据一起存储。
要计算校验和,请使用加密哈希函数,如MD5、SHA-1、SHA-256或SHA-512。Hash函数获取输入数据,生成固定长度的字符串(包括字母和数字);这个字符串称为校验和。
当系统存储一些数据时,它会计算数据的校验和,并将校验和与数据一起存储。当客户端检索数据时,它会验证从服务器接收的数据是否与存储的校验和匹配。如果没有,客户端可以选择从另一个副本中检索数据。
HDFS和查比将每个文件的校验和与数据存储在一起。
4.13一个灰色的总结本节大部分内容来自以下博文,感兴趣的朋友建议查看原文。
分布式系统设计模式|作者Nishant | Medium [16]
本节主要简要介绍分布式系统中应用的一些技术方案。如果有对其中一项技术感兴趣的朋友可以留言,以后会一一完成。
5.分布式系统解决方案最后介绍了一些常见的分布式业务场景和相应的解决方案,如全局唯一增量ID-雪花算法、分布式系统资源抢占-分布式锁、分布式事务-2pc/3pc/tcc、分布式缓存等。
5.1缓存缓存其实并不是分布式独有的。这里补充一下主要是因为它的应用非常广泛,在应用服务、基础软件工具、操作系统中都可以看到大量的缓存。
cache的核心思想是用更高效的IO模式取代昂贵的IO模式。
比如:
Redis的性能高于MySQL,比如内存读写,也远高于磁盘IO、文件IO、磁盘顺序读写、随机读写。
充分利用缓存可以有效提高应用程序的性能。我们以一个普通的java前台应用为例来说明。
JVM缓存-redis/memcache)-mysql缓存-操作系统文件缓存-磁盘文件
缓存的核心问题是
一致性问题:如何保证cache和db的一致性(相信大家都听说过这个问题或者实际处理过)数据完整性:比如常见的先写缓存异步刷新到磁盘,那么从缓存到磁盘刷新期间数据丢失怎么办?提示:以上问题可以参考mysql的redolog。
5.2全局唯一id在传统的单一架构中,业务id基本由数据库自增ID处理;当我们进入分布式场景,比如把数据库划分成表,就需要考虑如何实现全局唯一的业务id,避免表内冲突。
全球唯一ID解决方案:
UUid数据库自增id表Redis原子自增命令雪花算法(原生,扩展百度UidGenerator,美团叶子等。)薄雾薄雾算法
5.3分布式锁通常用于分布式系统中的资源控制。只有持有锁的人才能继续操作,确保同一时间只有一个实例可以访问该资源。
常见的分布式锁有
基于数据库实现分布式锁Redis实现分布式锁(应用)| A灰色学习[17]实现从0到1的分布式锁| A灰色学习[18] ETCD实现分布式锁基于cons实现分布式锁
5.4分布式事务代表一组操作,要么全部成功,要么全部不成功;独立事务通常指数据库事务;分布式事务可以简单理解为多个数据库的操作,要么同时成功,要么根本不成功。
更确切地说,分布式事务主要要求事务的参与者,可能涉及多个系统、多个数据资源,要求其操作要么成功,要么回滚;
一个简单的示例描述了分布式事务场景:
当用户下单并扣除库存时,订单服务会生成订单信息支付网关,该网关会记录支付信息。如果库存服务成功或失败,将扣除相应的库存。
订单支付操作涉及三个系统,同时需要分布式交易。如果支付成功,以上三个系统应该更新成功。如果某个操作失败,比如支付失败,那么被扣除的存货将被回滚(返回存货),生成的订单信息将被回滚(Delete-注意:实际上订单信息不会被删除,只是用来说明分布式交易,请不要带入实际的实现方案中)。
分布式事务的实现方案:
2PC:上面提到的两阶段提交是实现分布式事务的经典方案,3PC:三阶段提交TCC:补偿事务,简单理解为应用级2PC Saga事务本地消息表的MQ事务方案。
5.5分布式任务与单机的调度任务相比,分布式任务可以简单理解为多个实例上的调度任务。从应用场景来说,可以分为两种。
互斥分布式任务是指在同一时间,集群中只有一个实例可以执行这个任务,所有的实例都可以同时执行这个任务。继续考虑如何避免多个任务操作相同的资源。
分布式任务的实现方案:
石英集群xxl-job弹性作业自研:基于资源分片策略的分布式锁控制的唯一任务执行策略
5.6分布式会话会话通常称为会话。会话技术是一种在服务器上保持http状态的解决方案,它通过服务器保持状态。我们可以将客户端浏览器和服务器之间的一系列交互操作称为会话。它是服务器为客户端开放的存储空间,里面保存的信息用来保持状态。所以session是解决http协议无状态问题的服务器端解决方案,可以让客户端和服务器之间的一系列交互变成一个完整的事务。
单机实现基于session/cookie的用户认证,那么分布式系统的多个实例之间如何验证用户身份?这就是我们所说的分布式会话。
分布式会话实现方案:
Session stick:客户端的每一个请求都被转发到同一个服务器(比如基于ip的哈希路由转发策略)。会话复制:会话生成后主动同步到其他服务器集中存储:用户信息统一存储,每次需要时从这里取(也就是常说的redis实现分布式会话方案)。cookie:客户机cookie用于存储会话数据,并且每个请求都携带这些数据。
5.7分布式链接跟踪分布式链接跟踪也可以称为全链接跟踪,可以说是每一个开发者的福音。它通常指前端请求。在这个请求过程中,所有涉及到的系统和链路都是串联的,这样你就可以清楚的知道调用了哪些服务,有哪些IO交互,瓶颈在哪里,异常在哪里抛出。
目前主流的全链接方案大多是基于google的Dapper paper实现的。
全链路实施方案
zipkin pinpoint SkyWalking CAT jaeger
5.8 Bloom filter Bloom filter是一种节省空间的概率数据结构,用于测试一个元素是否是一个集合的成员。
Bloom filter是一种由长度为m位的位数组和k个哈希函数组成的数据结构。
原理是当一个元素被添加到一个集合中时,它被k个哈希函数映射成一个位数组中的k个点,它们被设置为1。
在搜索时,我们只需要看这些点是否都是1,就可以知道集合中是否有它。也就是说,如果这些点有任何0,那么被检测的元素一定不在那里。如果它们都为1,则选中的元素可能在。
关于布隆过滤器,请记住一件事。
如果你决定打,你就不会真的打。如果你决定不打,你一定不在里面。
布鲁姆过滤器
常见的应用场景,如
防止缓存穿透爬虫时重复检测。
5.9一个灰色的总结分布式系统的解决方案当然不仅限于以上,比如分布式存储,分布式计算,这些也是常见的场景。当然,在我们实际的业务支持过程中,不太可能需要我们自己去支持这种大的工作;上面提到的几点基本上和我们的日常工作或多或少都有关系,在这里列出来,当然是为后面的细节做铺垫。
6.一个灰色的总结6.1总结这是一篇概括性的总结文章,可能干货不多,但当然限于我个人能力。以上总结可能不准确。如果你找到它,请让我知道。
全文总结如下
常见的分布式架构设计方案:
主-备用、主-从、多主-从、公共非中央集群、数据碎片架构
分布式系统的理论基石;
Cap,base,pacelec一致性算法:Paxos,Raft,ZAB一致性协议:2PC,3PC数据同步:gossip。
分布式系统中的算法;
分区的一致性哈希算法:基于哈希环,减少节点的动态增加,降低对整个集群的影响;适用于数据碎片化场景的法定人数NWR算法适用于一致性:投票算法,定义了如何对一个提案达成共识;PBFT拜占庭容错算法:PoW算法适用于集群中节点失效或工作负载证明广泛应用于不可信场景区块链:通过工作负载证明批准节点提交。
分布式系统解决方案:
分布式缓存全局唯一ID分布式锁分布式事务分布式任务分布式会话分布式链接跟踪布隆过滤器
原文链接:https://mp.weixin.qq.com/s? _ _ biz=mzu 3 mtazntmzmq==mid=2247487507 idx=1sn=9 C4 ff 02747 e 8335 ee 5 E3 c 7765 cc 80 B3 cutm _ source=tuicoullutm _ medium=referral