打印
[PIC®/AVR®/dsPIC®产品]

一文看懂分布式存储架构-分布式理论浅析

[复制链接]
14391|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 资深从业爱好者 于 2022-11-7 13:54 编辑

由于异常的存在,分布式存储系统设计时往往会将数据冗余存储多份,每一份称为一个副本)。这样,当某一个节点出现故障时,可以从其他副本上读到数据。可以这么认为,副本是分布式存储系统容错技术的唯一手段。由于多个副本的存在,如何保证副本之间的一致性是整个分布式系统的理论核心。

数据一致性这个单词在平常开发中,或者各种文章中都能经常看见,我们常常听见什么东西数据不一致了,造成了一定的损失,赶快修复一下。那有几种一致性呢?

a、 时间一致性:要求所有数据组件的数据在任意时刻都是完全一致的;

b、 事物一致性:事务一致性只能存在在事务开始前的和事务完成之后,在事务过程中数据有可能不一致,比如 A 转 100 元给 B , A 扣减 100 , B 加上 100 ,在事务开始前和事务完成之后都能保证他们的帐是对上的,那么这就是事务一致性。但是在事务过程中有可能会出现 A 扣减了 100 元, B 没有加上 100 元的情况,这就是不一致

c、 在应用程序中涉及多个不同的单机事务,只有在所有的单机事务完成之前和完成之后,数据是完全一致的。

仅仅靠这三种一致性在实际的一些复杂场合是很难描述清楚的,所以,我们引出了一致性模型,这里我们由强到弱简单的介绍几种常见的一致性模型。

A 、线性一致性
又称强一致性, 可以看做只有一个单核处理器,或者可以看做只有一个数据副本,并且所有操作都是原子的。


如上图所示,对于事件 e1 和 e2 来说,如果事件 e1 的 response 是在事件 e2 的 invoke 之前,我们就说 e1 happen before e2 。

对于同一个线程来说,前面的事件一定 happen before 后面的事件。但是对于不同线程上的两个事件来说,它们之间只有在在时间线上没有交叉的情况下,才会存在 happen before 关系。对于有交叉的那些事件,比如下图中的 event2 和 event3 ,它们两个就不存在 happen before 关系,对于我们要寻找的合法顺序执行过程来说,它们两个的顺序可以是任意的。

B 、顺序一致性
顺序一致性弱于严格一致性。对变量的写操作不一定要在瞬间看到,但是,不同处理器对变量的写操作必须在所有处理器上以相同的顺序看到,这里处理器再分布式系统中可以换成不同的节点。


假设有两个线程 A 和 B 并发执行。其中 A 线程由 3 个操作构成,它们在程序中的顺序是:A1->A2->A3. B 线程也有 3 个操作,它们在程序中的顺序是:B1->B2->B3. 假设如果在顺序一致的模型中的效果就是如上两个图所示。

C 、因果一致性
因果一致性是弱于顺序一致性的一致性模型,顺序一致性要求所有的操作的顺序都必须按照某个单个处理器 ( 节点 ) 的顺序,而因果一致性只需要满足有因果关系的操作是顺序一致性即可。


简单来说如果有人问你一个问题,那么你给出答案,这两个就是因果关系,但如果你给出答案再问题之前,那么这个就违反了因果关系。举个简单的例子如果节点 1 更新了数据 A ,节点 2 读取数据 A ,并更新数据 B ,这里的数据 B 有可能是根据数据 A 计算出来的,所有具备因果关系,但是如果节点 3 看到的是先更新的 B ,再更新的 A 那么就破坏了因果一致性。

D 、最终一致性
其实除了强一致以外,其他的一致性都可以看作为最终一致性,只是根据一致性不同模型的不同要求又衍生出了很多具体一致性模型。当然最简单的最终一致性,是不需要关注中间变化的顺序,只需要保证在某个时间点一致即可。只是这个某个时间点需要根据不同的系统,不同业务再去衡量。再最终一致性完成之前,有可能返回任何的值,不会对这些值做任何顺序保证。

