前言 CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)这三个基本需求,最多只能同时满足其中的2个。 正文 1. CAP原则简介 选项 描述 Consistency(一致性) 指数据在多个副本之间能够保持一致的特性(严格的一致性) Availability(可用性) 指系统提供的服务必须一直处于可用的状态,每次请求都能获取到非错的响应(不保证获取的数据为最新数据) Partition tolerance(分区容错性) 分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障 什么是分区? 在分布式系统中,不同的节点分布在不同的子网络中,由于一些特殊的原因,这些子节点之间出现了网络不通的状态,但他们的内部子网络是正常的。从而导致了整个系统的环境被切分成了若干个孤立的区域,这就是分区。 2. CAP原则论证 如图所示,是我们证明CAP的基本场景,网络中有两个节点N1和N2,可以简单的理解N1和N2分别是两台计算机,他们之间网络可以连通,N1中有一个应用程序A,和一个数据库V,N2也有一个应用程序B和一个数据库V。现在,A和B是分布式系统的两个部分,V是分布式系统的数据存储的两个子数据库。 在满足一致性的时候,N1和N2中的数据是一样的,V0=V0。 在满足可用性的时候,用户不管是请求N1或者N2,都会得到立即响应。 在满足分区容错性的情况下,N1和N2有任何一方宕机,或者网络不通的时候,都不会影响N1和N2彼此之间的正常运作。 如图所示,这是分布式系统正常运转的流程,用户向N1机器请求数据更新,程序A更新数据库V0为V1。分布式系统将数据进行同步操作M,将V1同步的N2中V0,使得N2中的数据V0也更新为V1,N2中的数据再响应N2的请求。 根据CAP原则定义,系统的一致性、可用性和分区容错性细分如下: 一致性:N1和N2的数据库V之间的数据是否完全一样。 可用性:N1和N2的对外部的请求能否做出正常的响应。 分区容错性:N1和N2之间的网络是否互通。 这是正常运作的场景,也是理想的场景。作为一个分布式系统,它和单机系统的最大区别,就在于网络。现在假设一种极端情况,N1和N2之间的网络断开了,我们要支持这种网络异常。相当于要满足分区容错性,能不能同时满足一致性和可用性呢?还是说要对他们进行取舍? 假设在N1和N2之间网络断开的时候,有用户向N1发送数据更新请求,那N1中的数据V0将被更新为V1。由于网络是断开的,所以分布式系统同步操作M,所以N2中的数据依旧是V0。这个时候,有用户向N2发送数据读取请求,由于数据还没有进行同步,应用程序没办法立即给用户返回最新的数据V1,怎么办呢? 这里有两种选择: 第一:牺牲数据一致性,保证可用性。响应旧的数据V0给用户。 第二:牺牲可用性,保证数据一致性。阻塞等待,直到网络连接恢复,数据更新操作M完成之后,再给用户响应最新的数据V1。 这个过程,证明了要满足分区容错性的分布式系统,只能在一致性和可用性两者中,选择其中一个。 3. CAP原则权衡 通过CAP理论,我们知道无法同时满足一致性、可用性和分区容错性这三个特性,那要舍弃哪个呢? 3.1. CA without P 如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA。 3.2. CP without A 如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。很多传统的数据库分布式事务都属于这种模式。 3.3. AP wihtout C 要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。 小结 对于多数大型互联网应用的场景,主机众多、部署分散。而且现在的集群规模越来越大,所以节点故障、网络故障是常态。这种应用一般要保证服务可用性达到N个9,即保证P和A,只有舍弃C(退而求其次保证最终一致性)。虽然某些地方会影响客户体验,但没达到造成用户流程的严重程度。… Continue reading 分布式理论(一) – CAP定理
Category: 分布式
浅谈分布式系统一致性问题(一)
0.写在前面 前几天在pyq发起了约稿,分布式一致性问题的选题呼声最高,分布式系统的内容是非常庞杂的,所以我们从其中几个重点的部分切入,慢慢展开。 今天重点来一起学习分布式系统一致性问题,不过内容比较多需要分几次写完。 1.为什么要学分布式 作为后端从业人员,我们在找工作写简历的时候除了高并发经验,一般还会写上自己熟悉|了解|掌握|精通分布式系统,所以高并发和分布式大多是成对出现的。 在拉勾上搜了个后端岗位: 分布式系统是个多金的知识点,那还不抓紧行动! 2. 熵增的分布式系统 关于什么是分布式系统,有很多文章介绍,其实这个并不难理解,大白话讲就是:工厂活多了一个人撑不住,那就多找些工人一起干,要让这么多人为了一个目标干得快干得好,就需要一些规矩和套路,否则就乱了。 从实践来看分布式系统属于重要的架构模式,对于互联网工程架构的演进,简单提一下为什么会出现分布式系统以及什么是分布式系统: 业务量的迅速增大,普通的单机系统无法满足要求,要么垂直扩展升级机器硬件,要么水平扩展堆廉价服务器,这也是主流可以想到的解决方法,目前来看互联网领域选择了后者-水平扩展。 水平扩展机器多机房部署升级服务集群规模来应对业务的增长,也就出现了分布式系统,这些分布式系统中的物理节点可能是多机房多网络场景部署的,相互之间通过网络进行通信和协作。 分布式系统就是为了解决巨大业务量和数据量而生的,但是庞大数量的节点来一起正确有序的完成共同的目标是需要理论和实践来锤打的,这也是分布式系统的重点内容。 一般我们常接触的分布式系统包括两大类:分布式存储和分布式计算。 分布式系统那么多机器要一起协调去完成任务也不是一件容易的事情,所以我们通常认为分布式系统是个熵增过程。 熵是描述一个系统内在混乱程度的物理量,对于一个宏观熵看孤立的系统来说,在没有外力干预做功的前提下,系统内在混乱程度是会不断增加的,也就是熵是增加的。 为了让系统保持有序就必须对其进行外力干涉,对于分布式系统而言,我们必须使用相应的策略和算法使整个系统保持有序和正确,所以认为分布式系统是个熵增过程。 这个并不难理解,就像我们为了保持房屋整洁,定期必须打扫,要不然就乱成一锅粥了。 如果对于系统不加以控制和干预,系统将自主走向混乱和无序。 3.分布式一致性问题的理解 分布式一致性到底是什么一致? 分布式的一致性可以表现在很多方面,这些都是个性问题,然而无论这些个性问题有多少,任何行为和状态的展示必然是以数据为基础的,所以这些个性的一致性问题最终都会映射到一个共性问题—分布式数据的一致性。 分布式系统中拥有很多独立的节点,这些节点一般来说可以独立进行存储和计算任务,这两项是最主要的任务类型,本质上计算和存储的过程仍然是围绕数据展开的,所以最终还是数据一致性。 在中心化结构中,存在管理节点和任务节点的区别,也就是每个节点的权利和义务是不一样的,管理节点可能负责分配任务给下属节点和收集计算结果等,总体承担协调者的角色,任务节点主要是承接任务,这样容易出现管理节点的单点问题。 在去中心化的结构中,各个节点的权利和义务是相同的,尽管没有单独指定领导者,在实际的运行中仍然会选举出领导者和failover动态更新领导者的问题,完全的去中心化系统并不多,相比中心化系统来说,去中心系统更加扁平也更加稳定,像Redis官方集群就是去中心化的实现,任何一个节点的故障都不会带来特别大的问题,因为节点是平等的。 无论在中心化还是去中心化的分布式系统中,任何一个节点的计算和存储结果都会对其他节点产生影响,这些独立的节点通过基础和特定的网络协议进行协作,从而形成一个整体。 4. 严格意义的数据一致性 经过前面的一些铺垫,我们开始重点部分的学习-分布式系统数据一致性问题。 我们必须要有个共识:严格意义上的分布式数据一致性是不存在的。 为啥不存在呢? 在分布式系统中数据存储是多节点主从备份的,一般做成读写分离,当客户端将数据通过主库的代理写入之后,在极其短暂的瞬间,主节点的数据是无法复制到从节点的,这个瞬间其他客户端读取到的从库数据都是旧数据。 聪明的读者盆友们可以体会一下瞬间这个词,当然你可以认为这是相对论的范畴,从物理角度去看可能更能体会。 我们以redis主从节点之间的数据复制来看同步复制和异步复制场景下的数据一致性问题: 一般来说,为了保证服务的高可用,主从节点的数据复制是异步的,因为同步复制延时无法保证,当然有的场景也是同步复制的,这样整体延时是无法保证的,假如是一主多从就更无法保证了同步复制的延时了。 所以我们不讨论严苛意义上的数据一致性,而是研究在我们认为可以接受的时间长度下的数据一致性问题,也就是在自身环境约束下的数据一致性。 单机系统的一致性和事务都是比较容易达到的,在分布式系统中由于所有节点的交互都要通过网络来实现,网络必然存在不稳定并且庞大系统中的单节点稳定性也是需要考虑的。 前面这段话,读起来云里雾里,我想表达的意思是:不要过分把对单机系统中的数据一致性要求照搬到分布式系统中,因为两者的约束不一样,我们要合理分析从而让分布式系统的一致性尽量接近单机系统。 solo和团战毕竟是不一样的,典型的《倚天屠龙记》中张无忌要去少林寺救谢逊,但是遇上的少林三位神僧渡厄、渡难、渡劫已经坐禅几十年,三人合一登峰造极,实在太难了,这也是优秀分布式系统的顶峰吧… 5.CAP理论和PACELC理论 我们知道cap理论描述了一致性、可用性、分区容忍性的关系。 在分布式系统中,由于节点物理分布和网络稳定性等原因,分区容忍性P是必然存在的,因此分布式系统必然要建立在分布式网络存在分区P的前提下。 在P的基础上我们对于C和A进行选择,当然并不是说在任何时刻我们都必须C和A二选一,在网络正常的情况下C和A我们也是可以都有的,并且每个系统设计目标也不一样,需要更加实际要求来进行选择。 分布式系统中P是必然存在的,我们在设计系统之初就要对C和A做平衡和选择,在正常的情况下跑出正确的结果是基本要求,在异常情况下仍然可以正常运行是设计重点。 在分布式系统中,我们使用PACELC理论比CAP理论更加合适,因为PACELC理论是CAP理论的扩展,简单来说PACELC理论的表述是这样的: 如果分区partition (P)存在,分布式系统就必须在availability (A) 和consistency (C)之间取得平衡作出选择,否则else (E) 当系统运行在无分区P情况下,系统需要在 latency (L)… Continue reading 浅谈分布式系统一致性问题(一)
浅谈分布式一致性协议之2PC
1.前言 前面一篇文章和大家一起学习了下分布式系统一致性问题的一些理论,其中重点是理解PACELC理论、BASE理论等问题,让我们对于分布式一致性的重点是什么有一些认识。 在了解分布式一致性的理论和概念之后,后续将和大家一起讨论分布式一致性协议,其中包括:2PC、3PC、Paoxs协议、Raft协议。 篇幅有限,本文重点展开2PC协议,后续文章继续深入。 图(网络)|NASA合成的银河系中心区域图像 2. 单机事务和分布式事务 在聊2PC和3PC之前,我们有必要先了解下单机事务和分布式事务。 事务是一组原子操作,要么全成功要么全失败 All or Nothing,否则就会出现数据混乱,这种需求在金融和电商领域很普遍。 试想你去天猫买了台mac,订单服务、扣款服务、库存服务出现任何一个环节的失败都会带来问题,所以就需要事务来做保证,一荣俱荣一损俱损。 单机事务具备ACID特性,大家都比较喜欢,但是单机的能力毕竟有限,我们常常必须在分布式场景下同样完成这一组原子操作,也就是分布式事务。 由于分布式系统中各个子服务是部署在不同的物理节点上,不同交换机、不同机房、不同城市,这样以来,要想像单机系统一样完成这一组原子操作就没那么容易了,因此就出现了很多分布式一致性协议和算法,来解决分布式事务问题保证数据一致性。 分布式系统的各个节点只能依靠网络来进行数据通信,但是网络往往并不完全可靠,同时节点物理故障也时常发生,在这样一个复杂的环境中去保证数据一致性确实不太容易。 3.一致性协议的一些思路 突兀地去学习一个新的协议或者算法往往比较生硬,不如思考一下生活现象,大部分的计算机领域的算法和思想在实际生活中都有映像,又或者说算法来源于生活。 举个栗子:在规模盛大的阅兵仪式中会有陆海空多兵种多方队,为了让命令和节奏准确地下达,我们需要乐曲、指挥、领队、排头、队员等多种角色。整个活动需要在不同角色的相互作用之下,才能让一个数量庞大的个体组成一个整体来完成一个目标。 再举个栗子:2018年5月在西安举行了一场盛大的无人机编组飞行灯光秀,共计1374架无人机组成一个庞大的编组来完成灯光表演,但是还是出现了问题,并未上演完美图案: 图(网络)|西安无人机编组飞行灯光秀 分布式系统也是如此,为了让很多参与的机器节点节奏步调一致,我们就需要不同的角色各司其职,共同完成一项任务,但是仍然困难重重,因为会有网络故障和节点物理故障等问题。 4. 2PC二阶段提交协议基本过程 要理解2PC协议重点在于节点角色分工和两个阶段所执行的动作以及不同情况下的处理逻辑。 2PC协议总体概览 4.1 节点角色 二阶段提交协议将节点分为:协调者和参与者,对于者两种角色,当然你也可以理解为Leader和大头兵。 协调者Leader负责向参与者发送指令,收集参与者反馈,做出提交或者回滚决策 参与者大头兵接收协调者的指令执行事务操作,向协调者反馈操作结果,并继续执行协调者发送的最终指令 4.2 两个阶段 2PC协议分为:准备阶段和提交阶段。 4.2.1 准备阶段 协调者向所有参与者节点发送询问并执行事务的命令,参与者节点收到命令后根据自己的状态执行或者不执行事务,并将动作记录下来,最后将对命令的处理结果反馈给协调者。 图|准备阶段的三个环节 1询问环节:协调者向参与者询问,是否准备好可以执行事务,之后协调者开始等待各参与者的响应,这个环节协调者处于阻塞等待状态。 2处理环节:参与者收到协调者的询问后根据自身情况来决定是否执行事务操作,如果参与者执行事务成功,将Undo和Redo信息记入事务日志,但不提交事务;否则直接返回失败。 3响应环节:当参与者成功执行了事务操作,就反馈yes给协调者,表示事务在本地执行;当参与者没有成功执行事务,就反馈no给协调者,表示事务不可以执行提交,这部分反馈对于协调者决策下个阶段起到非常重要的作用。 4.2.2 准备阶段 协调者根据准备阶段收到的参与者反馈来决定最终提交事务或者中断回滚事务,具体来说,当协调者在准备阶段结束时收到的响应反馈有一个no,那么就中断事务,如果收到的反馈全部是yes就提交事务。 情况一: 提交事务 如果在准备阶段结束时,协调者收到了来自所有参与者的yes反馈,接下来协调者就会向所有参与者发送提交事务指令,具体的过程如下: 步骤1. 协调者向所有参与者发送事务提交消息Commit命令 步骤2. 参与者在收到来自协调者的Commit命令之后,执行事务提交动作,并释放事务期间所有持有的锁和资源,这一步很重要 步骤3. 所有参与者在执行本地事务且释放资源完成后,向协调者发送事务提交确认消息ACK 步骤4. 协调者在收到所有参与者的ACK消息后确认完成本次事务… Continue reading 浅谈分布式一致性协议之2PC
浅谈分布式系统一致性之3PC协议
一.写在前面 分布式系统一致性专题本期该写 3PC 协议了,上周太忙没有时间更新,就拿了之前的旧文章做了一些调整重发了一下,还望各位读者海涵。 后面大约还有3期:Paxos 协议、Raft 协议等,先预热一下。 温馨提示:本篇文章并不会枯燥,换了个画图工具,对于我这种建筑专业出身的IT狗来说,画图简直是最开心的事情了,所以放心看吧! 图(网络)|猎户座大星云 二.3PC的出现 之前文章中提到了 2PC 协议存在的协调者单点、参与者阻塞超时、网络分区、容错性等问题,这些在某些程度上是做优化和调整的,并不是致命问题。 我们对 2PC 协议的异常情况做了拆解,但是那是个m*n的组合问题,我们尽量去分析主要矛盾,于是发现在协调者和唯一接收指令的参与者都出现不可恢复宕机时,即使后面选举了新的协调者,仍然可能出现数据的不一致性。 3PC 的出现可能是多种因素促成的。 但是基本上可以确定 3PC 将对 2PC 存在的问题进行修正和优化,但是这样并不意味着 3PC 不会引入新的问题。 本文将从 3PC 的协议过程来阐述这两大块内容: 三. 3PC协议的基本过程 3PC协议 Three-Phase-Commit 又称三阶段提交协议,相比 2PC 协议增加了一个阶段,因此我们普遍把 3PC 协议看作是 2PC 协议的改进版本。 3PC 协议将 2PC 协议的准备阶段一分为二,从而形成了三个阶段: 协调者和参与者等待超时情况单独说,先看正常情况的基本过程,要不然容易混淆。 3.1 CanCommit阶段 在2PC准备阶段中,协调者向参与者发送指令后,参与者如果具备执行条件,则获取锁并执行动作,只不过未真正提交,可以认为参与者就差临门一脚了,还得等协调者信号。 如果是 commit 信号那还好,如果是 rollback 信号,那么对于一些本地执行了动作的参与者来说白白浪费了,所以从这个角度来说,2PC 有点激进了,但是这么做也是有原因的,在复杂的网络环境中多一轮交互意味着性能的损耗。 3PC来说更加合理,先由协调者向参与者发送询问信号,兄弟们有档期吗??然后开始收集反馈,相比来说更加轻量。 这个阶段参与者并不真实获取锁占用资源,只是对自身执行事务状态的检查,查看是否具备执行事务的条件,进而回复询问。… Continue reading 浅谈分布式系统一致性之3PC协议
图解|高性能服务器设计之缓存系统一致性
缓存系统交互 缓存系统设计是后端开发人员的必备技能,也是实现高并发的重要武器。 对于读多写少的场景,我们通常使用内存型数据库作为缓存,关系型数据库作为主存储,从而形成两层相互依赖的存储体系。 < data-tool=”mdnice编辑器” style=”border-top: none; border-bottom: none; font-size: 0.9em; overflow: auto; color: #6a737d; padding: 10px 10px 10px 20px; margin-bottom: 20px; margin-top: 20px; border-left-color: rgba(0, 0, 0, 0.65); border-right: 1px solid rgba(0, 0, 0, 0.65); background: #f9f9f9;”> 共识:我们将使用Redis和MySQL作为缓存和主存的实体,展开今天的话题。 </> 缓存系统需要处理读取场景和更新场景: 读取时只要之前MySQL和Redis中的数据是一致的,后续只要没有更新操作就不会有什么问题,借助于内存读取速度来提高并发能力,这也是我们设计缓存系统的初衷。 单纯读取的情况并不多,即使是读多写少的业务模型,也还是会有更新操作,由于操作MySQL和Redis并非天然的原子操作,因此需要我们特殊处理。 读取过程示意: < data-tool=”mdnice编辑器” style=”border-top: none; border-bottom: none; font-size: 0.9em; overflow: auto; color:… Continue reading 图解|高性能服务器设计之缓存系统一致性