zookeeper的角色
zookeeper一般有三种角色: leader,follower,observer
zookeeper集群启动的时候会进行选举出一个leader节点,只有leader节点是可以进行写操作,follower节点只能进行同步数据和读取数据,leader节点宕机之后,follower节点是可以参与选举出来一个新的leader节点,oberver也能参与读的操作,但是oberserver节点不能参与选举。
zookeeper的作用
现在的微服务架构大行其道,各种都是分布式部署,有用到分布式的地方,基本上都绕不开zookeeper这个中间件,我们先来说下,我们用zookeeper都干哪些事情:
- 分布式锁
- 分布式协调
- master选举HA
- 元数据的存储
zookeeper的特性
集群部署,高可用
不可能单机版本,这里说的意思是基本上生产使用的话都是部署一个zookeeper集群的意思,不是说单机就不能启动起来,单机也可以自己启动一台zookeeper自己玩,但是生产上没人会只部署一台zookeeper进行跑吧;中间有某台机器宕机,可以保证数据的不丢失。
zookeeper的集群化部署最起码是3台机器组成一个zookeeper的集群,每台机器都在内存保存了zookeeper的全部数据,机器之间进行互相通信,client端可以连接任何一台机器都可以。
顺序一致性
所有的请求都是全部有序的,集群中只有一台机器可以进行写的操作,所有的机器都可以进行读的操作,所有的写请求都会分配一个zookeeper集群的全局唯一的递增编号:zxid,来进行保证client端的所有写的请求都是顺序的。
原子性
针对zookeeper集群的操作,要么全部机器都成功,要么全部机器都失败
数据一致性
这里是指无论你连接集群中的哪个zookeeper节点,看到的数据都是一致,不可能出现机器A上看到数据,跟在机器B上看到的数据是不一样的。任何一台zookeeper机器接收到写请求之后,都会把数据同步到集群中的其他机器上
watch机制
这里的实时性,是指的是zookeeper的watch机制,小园子这里把它叫做回调机器,指的是,数据一旦发生变更,它可以立马可以进行通知别的节点。
Zookeeper的数据模型
zookeeper的核心数据模型是znode树,我们往znode中写数据,就是创建树形结构的znode,znode有两种节点:持久节点和临时节点,持久节点就是哪怕客户端断开连接,节点也会一直存在,临时节点只要客户端断开连接,临时节点就不在了
Zab协议
zab协议是zookeeper中最重要的一个协议,zab协议解决了zookeeper集群中的两个最重要的问题:leader节点突然失效,如何进行恢复;leader节点如果把数据更新到所有的follower节点。zab协议的主要核心是2pc。简单来说,当有一个数据要进行写入的时候,leader会给每个follower都会创建一个队列,里面放入的是要发送给follower的数据,然后会进行发送数据给每个follower节点,当每个follower节点收到消息之后,就立即将数据写入本地磁盘日志中,写入成功之后就能保证数据不会丢失,然后会进行返回一个ack给leader,当超过一半的follower节点都返回ack之后,leader就会推动commit消息给全部的follower。
可能存在的数据不一致问题
情况一:
leader 已经收到了过半的ack,但是leader自己已经提交了commit请求,但是没来得及将commit请求进行发送给别的follower节点,自己宕机了。这样的话,宕机的leader就和别的follower节点存在了数据的不一致。
针对上述的这种情况,在进行leader节点崩溃恢复的时候,一个follower节点被选举成为了新的leader节点,这个时候就要查看自己本地的日志文件中,是否有尚未进行commit的数据,如果存在的话,可以判断是否已经有过半的机器都已经ack,如果是的话,就进行发送commit消息。
情况二:
当leader刚接收到一个请求,但是还未来得及进行同步其他follower节点,这个时候leader节点就宕机了,其他follower节点会进行重新选举出来一个新的leader节点,但是它没有那个写入的信息,这样就出现了数据错乱的情况。
针对这种情况,当leader还未进行同步其他follower节点,leader就宕机了,客户端就应该认定,数据写入失败,当这个宕机的leader重新启动起来的时候,就要舍弃掉这个数据,重新从新的leader节点中进行数据的拉取。
一个简单的小讨论
zookeeper到底是强一致性还是最终一致性?
zookeeper集群只要写入一条数据,无论是从zookeeper集群中进行读取数据,都可以进行读取到这条数据,强一致性简单来看,就相当于,你进行写操作的时候,只有所有的leader和follower节点都成功之后,才进行返回写入成功,但是从zab协议上看,写入一个数据的时候,只要有半数的节点成功了之后,就认为数据写入成功了,这样来看的话,zookeeper更倾向于最终一致性。
zookeeper官方给自己的定义是顺序一致性。这点咱们从zab协议上看更加能理解了为啥官方给的定义是顺序一致性。