E 、可用性
可用性指“ Reads and writes always succeed” ,即服务一直可用,而且是正常响应时间。对于一个可用性的分布式系统,每一个非故障的节点必须对每一个请求作出响应。所以,一般我们在衡量一个系统的可用性的时候,都是通过停机时间来计算的。


通常我们描述一个系统的可用性时,我们说淘宝的系统可用性可以达到 5 个 9 ,意思就是说他的可用水平是 99.999% ,即全年停机时间不超过 (1-0.99999)36524*60 = 5.256 min ,这是一个极高的要求。

好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。一个分布式系统,上下游设计很多系统如负载均衡、 WEB 服务器、应用代码、数据库服务器等,任何一个节点的不稳定都可以影响可用性

F 、分布式系统的一致性
2000 年 7 月,加州大学伯克利分校的 Eric Brewer 教授在 ACM PODC 会议上提出 CAP 猜想。2 年后,麻省理工学院的 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP 。之后, CAP 理论正式成为分布式计算领域的公认定理。

CAP 理论概述:一个分布式系统最多只能同时满足一致性( Consistency )、可用性( Availability )和分区容错性( Partition tolerance )这三项中的两项。


需要特别指出的 CAP 中的一致性是 all nodes see the same data at the same time ,也就是线性一致性。

一致性必须从两个维度看:

( 1 )从客户端角度,多进程并发访问时,非分布式数据库要求更新过的数据能被后续的访问都能看到,所有都是强一致的;

( 2 )从服务端角度,如何尽快将更新后的数据分布到整个系统,降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验非常重要的方面。

参考以下公式:

N — 数据复制的份数

W — 更新数据时需要保证写完成的节点数

R — 读取数据的时候需要读取的节点数

(1) 如果 W+R>N ,写的节点和读的节点重叠,则是强一致性。例如对于典型的一主一备同步复制的关系型数据库, N=2,W=2,R=1 ,则不管读的是主库还是备库的数据,都是一致的。

(2) 如果 W+R<=N ,则是弱一致性。例如对于一主一备异步复制的关系型数据库, N=2,W=1,R=1 ,则如果读的是备库,就可能无法读取主库已经更新过的数据,所以是弱一致性。

对于一个分布式系统来说。P 是一个基本要求, CAP 三者中,只能在 CA 两者之间做权衡,并且要想尽办法提升 P 。

包含两种系统:CP without A**、 AP without C**

我们在上文所提到的 Hdfs 、 Ceph 、 Swift, 均是属于CP without A的这个大类,只是并不是完全没有 A ,为了实现一定的可用性,一般设置副本的个数为 N>=3 。不同的 N,W,R 组合,是在可用性和一致性之间取一个平衡,以适应不同的应用场景。

那么,实际生活中,也有一些是AP without C的案例,如 CAP 图中所示,大部分是 Nosql 、 CoachDB 、 Cassandra 数据库,那场景是哪些呢?

其实就是不要求正确性的场合,如某米的抢购手机场景或 12306 抢购火车票的场景,可能前几秒你浏览商品的时候页面提示是有库存的,当你选择完商品准备下单的时候,系统提示你下单失败,商品已售完。这其实就是先在 A(可用性)方面保证系统可以正常的服务,然后在数据的一致性方面做了些牺牲。

2 、数据分布
分布式系统区别于传统单机系统在于能够将数据分布到多个节点,并在多个节点之间实现负载均衡。数据分布的方式主要有两种,一种是哈希分布,如一致性哈希,代表系统为

Amazon 的 Dynamo 系统, Openstack 的 Swift 系统;另外一种方法是顺序分布,即每张表格上的数据按照主键整体有序,代表系统为 Google 的 Bigtable 系统。Bigtable 将一张大表根据主键切分为有序的范围,每个有序范围是一个子表。

A 、哈希分布( Swift )

