zookeeper
Zookeeper 是一种专门为分布式应用所设计的开源协调组件, 自身具有高可用, 高性能, 数据最终一致性等特点.通常使用zookeeper 实现分布式系统中的配置维护, 命名服务, 分布式锁, 分布式消息队列, 分布式通知/协调等功能.依赖的zookeeper的应用有HDFS, Kafka, Dubbo 等.
Zookeeper 简介
1. zookeeper 应运而生
目前大部分分布式应用都需要一个主控,协调器或者控制器来管理物理分布的子进程(如资源, 任务分配等),因此,大部分应用需要开发私有的协调程序, 缺乏一个通用的机制. Google 的Chubby 是在分布式协调技术领域做的比较出色的, 但是并不是开源的, 因此zookeeper 就应运而生了,zookeeper 提供通用的分布式锁服务, 用以协调分布式应用. Zookeeper 可以说是Google Chubby的一种开源实现.
2. zookeeper 是什么
Zookeeper 是一个基于Paxos算法实现的专门应用于分布式应用的一个协调器, 自身拥有高可用, 高性能, 数据最终一致性等特点.zookeeper 包含一套简单的原语集, 分布式应用可以基于它实现数据同步, 分布式锁, 配置维护, 命名服务等功能. zookeeper 的主要目的就是保证分布式数据最终一致性的.
3. Paxos 算法核心
- Paxos 算法中每个节点进行投票时, 只看投票编号, 不看提议内容, 如果编号大于当前拥有的编号, 则同意.
- 提议必须超过半数节点同意才能通过
- zk 数据是直接存储在内存中的, 所谓提议通过是指内存中修改数据成功.
- 每个节点的数据不一定是最新的, 因为半数同意即可, 所以可能有节点数据和leader 节点数据不一致. 可以通过与 leader 同步来保证数据一致, 这也就是所谓的最终数据一致性.
2. zookeeper 集群
通常zk 集群中的节点数量为3, 5, 7, 9, 11 台, 虽然zk 节点数量越多, zk 的高可用性越高, 但是zk 集群节点的增多也会增加zk 节点之间的通信交互, 降低zk性能, 因此通常生产环境中的zk 集群中节点不会有太多, 5或者7台就可以协调上千台分布式应用服务应用了.
1. zk 节点角色
zk 集群中的节点主要有以下三种角色:
- Leader: 领导者, 负责提议的发起和决议, 更新系统状态
- follower: 跟随者, 处理客户端 请求, 选主过程中参与投票
- observe: 观察者, 处理客户端请求, 但选主过程中不参与投票, 是为了zk 集群读能力而产生的, 通常无须配置, 因为zk 集群的节点不会
2.zk 集群特点:
- zk 集群启动时, 会将本地数据加载到内存
- zk 集群启动时, 自动选主, 选主完成后, 会向leader 进行数据同步
- zk 集群新增节点时, 启动之后, 新节点会向leader 进行数据同步
3. zk 集群技术台原因
- 容错性: 3台服务器允许1台宕机, 4台服务器也是允许 1台宕机, 因此多一台也没有多大的意义
- 防止脑裂: 选主时, 如果两个提议各通过一半,那么就选不出主服务器了
4. zookeeper 原理
zookeeper 的核心是原子广播, 这个机制保障各个节点之间的数据同步, 实现这个机制的协议称之为zab 协议. Zab 协议有两种模式, 一中是恢复模式(选主过程) 和 广播模式(数据同步过程). 为保证zookeeper事务的顺序一致性, zk 采用了自增的事务唯一标识zxid 标识事务. 所有对zNode 的CURD操作时都添加了zxid, zxid 是一个64位的数字, 高32位标识leader 是否发生改变, 低32位标识修改次数,自增.
zookeeper 数据是存储在内存中的, 但也会落地到磁盘中, 所以性能很高.
1. 恢复模式
- 集群启动时, 各个节点发起提议选举自己为leader, 当收到半数节点同意之后, 升为leader, 并发送广播通知个节点更新系统状态.
- leader 宕机, 在zk 集群中follower节点检测到zk leader 宕机之后, 会发起提议推选自己为leader, 当收到半数节点同意之后, 升为leader, 然后发送广播, 通知个节点更新系统状态.
2. 广播模式
- 当zk leader 发起的更新提议通过后, zk leader 节点向集群中各个节点发送广播, 告知follower 当前leader 保存的最新数据id 是多少, 各follower节点各自更新本地当前记录的数据id.
3. ZNode 节点
1. Znode
zookeeper 中提供类似了一个层次化的目录结构, 类似于Unix 的文档目录树结构, 以保证zNode 节点的唯一性. zNode 节点和Unix 中的目录比较类似, 可以有子节点, 拥有权限管理(ACL), 命名规范 ,可拥有子节点, 不同的是, zk 的目录节点也是可以存储数据的.
2. zNode 数据类型
- zNode 有四种数据类型, 根据这四种类型节点特性, 可实现不同的操作:
数据类型 | 特点 |
---|---|
persistent | 持久性节点, 会落地在磁盘中, 不能重复创建 |
ephemeral | 临时节点, 客户端断开连接时销毁, 生命周期为客户端与节点连接的过程中, 类似于session |
persistent_sequential | 持久有序节点, 节点可重复创建, 因为创建节点时, 会自动为节点名称添加自增序号 |
ephemeral_sequential | 临时有序节点, 节点可重复创建, 因为创建节点时, 会自动为节点名称添加自增序号 |
3. zNode 存储信息
- 每个ZNode 除了存储数据之外, 还会存储一些额外的信息:
字段 | 含义 |
---|---|
czxid | 节点被创建时的事务id |
ctime | 节点上次修改的事务id |
mzxid | 节点上次修改的事务id |
mtime | 节点上次修改的时间 |
dataversion | 节点被修改的版本号 |
datalengh | 节点存储的数据的长度, 单位字节 |
aclversion | 节点的ACL 被修改的版本号 |
ephemeralOwner | 临时节点的拥有者的sessionid, 持久性节点为0 |
numChildren | 子节点的数量 |
cversion | 子节点变化版本号, 新增/删除子节点时会自增 |
pzxid | 子节点点最近修改(新增/删除)的zxid |
4.CRUD 原理
- zk 集群中, 每个节点都可以请求响应客户端请求, 但是只有leader 节点能发起修改提议. 因为只有一个节点能发起修改提议, 因此才能保证事务的一致性.
1. 查询操作:
客户端向zk 节点发送查询数据请求, 此时zk 节点数据并不一定是最新的, 若需要最新的数据, zk 节点需要向leader 进行一次数据同步 , 然后将最新的数据返回给客户端, 这就是所谓的最终数据一致性.
2. 增/删/改操作
- 客户端向集群中一个follower 节点发送更新请求
- follower节点向leader 发送更新请求, leader 中存在一个提议队列, 保证提议处理顺序
- leader 向集群中各follower节点发起更新数据提议,等待各节点回复
- follower 节点回复leader 提议, leader 收到半数通过则提议通过(提议的id大于本地记录的id即成功), 否则提议不通过;
- leader 发送广播通知各节点当前数据最新的id, 各follower各自更新本地当前记录的数据id
- follower 节点将数据返回给客户端
3. Watcher 机制
Watcher 可以监控目录节点的数据变化及子目录的变化,一旦发生变化, 那么服务器就会通知所有在这个目录节点上的watcher, 但watcher 只能通知一次, 类似于生产者消费模型, 消费后需重新注册watcher. 产生变化的因素有很多, 包括当前节点存储数据发生变化, 当前节点删除, 子节点数量发生变化等.
附:
1.ZK 高可用对比 Keepalived
- zk 做高可用只是zk 的一个副产品而已, 是应用利用zk 的临时节点类型和Watcher 机制实现, zk 各个节点都可以访问, 因此自带负载效果.
- keepalived 主要是通过虚拟ip 技术实现高可用的, 两台节点虚拟出一个ip , 根据prioriy 属性进行抢占共用ip, 因此通常keepalived 主从priority 初始值应该相差50以上. 这样主挂了之后, 从升为主, 主重启之后再抢回主节点.
方式 | 模式 | 特点 | 适用案例 |
---|---|---|---|
zookeeper | 被动模式 | 应用程序需要主动向zk 中维护并监控zk 数据变化,自带负载效果 | dubbo, HDFS, Kafka |
keepalived | 主动模式 | keepalived 主动检测应用程序是否存活, 如果宕机的话, 进行ip 漂移 | Nginx HA,mysql HA |