一、zookeeper的介绍

1、什么是zookeeper

zookeeper是很早的注册中心,在我刚毕业的时候,就已经开始开始。一种分布式协调服务,使用简单的API和架构决绝了这个问题。

2、zookeeper的应用场景

  • 分布式协调组件,协调分布式场景下各个组件的状态
  • 分布式锁,因为zookeeper是符合cp的,所以分布式锁相对redis更安全
  • 无状态化的实现,存放登录状态

二、搭建zookeeper服务器

1、zoo.cfg配置文件说明

# zk时间配置中的基本单位(毫秒)
tickTime=2000
# 允许follower初始化链接到leader最大时长,它表示tickTime时间陪数:initLimit* tickTime
initLimit=10
# 允许follower与leader数据同步最大时长
syncLimit=5
# zk数据存储目录及日志保存目录(没指名日志目录,也保存在这个地址)
dataDir=/tmp/zookeeper
dataLogDir=/tmp/zookeeper/log
# 对客户端提供的端口号
clientPort=2181
# 单个客户端与zk最大并发连接数
maxClientCnxns=60
# 保存数据快照数量,之外的会被清除 
autopurge.snapRetainCount=3
# 自动触发清楚任务间隔时间,默认为0 表示不清除
autopurge.purgeInterval=1

2、zookeeper服务器操作命令

  • ./zkServer.sh stop\status\start.  关闭、状态、启动
  • ./zkCli.sh 客户端链接命令

三、zookeeper内部的数据模型

1、zookeeper是如何保存数据的

zk是可以存放数据的,数据都是保存在znode上,是以树状结构存放相关数据的:

 获取数据:

 那么说明,数据abc存放在test2这个znode中。 

2、zookeeper中znode是什么样结构

zk中的znode,包含四个部分:

  • data:保存数据
  • acl:权限
    • c:create权限,允许在节点下创建子节点
    • w:write权限,允许更新该节点的数据
    • r:read权限,允许读取该节点的内容及子节点的列表信息
    • d:delete权限,允许删除该节点的子节点
    • a:admin权限,允许对该节点进行acl权限设置
  • stat:表述当前znode的元数据
  • child:当前节点的子节点

3、zookeeper中节点znode的类型

  • 持久节点:创建出的节点,在回话结束后,依然存在,并能保存数据
  • 持久序号节点:创建出的节点,根据先后顺序,会在节点以后带上递增序列,适用于分布式锁、高并发场景(create -s /test01)
  • 临时节点:临时节点是在回话结束后,自动被删除的,通过这个特性,zk可以实现服务发现和注册的效果(create -e /test01)
  • 临时序号节点:跟持久序号节点相同,只不过是临时的(create -e -s /test01)
  • Container节点:容器节点,当容器中没有任何子节点的时候,会被zk定期删除(60s)(create -c /test01)
  • TTL节点:指定节点到期时间,到期后会被zk定时删除,需要设置才能开启

临时节点删除流程:

4、zookeeper的数据持久化

zk的数据是运行在内存中的,必然会提供持久化机制,zk提供的持久化有2种:

  • 事物日志:zk把执行的命令以日志的形式保存在文件中
  • 数据快照:zk会定期对内存数据做一次快照并保存到本地硬盘中

同redis一样,采用混合方式进行恢复,先用快照恢复,然后用事物日志增量恢复。

四、zookeeper客户端的使用(zkCli)

1、多节点类型的创建

2、查询节点

  • 查询普通节点
  • 查询节点相信信息
    • zCxid:创建节点的事务ID
    • mZxid:修改节点的事务ID
    • pZxid:添加和删除子节点的事务ID
    • ctime:节点创建的时间
    • mtime:节点最近修改的时间
    • dataVersion:节点的数据版本,每次修改都会+1
    • aclVersion:节点的权限版本
    • ephemeralOwner:临时节点的sessioId
    • dataLength:数据长度
    • numChildren:子节点个数

3、删除节点

  • delete -v 1 /test1 删除数据版本为1的test1节点(乐观锁)

4、权限设置

  1. 注册当前回话的账号密码:addauth digest xiaowang:123456
  2. 创建节点并设置权限:create /test-node abcd auth:xiaowang:123456:cdwra
  3. 在另一个回话,必须使用账号密码,才能操作该节点

五、Curator客户端的使用

Curator是一个zk客户端,NetFlix提供的客户端。同时也封装了很多功能,比如Leader选举、分布式锁等等,减少了java开发人员使用zk时候底层细节开发工作。也被称为最好的zk开源框架。

pom:

六、zookeeper实现分布式锁

1、zk中锁的种类

  • 读锁:大家都读,想要上读锁的之前,之前的锁没有写锁
  • 写锁:只有得到锁的才能写。想要上写锁之前,是没有任何锁

2、zk如何上读锁

  • 创建一个临时序号节点,节点的数据是read,表示读锁
  • 获取当前zk中序号比自己小的所有节点
  • 判断最小节点是否是读锁:
    • 如果不是读锁,则上锁失败,为最小节点设置监听。阻塞等待,zk的watch机制会当最小节点发生变化的时候,通知当前节点,在执行第二步
    • 如果是读锁的话,则上锁成功

3、zk如何上写锁

  • 创建一个临时序号节点,节点的数据是wirte,表示写锁
  • 获取zk中全部的子节点
  • 判断自己是否是最小的节点:
    • 如果是,则上写锁成功
    • 如果不是,则说明前面还有锁,则上锁失败,监听最小的节点,如果最小节点有变化,则回到第二步