哈希函数的散列特性很好,哈希方式可以将数据比较均匀地分布到集群中去。而且,哈希方式需要记录的元信息也非常简单,每个节点只需要知道哈希函数的计算方式以及模的服务器的个数就可以计算出处理的数据应该属于哪台机器。

然而,找出一个散列特性很好的哈希函数是很难的。这是因为,如果按照主键散列,那么同一个用户 id 下的数据可能被分散到多台服务器,这会使得一次操作同一个用户 id 下的多条记录变得困难;如果按照用户 id 散列,容易出现 “ 数据倾斜 ” ( data skew )问题,即某些大用户的数据量很大,无论集群的规模有多大,这些用户始终由一台服务器处理。

处理大用户问题一般有两种方式,一种方式是手动拆分,即线下标记系统中的大用户(例如运行一次 MapReduce 作业),并根据这些大用户的数据量将其拆分到多台服务器上。这就相当于在哈希分布的基础上针对这些大用户特殊处理;

另一种方式是自动拆分,即数据分布算法能够动态调整,自动将大用户的数据拆分到多台服务器上。其中包含两种算法。

一种是传统的哈希算法,访问数据时,首先计算哈希值,再查询元数据服务器,获得该哈希值对应的服务器。在这种算法下,服务器的上线和下线将导致大量的数据迁移,不适合于生产。

另一致性哈希( Distributed Hash Table,DHT )算法。算法思想如下:给系统中每个节点分配一个随机 token ,这些 token 构成一个哈希环。执行数据存放操作时,先计算 Key (主键)的哈希值,然后存放到顺时针方向第一个大于或者等于该哈希值的 token 所在的节点。一致性哈希的优点在于节点加入 / 删除时只会影响到在哈希环中相邻的节点,而对其他节点没影响。


如上图所示,算法本身的特性可以使得 磁盘划分为比较多的较为均匀的虚拟分区,每个虚拟分区是哈希环上的一个节点,整个环是从 0 到 32 位最大值的一个区间,并且首尾相连,当计算出数据(或者数据名称)的哈希值后,必然落到哈希环的某个区间,然后以顺时针,必然能够找到一个节点。那么这个节点就是存储数据的位置。可见如果只有一个节点,最大到 32 还未找到节点,那么数据就在第一个唯一节点上。

整个的数据定位就是基于上述的一致算法,实现将请求重新定向到该设备进行处理

(1) 在对象存储上,通过账户名 / 容器名 / 对象名三个名称组成一个位置的标识,通过该唯一标识可以计算出一个整型数;

(2) 存储设备方面, Swift 构建一个虚拟分区表,表的大小在创建集群是确定(通常为几十万),这个表其实就是一个数组;

(3) 整数值和这个数组,通过一致性哈希算法就可以确定该整数在数组的位置。


一致性算法原理上可以保证数据的均衡性、单调性,避免数据的分散性,有效的保证数据的一致性,使得负载尽可能的被映射到一个特定的缓存区。

因为 一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。所以在实际应用中,通常将虚拟节点数设置为比 32 更大的值,因此即使很少的服务节点也能做到相对均匀的数据分布。

B 、顺序分布( Bigtable )
哈希散列破坏了数据的有序性,只支持随机读取操作,不能够支持顺序扫描。某些系统可以在应用层做折衷,比如互联网应用经常按照用户来进行数据拆分,并通过哈希方法进行数据分布,同一个用户的数据分布到相同的存储节点,允许对同一个用户的数据执行顺序扫描,由应用层解决跨多个用户的操作问题。另外,这种方式可能出现某些用户的数据量太大的问题,由于用户的数据限定在一个存储节点,无法发挥分布式存储系统的多机并行处理能力。

顺序分布在分布式表格系统( Bigtable )中比较常见,一般的做法是将大表顺序划分为连续的范围,每个范围称为一个子表,总控服务器负责将这些子表按照一定的策略分配到存储节点上。


