一致性
分布式中最重要的理论——CAP理论:一致性、可用性、分区容错性,只能满足其中两点
最终一致性
:分布式数据库一个节点写数据,不能保证另外一个节点立马读到数据,但能保证未来某个时间点可以读到
举例:DNS,公网增加一个ip以及域名,刚开始可能在其他地点访问不了,过一段时间几分钟后就可以访问
强一致性需要解决的问题
- 数据不能单节点
- 状态机复制
主从同步
可以联想到mysql主从的机制(读写分离)
主从同步复制:
-
1、master接收写请求;
-
2、master复制日志到slave(mysql中是binlog日志,复制到从relay-log);
-
3、master等待
所有
从库的返回。
明显的缺点就是一个节点失败后,mater会阻塞,导致整个集群的不可用,也就是保证了一致性,缺大大降低了可用性
多数派
并不是等待所有节点返回,而是保证每次写入大于N/2个节点,每次读出保证大于N/2个节点(zookeeper中ZAB协议就是半数协议)
看起来是较好的解决上文全部返回的问题,但还是会出现问题:
- 考虑并发环境,多个线程处理,无法保证其执行逻辑的顺序性
Paxos
Basic Paxos
- client:发请求者
- proposer:接收请求
- acceptor:提议执行(形成一定人数,大都是多数派也就是大于N/2)
- learner:备份记录
执行流程:
- 1
- prepare:proposer提出要执行事件,编号为N(N大于该proposer之前提出的编号)
- promise:acceptor只会接收大于之前编号的提议,所以看起N是否比之前大,大则接收,小则拒绝
- 2
- accept:数目达到多数派,proposer会发出接收请求,此请求包含编号以及需要执行事件内容
- accepted:在此期间如果acceptor没有受到任何编号大于N的事件,就接收该事件(所以会失败,就是要执行时候突然发现一个新的,大于N的编号,那当前事件就会拒绝)
下图,成功流程图:
下图,部分节点失败,但不影响事件提交执行,因为是多数派:
下图,proposer发给acceptor失败,可能宕机或者其他原因导致失败,此时系统另外一个proposer会接替当前失败proposer的工作,注意此时编号会变大,但内容不变:
下图,活锁问题:其中一个acceptor A 准备投票第一个事件时,突然另外一个acceptor B 也在召集投票另一事件,并且该事件比第一个事件编号大,此时A因为没有执行,所以将编号增大,但内容不变,也要召集,B也同样操作,就会导致活锁
解决方法:A执行,B等待几秒,没执行完就交替,B执行,A等待几秒;
Multi Paxos
basic paxos较难实现且效率较低,需要2轮RPC、活锁问题…
- multi paxos引入Leader,唯一的proposer,所有的请求都需经过此Leader
下图,proposer先去竞选Leader,竞选成功后,只有leader才能提出事件,并交给acceptor投票
提高效率的地方在于:第二次事件提出时,leader直接递交,也就是可以想到单分区有序执行,不会产生冲突事件,都是按照顺序执行
下图,减少角色化冗余
-
client:发送请求
-
servers:接收请求,图中表示三竖线表示三节点
- client发送请求
- 没有leader,先去竞选leader
- 有事件请求,听从leader安排
- 按顺序执行事件
- servers返回请求结果
Raft
提出问题
- 怎么选leader?
- log怎么同步其他节点?
- 如何保证集群是一致的?
定义角色
- Leader
- Follower
- Candidate(要竞选leader的follower,这是一种状态)
详细 选leader
步骤,3节点举例
-
1、刚开始三个节点会有一个timeout(超时时间),时间结束后还没有leader出现,证明该集群没有leader
-
2、想竞选leader节点变成Candidate,并且有一个id(第几任leader)和一个count(支持数,初始值为1,自己投自己),发送给其他节点投票,每有一个支持,count+1,投票结束,count=3,成为leader,此时另外两个节点timeout会刷新
-
3、leader给另外两个节点发送心跳信息,表示已经成为leader并且活着,后续事件操作也会附在心跳内进行发送,另外两个节点收到心跳也需要及时返回,并且刷新自己的timeout,如此循环
-
4、如果leader挂了,由于timeout机制,下一个leader将会出现顶替(三节点,挂一个还是多数派)
-
异外情况
:如果4个节点,有两个节点都想成为leader且都获得两票(自己一票,其他节点一票),此时这两个想竞选leader的节点就会产生一个随机的timeout,谁先结束谁就是leader
详细 log如何同步其他节点
步骤,3节点举例
- log日志也就是请求事件过来,leader拿到事件,心跳机制携带给剩余节点
- leader收到其他节点(多数派),执行commit操作,并发心跳告知其他节点写操作,这里有点二次提交的味道
详细 如何保证集群是一致
步骤,5节点举例
- 刚开始是一个节点leader(第一任),剩余4个是follower,请求过来正常操作
- 异常情况出现,产开网络分区了,3个follower属于一个区,一个leader和一个follower属于另外一个区,两区不能通信,于是三follower重现选取了leader(第二任)
- 当有请求过来,两个节点的必然执行失败,3个节点的新分区执行成功,多数派准则
- 当异常消失,5节点可以相互通信,原来旧leader会变成follower,因为任期id原故
ZAB
传送门
zookeeper中,类似于raft,名词叫法有些区别、心跳方向相反,ZAB是follower向leader