zookeeper原理

什么是一致性:

要站在集群的角度去思考问题:

 

 

 一致性的分类:

强一致性:它要求系统写入什么,读出来的

弱一致性:不承诺立即可以读到写入的值,也不久承诺多久之后数据能够达到一致,但会尽可能地保证
到某个时间级别(比如秒级别)后,数据能够达到一致状态。 最终一致性: 系统会保证在一定时间内,能够达到一个数据一致的状态。 它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型。

注意:zookeeper尽量达到强一致性,但是实际上只实现了最终一致性

 

什么是2pc

二阶段提交(Two-phaseCommit)

2PC是一个非常经典的强一致、中心化的原子提交协议

先由一方进行提议(propose)并收集其他节点的反馈(vote),再根据反馈决定提交(commit)或中止(abort)事务。
我们将提议的节点称为协调者(coordinator),其他参与决议节点称为参与者(participants, 或cohorts)

第一阶段:

coordinator发起一个提议,分别问询各participant是否接受。

 

 

 

 第二个阶段 

coordinator根据participant的反馈,提交或中止事务,如果participant全部同意则提交,只要有一个participant不同意就中止。

 

 

 

 

zookeeper中的一致性:------Zab协议

 Zookeeper Atomic Broadcast (Zookeeper原子广播)。
Zookeeper 是通过 Zab 协议来保证分布式事务的最终一致性。

1:Leader-------选举过程

2:2pc---------------过程

3:过半机制-验证是不是超过一半

4:同步过程-----------发生机制

 

Leader领导者选举

至少要两台zk,才会有选举

 

zookeeper的数据存储:

内存---每个zk都有一个ZkDatabase对象,

磁盘----Database对象持久化到磁盘

 

 

请求的过程:

1收到一个create /quan  123请求后


2会先生成一个日志------持久化到磁盘
(使用的是追加模式,速度快)
 

3指定操作内存中的数据----DataBase

注意,我们很多数据库都是靠日志来恢复数据的

create /quan 123

set /quan 234

set /quan 345

这样子其实有些日志是不需要追加的,导致日志越来越大

解决:

zk有有个单独的线程,去定时将内存中的数据进行快照

快照就是将内存中的DataBase存到DataBase文件里面去

就在这个时候,会把日志删除掉

 

 

 

Leader的特征:

1-数据最新

因为上面我们知道处理数据之前,我们都是先进行日志追加,而日志追加的内容

有一个zxid,是一个自增的id,

这就意味着zxid越大,表示处理的数据是越多的,那集群里面应该是最新的

 

 

第二种情况:

 

 当zxid都是一致的时候,比较myid,最大的选为leader

 

 

 

zk的投票过程:

11111

 

 

服务器刚刚启动的时候,投的票都是自己
zookeeper里面存在一个hash表,存储的是投票信息zxid,myid
所以一开始都是写自己的信息

222222,发送自己的投票信息,

 

 

当投票完自己之后,需要进行集群之间的交流,服务器之间要建立socket连接

zookeeper的源码里面定义了我去连的zk的myid必须要比自己的小才能建立socket连接
这样子避免了建立多条连接

 

3333比较收到的投票信息

 

 

 

 4444

我们如果只有3台zk,那么现在就可以知道leader是谁了,因为zk有一个过半机制

 

 

555如果这个时候zk3启动

 

zk3也会先投票给自己
然后想zk1 zk2其他服务器发送自己的投票信息,
而其他服务器已经知道自己的角色了,所以直接都返回leader是谁的信息给zk3

最后其实zk3可以直接知道自己的角色是follower.

 

 6666zk3知道自己是follower后,会和leader建立一个数据同步的socket连接

 

 所以可以知道其实每一台zk都会启动三个端口,一个是leader选举端口,一个是数据同步+心跳端口

 

最后一个是zk客户端连接端口

 注意:即使zk3的zxid为200,也不会是leader,而zk里面会直接将zk3进行回滚(可以这么理解),其实就是数据同步

出现这个情况的场景就是,leader处理完一个数据之后,还没来得及通知其他zk,就已经dea掉了。所以这个数据应该

当重新启动的时候,其他在线的zk可能处理了其他请求,所以zk里面原则就是后来则follower

 

领导者选举发送的场景:

刚开始启动集群的时候

leader-down的时候

超过一半的集群内的机器挂掉的时候

注意:leader可以通过socket连接进行心跳检测,知道多少台follower在线,炒股一半的时候,会自发shutdown

 

特殊场景11

 

 

这时候其实zk2还是在选举的过程,
所以会新建socket连接去继续选举

 

2-处理数据

 

 

1客户端发送处理数据请求给leader
2leader会生成日志,并将日志发送给follower,同时开启一个死循环
3死循环的内容就是接收所有follower响应回来的ack数量,一旦数量 超过集群的一半(过半机制),leader就认为整个集群都可以处理整个请求了
4follower接收到这个日志之后,进行持久化,并返回ack给leader
5当leader接收到的ack数量过半,leader就进行数据的处理commit
6发送commit的请求给follower,
7follower接收到请求后,更新自己的database

 

特殊情况:

1当ack发送失败

leader会一直在等待,因为在源码里面,有一个laenerHandler线程会一直在等

不会报什么异常,但是因为客户端和leader的连接有timeout,所以客户端会超时

 

注意:

follower发送心跳的时候,会携带自己的zxid,leader会返回给follower当前你的zxid是大了还是小了还是相等

小了就进行同步

 

异步模式

发送commit的时候,其实是想将消息发送添加到一个队列里面,然后开启一个新的线程去从队列里面

取出消息并发送

并不会取关心follower是否commit成功,因为可以看看上面的注意,是一个补偿机制

 

posted @ 2020-09-06 20:09  小丑quan  阅读(255)  评论(0)    收藏  举报