如图所示,用户表( User 表)的主键范围为 1 ~ 7000 ,在分布式存储系统中划分为多个子表,分别对应数据范围 1 ~ 1000 , 1001 ~ 2000 , ……6001 ~ 7000 。其中 Meta 表是为了支持更大的集群规模,它将原来的一层索引结分成两层,使用 Meta 表来维护 User 子表所在的节点,从而减轻 Root 节点的负担。

顺序分布与 B+ 树数据结构比较类似,每个子表相当于叶子节点,随着数据的插入和删除,某些子表可能变得很大,某些变得很小,数据分布不均匀。如果采用顺序分布,系统设计时需要考虑子表的分裂与合并,这将极大地增加系统复杂度。

C 、 CRUSH 分布
CRUSH 算法,全称叫 Controlled, Scalable, Decentralized Placement of Replicated Data. 严格说起来 Crush 算法,其实也是以 Hash 算法为基础的。只不过映射的方法和一致性哈希不同。我们用 Ceph 分布的过程来加以说明。

Ceph 分布数据的过程:首先计算数据 x 的 Hash 值并将结果和 PG 数目取余,以得到数据 x 对应的 PG 编号。然后,通过 CRUSH 算法将 PG 映射到一组 OSD 中。最后把数据 x 存放到 PG 对应的 OSD 中。注明:PG 全称是 Placement Group (放置组)。

这个过程中包含了两次映射,第一次是数据 x 到 PG 的映射。如果把 PG 当作存储节点,那么传统 Hash 算法一样。不同的是, PG 是抽象的存储节点,它不会随着物理节点的加入或则离开而增加或减少,因此数据到 PG 的映射是稳定的。


以 Dynamo 为例,在这个过程中, PG 起到了两个作用:第一个作用是划分数据分区。每个 PG 管理的数据区间相同,因而数据能够均匀地分布到 PG 上;第二个作用是充当 Dynamo 中 Token 的角色,即决定分区位置。实际上,这和 Dynamo 中固定分区数目,以及维持分区数目和虚拟节点数目相等的原则是同一回事。

以 Ceph 为例, CRUSH 算法通过两次映射计算数据存储位置来确定如何存储和检索数据。CRUSH 使 Ceph 客户机能够直接与 OSDs 通信,而不是通过集中的服务器或代理。

通过算法确定的数据存储和检索方法, Ceph 避免了单点故障、性能瓶颈和对其可伸缩性的物理限制。CRUSH 需要集群的映射,并使用 CRUSH 映射在 OSDs 中伪随机存储和检索数据,数据在集群中均匀分布。

3 、复制
为了保证分布式存储系统的高可靠和高可用,数据在系统中一般存储多个副本。当某个副本所在的存储节点出现故障时,分布式存储系统能够自动将服务切换到其他的副本,从而实现自动容错。分布式存储系统通过复制协议将数据同步到多个存储节点,并确保多个副本之间的数据一致性。

A 、强同步复制
客户端将写请求发送给主副本,主副本将写请求复制到其他备副本,常见的做法是同步操作日志( Commit Log )。主副本首先将操作日志同步到备副本,备副本回放操作日志,完成后通知主副本。接着,主副本修改本机,等到所有的操作都完成后再通知客户端写成功。下图中的复制协议要求主备同步成功才可以返回客户端写成功,这种协议称为强同步协议。


假设所有副本的个数为 N ,且 N > 2 ,即备副本个数大于 1 。那么,实现强同步协议时,主副本可以将操作日志并发地发给所有备副本并等待回复,只要至少 1 个备副本返回成功就可以回复客户端操作成功。强同步的好处在于如果主副本出现故障,至少有 1 个备副本拥有完整的数据,分布式存储系统可以自动地将服务切换到最新的备副本而不用担心数据丢失的情况。

B 、异步复制

