AlexiaChen / AlexiaChen.github.io

My Blog https://github.com/AlexiaChen/AlexiaChen.github.io/issues
87 stars 11 forks source link

架构设计-----存储高可用 #81

Open AlexiaChen opened 4 years ago

AlexiaChen commented 4 years ago

存储高可用

一般本质上都是通过将数据复制到多个存储设备,通过数据冗余的方式来实现高可用,其复杂性主要体现在如何应对网络延迟和网络中断导致的数据不一致的问题。

所以思考的问题是:

主备复制

最常见的方案,也是最简单的。几乎所有存储系统都提供了主备复制的功能,比如MySQL,Redis,MongoDB等。

基本实现

优缺点分析

优点:

缺点:

一般这种方案不会用在互联网中,但是用在企业管理后台就挺多了,有些企业后台数据不是很重要,比如某学校或公司的员工管理系统,考勤系统等等。业务量不大,数据变更频率低。可以用主备复制方案。

主从复制

与主备只差一个字,“从”是slave,随从,奴仆的意思,意思从机是要承担一部分主机的工作量的,不仅仅作为备份,它要干活的。一般从机只承担读操作,主机负责读写操作,一般业务的读写分离,就是这样的架构。

基本实现

优缺点分析

优点:

缺点:

一般这种方案不会用在互联网行业的主流业务中,因为互联网行业要7 × 24小时运行,更不可能需要人工干预。但是这样的方案,适合用在论坛,BBS,新闻网站这类读多写少的业务中,此类业务的读操作一般在写操作的10倍乃至百倍以上。如果搭建一个社区,学校BBS啥的,确实可以考虑主从。

主备切换与主从切换

设计关键

主备和主从有两个共性问题:

主备切换和主从切换其实就是增加了一个自动切换角色的功能,无需人工干预,以达到高可用。貌似就是自动化而已,没什么难的? 其实不是的,自动切换复杂度提升了一个量级。如果选择自研,以代码量来衡量就是10倍的差距,差了一个数量级。为什么会这么复杂? 接着往下看:

  1. 主从间的状态判断
  1. 切换决策
  1. 数据冲突解决

当故障的主机恢复后,主从之间可能存在数据冲突,冲突的时候该怎么选择?你用git的时候不同的分支数据合并的时候,都会冲突呢,到底用谁的数据?

主从切换不同的存储系统其实已经有成熟的方案了,MySQL有MHA,Redis有Sentinel。所以小公司,没有研发能力的,还是尽量用成熟的方案吧。当然,还可以选择部分自研,你可以用Zookeeper来作为第三方仲裁协调节点,来让MySQL达到高可用。你在网上可以搜到基于Zookeeper来实现MySQL HA的方案

这样的主从自动切换方案,就开始接近现代互联网的存储高可用方案了。

主主复制

意思就是两台机器都是主机,互相将数据复制给对方,客户端可以任意选择其中一个机器进行读写业务。

优点:

缺点:

主主复制架构必须保证数据能够双向复制,但是,很多数据是不能双向复制的。比如,用户ID自增,如果双向复制,会导致不一致,冲突。余额这样的数据双向复制也会出问题。

所以,主主复制架构对数据的设计有严格要求,一般适合临时的,可丢失的,可覆盖的数据场景。比如,用户登录的session数据,用户行为的日志数据,论坛的草稿数据。

数据集群

主备,主从,主主架构都有一个隐含的假设:就是,主机能够存储所有数据(并且都是两台机器)。然而,对于现代互联网企业,没有这样的存储能力和处理能力应对海量数据的主机。2013年的时候,FaceBook一天上传的图片差不多就是3亿5000万张。到现在差不多也是千亿级别的图片数量,照片的容量已经达到PB级别,这么大的数据量肯定是需要数据集群架构了。

集群分为两大类,数据集中式和数据分散式集群。

数据集中式集群

这种架构与主备,主从架构类似,它无非就是把备机,从机弄成多个,叫1主多备,一主多从。一般读写业务也只是到主机,读业务可以分散都各种备机,复制通道不止一条,可能也会导致备机之间数据不一致。解决方案也可以用Zookeeper来协调。对于现代互联网企业,这种架构也是用不了了。暂时不过多讨论。

数据分散式集群

意思就是,多个服务器组成一个集群,每台服务器负责存储一部分数据(Region)。为了提升可用性,同时每台服务器又会备份一部分数据(Replica)。

一般这样的架构就已经是现代互联网的主流思路了。复杂点在于如何将数据分散到不同的服务器上,需要考虑以下三点:

在分散式集群中,每台服务器都可以处理读写请求,与集中式不一样。在分散式集群中,必须有一个角色来负责执行数据分配算法,这个角色可以是一台独立配置的服务器(会有单点故障风险),也可以是集群自己选举出的一台服务器(通过分布式共识算法,无单点故障)。一般选举出来的节点机器叫主机,也可以叫leader或者manager节点。

Hadoop的实现就是独立配置的服务器负责数据分区的分配,这台服务器叫Namenode。这台服务器是中心化的节点,负责管理一堆Datanode。Namenode执行文件系统的名字空间操作,也负责确定文件数据块到具体的Datanode节点的映射。Datanode处理文件系统客户端的读写请求,在Namenode的统一调度下进行数据块的创建,删除和复制操作。

ElasticSerach集群就与Hadoop集群不一样了,它是由分布式共识算法选举出来的leader节点来做数据分区的分配,叫master node。

集中式与分散式架构总结