4、羊群效应

如果使用上述的上锁方式,只要节点发生变化,就会出发其他节点的监听事件,这样的话对zk的压力很大,也就是羊群效应,使用链式监听可以解决这个问题。

七、zookeeper的watch机制

1、watch机制介绍

我们可以把watch理解成是注册在特定Znode上的触发器。当这个Znode改变了,也就是调用create、delete、setData方法的时候,就会将触发Znode上注册的对应事件,请求watch的客户端就会接收到异步通知。客户端使用NIOfang s

交互如下:

  • 客户端调用getData方法,wathc参数是true。服务端接到请求,返回节点数据,并在对应hash表中插入被watch的Znode路径,以及wathc列表
  • 当watch的znode被删除,服务端会查找hash表,异步通知所有的watcher,并删除hash表中的数据。

使用ls -w 监听目录变化。get -w 是监听节点内容的。-R 递归监听。

八、zookeeper集群实战

1、zk集群中的角色

zk集群中有三种角色:

  • Leader:处理集群所有事务,集群中只有一个leader
  • Follower:只能处理请求,参与Leader的选举
  • Observer:只能处理读请求,提升集性能,不参与Leader的选举

2、搭建集群

  1. 准备四个节点的数据
    1. 创建每个节点的myId描述文件
    2. 创建每个节点的zoo.cfg文件
    3. 创建节点之间的通信,第一个端口是数据通信、第二个端口是集群leader选举的
  2. 启动四台集群的节点

3、链接zk集群

  • ./zkCli.sh IP1:port IP2:port

九、ZAB协议

1、ZAB介绍

zk作为非常重要的分布式协调组件,集群会以一主多从的形式进行部署。zk是强数据一致性的(CP),所以用到了ZAB(原子广播协议)协议,zk节点崩溃的时候,主从同步问题。

2、ZAB协议四种节点的状态

  • Looking:选举状态
  • Following:Follower节点状态
  • Leading:Leader节点状态
  • Observeing:观察者节点状态

3、集群上线时的Leader选举过程

  1. 第一个、第二个节点启动完成后,就开始了集群选举
  2. 比较事物ID和MyID,以事物ID优先。所以第一轮就是第二个节点胜出(因为 都没有事物)
  3. 因为得票数没有超过集群的一半,第二轮选举,都会投票给上一轮成功的,同时也是node1和node2进行选举 
  4. 当node3启动后,发现已经选举完毕,自己直接就称为了follower
  5. 其实前两个节点的时候,已经知道集群有三个节点了,因为配置文件已经放入了
  6. 所以zk需要奇数节点

4、崩溃恢复时候的Leader选举

当leader宕机的时候,follower节点发现,会重新选举新的leader。此时集群不对外提供服务。

5、主从服务器之间的数据同步

  • 主节点负责全部的写操作
  • 主节点把数据写到自己的数据文件中,并返回一个ACK
  • 主节点把数据发送给从节点(广播)
  • 从节点写入到本地数据文件中
  • 从节点返回ACK给主节点
  • 主节点接收到半数以上的ACK后向从节点发送Commit
  • 从节点收到Commit后,把数据写入到内存中 

也就是zk为什么是CP的,必须半数以上的节点已经写入的文件中,才向内存提交。

6、zk中的NIO和BIO应用

  • NIO(现在已经是netty了)
    • 用于客户端链接2181端口
    • 客户端开启Watch时候,也是用NIO
  • BIO
    • 在选举投票,多节点直接通信的时候,使用BIO

十、CAP理论

1、CAP定理

一个分布式系统中最多只能同时满足一致性(C)、可用性(A)和分区容错性(P)中的2项:

  • 一致性(Consistency):一致性是指更新操并返回客户端后,所有节点统一时间的数据一直
  • 可用性(Availability):可用性是指服务一直可用,而且是正常响应时间
  • 分区容错性(Partition tolerance):分布式系统在遇到某个节点或者网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务

2、CAP权衡

既然无法同时满足CAP,那么需要社区哪个呢 ?

在分布式系统中,分区容错性一定是要满足的,否则整个系统就不存在意义。

一致性和可用性,一致性追求的就是数据的就一致性,可用性追求的就是系统在任何时候都是可用的。两个属性是相互违背的。

如果为了数据一致性,在数据同步的时候,是否对外提供服务就是一个大问题,如果提供服务,那么就会出现错误数据的访问,如果不提供服务,那么就无法满足可用性。

3、BASE理论

BASE理论是对CAP理论的眼神,核心思想是无法做到强一致性(CAP就是强一致性),但是可以采用合适的方法达到最终一致性。

  • 基本可用:基本可用性是指分布式系统在出现故障的时候,允许损失部分可用性,既保证核心可用。
  • 软状态:软状态是指允许系统存在中间状态,而该中间状态不会影响系统的整体可用性。分布式存储中一般一份数据至少会有三个副本,允许副本延迟同步就是软状态的表现。
  • 最终一致性:最终一致性是指系统中所有数据副本在经过一定时间之后,最终能够达到一致的状态。是弱一致性的一直特殊状态

4、zk追求的一致性

zk在追求过程主,满足的是CP,也就是满足数据一致性,最大的特点当复制同步的数据时候,只有半数以上的数据完成本地文件存储,才能同时写入内存。但是也不是强一致性,追求的算是顺序一致性。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