与强同步对应的复制方式是异步复制。在异步模式下,主副本不需要等待备副本的回应,只需要本地修改成功就可以告知客户端写操作成功。另外,主副本通过异步机制,比如单独的复制线程将客户端修改操作推送到其他副本。异步复制的好处在于系统可用性较好,但是一致性较差,如果主副本发生不可恢复故障,可能丢失最后一部分更新操作。

C 、 NWR 复制
分布式存储系统中还可能使用基于写多个存储节点的复制协议( Replicated-write protocol )。比如 Dynamo 系统中的 NWR 复制协议,其中, N 为副本数量, W 为写操作的副本数, R 为读操作的副本数。

NWR 协议中多个副本不再区分主和备,客户端根据一定的策略往其中的 W 个副本写入数据,读取其中的 R 个副本。只要 W+R > N ,可以保证读到的副本中至少有一个包含了最新的更新。然而,这种协议的问题在于不同副本的操作顺序可能不一致,从多个副本读取时可能出现冲突。这种方式在实际系统中比较少见,不建议使用。

4 、分布式协议
分布式协议有很多,其中以两阶段提交和 Paxos 协议最具代表性。两阶段提交协议( 2PC )或三阶段提交( 3PC )用于保证跨多个节点操作的原子性,也就是说,跨多个节点的操作要么在所有节点上全部执行成功,要么全部失败。Paxos 协议用于确保多个节点对某个投票(例如哪个节点为主节点)达成一致。

A 、两阶段提交
二阶段提交的算法思路可以概括为 : 参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。

(1)请求阶段 ( 表决 ) :

事务协调者协调者通知事务参与者准备提交或者取消事务,然后进入表决过程。在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地执行成功)或者取消(事务参与者本地执行失败)。

(2)提交阶段 ( 执行 ):

在该阶段,协调者将基于第一个阶段的投票结果进行决策 : 提交或取消,当且仅当所有的参与者同意提交事务,协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务参与者在接收到协调者发来的消息后将执行响应的操作。


(3)两阶段提交无法解决的问题

A )、如果一个参与者迟迟不投票,那整个阶段都会处于等待状态,但这可以通过超时机制解决

B )、当协调者出错,同时参与者也出错时,两阶段无法保证事务执行的完整性。

考虑协调者在发出 commit 消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。

那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

B 、三阶段提交
三阶段提交拥有 CanCommit 、 PreCommit 、 DoCommit 三个阶段

( 1 )其中 CanCommit 阶段近似等同于两阶段的请求阶段;DoCommit 近似等同于两阶段的提交阶段。而准备阶段 PreCommit 是一个缓冲,保证了在最后提交阶段之前各参与节点的状态是一致的。

( 2 )三阶段提交在两阶段提交的第一阶段与第二阶段之间插入了一个准备阶段( PreCommit ),使得原先在两阶段提交中,参与者在投票之后,由于协调者发生崩溃或错误,而导致参与者处于无法知晓是否提交或者中止的“不确定状态”所产生的可能相当长的延时的问题得以解决。


( 3 )三阶段提交无法解决的问题

如果进入 PreCommit 后,协调者发出的是 commit 请求,假设只有一个参与者收到并进行了 commit 操作,而其他参与者对于网络中断没有收到,会根据 3PC 选择 abort 操作,此时系统状态发生不一致性。

C 、 Paxos 协议
要讲 Paxos ,先要从拜占庭问题讲起,其故事背景是这样的:拜占庭位于现在土耳其的伊斯坦布尔,是东罗马帝国的首都。由于当时拜占庭罗马帝国国土辽阔,为了防御目的,因此每个军队都分隔很远,将军与将军之间只能靠信差传消息。在战争的时候,拜占庭军队内所有将军必需达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,军队可能有叛徒和敌军间谍,这些叛徒将军们会扰乱或左右决策的过程。这时候,在已知有成员谋反的情况下,其余忠诚的将军在不受叛徒的影响下如何达成一致的协议,这就是拜占庭将军问题。

我们否定假设,给出了非拜占庭模型定义:

( 1 )一致性模块的行为可以以任意速度执行,允许运行失败,在失败后也许会重启并再次运行;

( 2 )一致性模块之间通过异步方式发送信息通信,通信时间可以任意长,信息可能会在传输过程中丢失,也允许重复发送相同的信息,多重信息的顺序可以任意。但是有一点:信息不允许被篡改。

由此,我们得出了 Paxos 的基本二阶段:Prepare 阶段、 Accept 阶段,这个两个阶段的逻辑非常复杂,是互信算法的基础,本文并不打算做过深的解读。有兴趣的读者可以去参考《区块链算法》一书。

D 、 Raft 协议
Raft 是 Replicated And Fault Tolerant 的缩写, Paxos 的简化版本。

在一个分布式系统中,要提高系统的健壮性,可用性和数据的安全性,我们最正确的姿势是什么?当然是靠多备份了,服务多备份,数据多备份,去除单点,确保即使相关组件挂掉一些,系统还能健康服务。

去除单点,没有固定不变的权威,固然好,但是带来的问题就是,以谁的意见为准,在信息可能丢失的环境下,这是一个相当困难的事(可见沟通是多么的重要)!

在 1990 年提出来之时,几乎没有人能够理解。经过作者多次简化,再解释,包括谷歌等团队的实践再创造,再解释的过程,十几年过去了,才渐渐的成为事实标准并被大家所了解和接受。但直到现在,无比抽象的 Paxos 算法,还是没有几个人能理解。

大道至简!这是永恒不变的真理, Raft 的目标问题,是构建一个容易理解和构建的分布式一致性协议,在容易的基础上,确保理论正确的。

Raft 协议,如果照本宣读,还是需要点时间的,本文采用通俗的办法给大家做解释

Raft 大致的原理,这是一个选主( leader selection )思想的算法,集群总每个节点都有三种可能的角色:

( 1 ) leader

对客户端通信的入口,对内数据同步的发起者,一个集群通常只有一个 leader 节点

( 2 ) follower:

非 leader 的节点,被动的接受来自 leader 的数据请求

( 3 ) candidate:

一种临时的角色,只存在于 leader 的选举阶段,某个节点想要变成 leader ,那么就发起投票请求,同时自己变成 candidate 。如果选举成功,则变为 candidate ,否则退回为 follower 。

算法包含两个过程:leader 选举和日志复制:

(1) 选举过程:(假设有 5 个节点, S1~S5 )

a、 初始状态下,大家都是平等的 follower ,那么 follow 谁呢,总要选个老大吧。大家都蠢蠢欲动,每个 follower 内部都维护了一个随机的 timer ;

b、 在 timer 时间到了的时候还没有人主动联系它的话,那它就要变成 candidate ,同时发出投票请求( RequestVote )给其他人,假设 S1, S3 成为 candidate

c、 对于相同条件的 candidate , follower 们采取先来先投票的策略。如果超过半数的 follower 都认为他是合适做领导的,那么恭喜,新的 leader 产生了,假如 S3 变成了新一届的大哥 leader ;

d、 S1 很不幸,没有人愿意选这个悲剧的 candidate ,那它只有老老实实的变回小弟的状态 follower;

e、 同样的,如果在 timer 期间内没有收到大哥的联络,这时很可能大哥已经跪了,如下图,所有小弟又开始蠢蠢欲动,新的一轮 (term) 选举开始了。

(2) 日志复制:(假设有 5 个节点, S1~S5 )

a、 leader 扮演的是分布式事务中的协调者,每次有数据更新的时候产生二阶段提交( two-phase commit )。在 leader 收到数据操作的请求,先不着急更新本地数据(数据是持久化在磁盘上的),而是生成对应的 log ,然后把生成 log 的请求广播给所有的 follower ;

b、 每个 follower 在收到请求之后有两种选择:一种是听从 leader 的命令,也写入 log ,然后返回 success 回去;另一种情况,在某些条件不满足的情况下, follower 认为不应该听从 leader 的命令,返回 false ;