所以,你也看到了,就技术先进性来说,肯定是分散式架构更好,分散式也更符合主流互联网企业大数据的诉求,也决定了两种架构的应用场景不同。集中式显然适合数据量不大,集群机器数量不多的场景。而分散式集群由于良好的可伸缩性,适合的业务数据就是海量数据,机器数量庞大,比如Hadoop,HBase集群,节点规模可以达到上百,上千。

分布式事务算法

某些业务场景需要事务来保证数据一致性,如果采用了数据集群方案,那么数据可能分散在不同的节点上,由于节点间只能通过消息进行通信,因此分布式事务实现起来只能依赖消息通知。但是由于网络本身不可靠,消息可能会丢失,这就给分布式事务的实现带来了复杂性。

分布式事务也要保证ACID,比较有名的算法是两阶段提交协议(2PC)和三阶段提交协议(3PC)。

2PC

字面意思,就是由两个阶段步骤组成,分别是commit-request阶段(投票阶段)和commit阶段。该算法的成立基于以下假设:

所以从以上假设上看,最好每个节点都需要支持单机ACID本地事务。

2PC第一阶段

有时候这一阶段也被成为投票阶段,即各参与者投票是否继续接下来的提交操作。

2PC第二阶段

当所有参与者都返回Yes时(成功):

当所有参与者其中任意一个返回No时,或者投票阶段由于网络超时导致接收响应失败(失败):

这个阶段有时候叫完成阶段,因为无论结果怎样,协调者都必须在此阶段结束当前事务

2PC优缺点

2PC是强一致性事务算法,优点是实现简单,但是缺点也很明显:

3PC

3PC从名字上看就像为了解决一部分2PC带来的问题而生的,事实上也确实是这样的,3PC是针对2PC存在的“单点故障”和“可能一直阻塞”而提出的解决方案。通过在2PC的两个阶段之间插入一个新的中间阶段----“准备阶段”,当协调者故障后,参与者可以通过超时提交来避免一直阻塞。

3PC第一阶段

也叫提交判断阶段

3PC第二阶段

也叫准备提交阶段

3PC第三阶段

也叫提交执行阶段

3PC的优缺点

优点提到了,只说缺点,缺点就是在极端情况下还是会存在数据不一致的问题。

其他分布式事务算法

业界XA协议,TCC(Try-Confirm-Cancel)这种柔性事务方案。

分布式共识算法

有些时候也叫分布式一致性算法。分布式事务算法主要目的是为了保证分散在多个节点上的数据的统一提交或统一回滚,以满足分布式事务的ACID的要求。而分布式共识算法的主要目的是为了多个节点达成一致性的共识,这样就可以做到保证同一份数据在多个节点上的一致性,以满足CAP中的CP要求。

复制状态机的核心就是分布式共识算法,该算法很复杂,其中特别死Paxos最难,最复杂。

Paxos

Lamport老爷子发明,最有名的就是这个算法了,已经被理论上证明是正确的算法了。

Paxos的一个问题就是,特别复杂,特别难以理解,Raft的论文中都提到,如果不是作者读了很多资料,并且自己设计了代替的算法之后是不能够真正理解Paxos算法的。Raft作者这么牛逼的人物都觉得Paxos复杂了,可见还是复杂的。

Paxos还有一个巨大的问题就是,论文中缺乏很多细节,工程上难以实现,这些细节在工程实现上不可避免。 有些Paxos算法的工程实现,可能会有bug,也不能被证明正确。

Google的分布式协调服务Chubby底层就是一个以Paxos为基础的一致性算法,但是其开发者这么评论过:Paxos算法的描述和真实世界的系统的需求实现存在巨大的实现鸿沟,最终系统只能实现为一个没有被证明为正确的Paxos-like的共识协议。

虽然如此,但Paxos算法的地位是不可代替的,Chubby的作者也评价过:世界上只有一种共识算法,就是Paxos,所有其他一致性算法都是Paxos算法的阉割版。

这个章节能力有限,就不讲Paxos算法描述了,不过Paxos如此有名,甚至Paxos的原始论文都有翻译质量比较高的中文翻译了,还有精读注解。

Raft

为了解决复杂不堪,难以理解,工程上难以实现正确的Paxos算法,由此Raft算法诞生了。之前提到过,非Paxos算法的共识算法都是Paxos的阉割版。恩,Raft算法从理论上来讲确实不是一个完备的分布式共识算法。

为了可理解,可操作,可实践,Raft对一些复杂的处理做了一些简化,以保证绝大部分情况下都保证一致性。

Raft算法通过将分布式一致性的问题拆分为3个子问题来简化算法:Leader选举,日志复制,安全保证。Raft强化了leader的作用,通过leader来保证分布式一致性。Raft算法也详细说明了具体工程实现时的各种方案细节。比如,日志亚索,Client互交等。基本上对照算法论文就能够实现,而且代码量也不大。

Raft论文中提到只用了2000行C++代码就实现了算法。

ZAB

全称:Zookeeper Atomic Broadcast Protocol,是Zookeeper系统中采用的分布式共识算法。抛开各种细节,ZAB和Raft的实现类似,也是Paxos的阉割版。比如,强化leader的作用,通过leader来保证分布式一致性。

共识算法的比较

ZAB,Paxos和Raft有一个较大的差异就是复制的方式,Paxos和Raft采用的是状态机副本(state machine replication,又叫active replication),ZAB采用的是主备份(primary backup,又称passive replication)。

这样的思路有点像MySQL中的binlog,确实有点像。

注意:以上的共识算法的前提都是非拜占庭网络环境(一般是公司内网,不考虑存在恶意节点),如果是拜占庭网络环境(公网,一定要考虑恶意节点作恶),那么共识算法就不是这些了,拜占庭网络的共识算法一般是区块链相关的共识算法:PoW,PoS,DPoS,PBFT等。

EOF