Distributed System - 一致性算法(Paxos, Raft, ZAB)

CAP Theorem

对于一个分布式系统,不能同时满足以下三点。

Consistency

分布式系统,每一个节点的数据都是一致的。

在分布式系统完成某写操作后任何读操作,都应该获取到该写操作写入的那个最新的值。相当于要求分布式系统中的各节点时时刻刻保持数据的一致性。

Availability

分布式提供的服务是经常可以访问的。

一直可以正常的做读写操作。简单而言就是客户端一直可以正常访问并得到系统的正常响应。用户角度来看就是不会出现系统操作失败或者访问超时等问题。

Partition Tolerance

指的分布式系统中的某个节点或者网络分区出现了故障的时候,整个系统仍然能对外提供满足一致性和可用性的服务。也就是说部分故障不影响整体使用。

事实上我们在设计分布式系统是都会考虑到bug,硬件,网络等各种原因造成的故障,所以即使部分节点或者网络出现故障,我们要求整个系统还是要继续使用的

(不继续使用,相当于只有一个分区,那么也就没有后续的一致性和可用性了)

分区:

  • 中国的节点和美国的节点断开了联系(因为
  • 但是每个节点都能提供对应的服务

CAP取舍

(1) CA: 优先保证一致性和可用性,放弃分区容错。 这也意味着放弃系统的扩展性,系统不再是分布式的,有违设计的初衷。

CA: RDBMS

(2) CP: 优先保证一致性和分区容错性,放弃可用性。在数据一致性要求比较高的场合(譬如:zookeeper,Hbase) 是比较常见的做法,一旦发生网络故障或者消息丢失,就会牺牲用户体验,等恢复之后用户才逐渐能访问。

CP: MongoDB,HBASE,Redis

(3) AP: 优先保证可用性和分区容错性,放弃一致性。NoSQL中的Cassandra 就是这种架构。跟CP一样,放弃一致性不是说一致性就不保证了,而是逐渐的变得一致。

CouchDB

Cassandra

DynamoDB

Riak

一致性模型

弱一致性

最终一致性:最终达到一致性(不能立即得到正确的回复,在后面的某个时间点回复正确答案)

  • DNS(Domain Name System)
  • Gossip(Cassandra 的通信协议)

强一致性

  • 同步
  • Paxos
  • Raft(multi-paxios)
  • ZAB(multi-paxos)

明确问题

鸡蛋不能放在同一个篮子里、

数据不能单点存储

分布式系统对于Fault Tolerance的解决方案一般是:State Machine Replication(consensus)算法。(log replication)

paxos其实是一个共识算法。系统的最终一致性。不仅需要达成共识,还会取决于Client的行为

强一致性算法

主从同步

  1. Master接受写请求
  2. Master复制日志到Slave
  3. Master等待,直到所有从库返回

存在的问题:

  • 一个节点失败,Master阻塞,导致整个集群不可用
  • 保证了一致性,可用性大大降低

多数派

基本思想:

  • 每次写都保证写入的节点大于n/2节点,每次读从大于n/2节点中读

存在的问题:

  • 并发环境下,无法保证系统正确性,顺序非常重要

Paxos

Lesile Lamport, Latex的发明者

为描述Paxos算法,Lamport虚拟了一个叫做Paxos的希腊城邦,这个岛按照议会民主制的政治模式制订法律,但是没有人愿意将自己的全部时间和精力放在这种事。所以无论是议员,议长或者传递纸条的服务员都不能承诺别人需要时一定会出现,也无法承诺批准决议或者传递消息的时间。

Paxos(牌咳嗽嘶)

  • Basic Paxos
  • Multi Paxos
  • Fast Paxos

Baisc Paxos

角色介绍

  • Client:系统外部橘色,请求发起者。民众
  • Propser:接受Client请求,向集群提出提议Propose。并在冲突产生式,调节冲突。像议员,替民众提出议案。
  • Acceptor(Voter):提议投票和接受者,只有在形成法定人数(Quorum,一般为Majority多数派)时,提议才会被最终接受,像国会。
  • Learner:提议接受者,backup,备份,对集群一致性没什么影响。像记录员。
  1. Phase 1a : Prepare

    proposer 提出提案,编号为N,此N大于这个proposer之前提出的提案编号。请求Acceptor的quorum接受。

  2. Phase 1b : Promise

    如果N大于此acceptor之前接受的任何提案编号则接受,否则拒绝

  3. Phase 2a: Accept

    如果达到了多数派,Proposer会发出Accept请求,此请求包含提案编号和内容。

  4. Phase 2b: Accepted

    如果此acceptor在此期间没有收到任何编号大于N的提案,则接受此提案内容,否则忽略。

image-20210416183736215

image-20210416184001943

image-20210416184102802

存在的问题:

活锁、难实现、效率低(2轮RPC)

Multi Paxos

引入Leader:唯一的Proposer,所有的请求都需要经过该Leader

Raft

达到一致需要共识和客户端的行为

保证共识,划分为三个子问题:

  • Leader Election:怎么选

  • Log Replication:log 同步到其它结点

  • Safety:共识过程中每一存在错误

重新定义角色

  • Leader

  • Follower:Follow Leader的决策

  • Candidate:Follower状态

Log Replication过程

  • 初始状态:都是follower状态

  • 如果followers长时间没有收到leader的消息,他们就可以成为candidate

  • 其中一个节点会首先发起 竞选Leade投票请求:其它Follower 回复该投票

  • 拿到投票之后就可以成为Leader

  • 成为Leader之后 所有请求都要经过Leader

  • 一个请求到来set 5

  • Leader先写入本地log,再向Followers发送写请求set 5

  • Followers收到请求后会告诉leader写入完毕,Leader提交写入操作 此时数据真的被修改为5,通知Follower 可以提交了

  • 最后整个系统的数据达到一致

Leader Election

  • 一个Timer Election Timeout
  • 在一个Timer中,没有收到Leader的消息, 某个Follower首先结束了Timer,开始竞选Leader,成为Candidate 并且new一个任期(一个递增的ID 第一任总统),记录Vote Count(自身一票 + 其它Follower Vote的票),向其它Follower请求投票给自己。如果拥有了大多数的投票就称为Leader。收到投票请求的Follower就会刷新Timer
  • 成为Leader之后,对于一个Heart Beat timeout,发送一个心跳包(可以夹杂数据),刷新其它Follower Timer,维护自身的权利。
  • 任期持续到某个Follower的Timer没有收到心跳包
  • 该Follower成为Candidate重复之前的步骤。

Split Vote解决

两个节点同时成为了 Candidate,竞选同一任期总统。

解决方法:参与竞选的节点,各自等待一个随机的时间。

Partition解决

image-20210416195845218

image-20210416200023476

解决分区问题后:根据任期期间来判断那一部分是新的,分区恢复。

ZAB

基本与raft相同

在一些名词的叫法上有不同:如AZB将某一个Leader的周期称为epoch,而raft则称为term

实现上的不同:raft保证日志连续性,心跳方向为leader至follower。ZAB则相反。

项目实践

Zookeeper(ZAB)集群搭建和命令行操作

ZK采用配置文件的方法启动


Etcd(Raft)集群搭建和restful api

posted @ 2021-04-21 16:13  DengSchoo  阅读(212)  评论(0编辑  收藏  举报