c、 此时如果超过半数的 follower 都成功写了 log ,那么 leader 开始_第二阶段_的提交:正式写入数据,然后同样广播给 follower , follower 也根据自身情况选择写入或者不写入并返回结果给 leader ,最终所有节点的数据达成一致。

d、 这两阶段中如果任意一个都有超过半数的 follower 返回 false 或者根本没有返回,那么这个分布式事务是不成功的。此时虽然不会有回滚的过程,但是由于数据不会真正在多数节点上提交,所以会在之后的过程中被覆盖掉

Raft 协议保证_leader_的强领导地位 ,client _读写都_通过_leader__,有很高的一致性,但有些同学会问,那分布式的价值在什么地方呢?如何才能负载均衡呢?在实际中我们采用 Multi Raft 架构,结合应用,不同的应用选举不同的 leader 节点,在负载均衡。

5、跨机房部署
在分布式系统中,跨机房问题一直都是老大难问题。机房之间的网络延时较大,且不稳定。跨机房问题主要包含两个方面:数据同步以及服务切换。跨机房部署方案有三个:集群整体切换、单个集群跨机房、 Paxos 选主副本。下面分别介绍。

A 、集群整体切换
集群整体切换是最为常见的方案。如图所示,假设某系统部署在两个机房:机房 1 和机房 2 。两个机房保持独立,每个机房部署单独的总控节点,且每个总控节点各有一个备份节点。当总控节点出现故障时,能够自动将机房内的备份节点切换为总控节点继续提供服务。另外,两个机房部署了相同的副本数,例如数据分片 A 在机房 1 存储的副本为 A11 和 A12 ,在机房 2 存储的副本为 A21 和 A22 。在某个时刻,机房 1 为主机房,机房 2 为备机房。


机房之间的数据同步方式可能为强同步或者异步。如果采用异步模式,那么,备机房的数据总是落后于主机房。当主机房整体出现故障时,有两种选择:要么将服务切换到备机房,忍受数据丢失的风险;要么停止服务,直到主机房恢复为止。因此,如果数据同步为异步,那么,主备机房切换往往是手工的,允许用户根据业务的特点选择“丢失数据”或者“停止服务”。

如果采用强同步模式,那么,备机房的数据和主机房保持一致。当主机房出现故障时,除了手工切换,还可以采用自动切换的方式,即通过分布式锁服务检测主机房的服务,当主机房出现故障时,自动将备机房切换为主机房。

B 、单个集群跨机房
将单个集群部署到多个机房,允许不同数据分片的主副本位于不同的机房,如图 3-11 所示。每个数据分片在机房 1 和机房 2 ,总共包含 4 个副本,其中 A1 、 B1 、 C1 是主副本, A1 和 B1 在机房 1 , C1 在机房 2 。整个集群只有一个总控节点,它需要同机房 1 和机房 2 的所有工作节点保持通信。当总控节点出现故障时,分布式锁服务将检测到,并将机房 2 的备份节点切换为总控节点。


如果采用这种部署方式,总控节点在执行数据分布时,需要考虑机房信息,也就是说,尽量将同一个数据分片的多个副本分布到多个机房,从而防止单个机房出现故障而影响正常服务。

C 、 Paxos 选主副本
如果采用 Paxos 协议选主副本,那么,每个数据分片的多个副本构成一个 Paxos 复制组。如图所示, B1 、 B2 、 B3 、 B4 构成一个复制组,某一时刻 B1 为复制组的主副本,当 B1 出现故障时,其他副本将尝试切换为主副本, Paxos 协议保证只有一个副本会成功。这样,总控节点与工作节点之间不再需要保持租约,总控节点出现故障也不会对工作节点产生影响。它的优点在于能够降低对总控节点的依赖,缺点在于工程复杂度太高,很难在线下模拟所有的异常情况。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

57

主题

89

帖子

0

粉丝