zookeeper知识总结
2020-11-27 14:54:26 6 举报
AI智能生成
zookeeper最全知识总结。包括基础和进阶知识。集群配置,Leader选举等。
作者其他创作
大纲/内容
背景
解决分布式系统的协调问题
分布式系统
概念
硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递
进行通信和协调的系统
进行通信和协调的系统
特点
分布性
各个服务分布在不同的机器。空间上是随意的
对等性
防止单个服务出现问题,都会有一个备份服务存在,两个服务是对等的
并发性
多服务器节点可能并发的操作共享数据,需要协调各服务
缺乏全局时钟
节点分布在任意地方,每个节点都有自己的时间系统。现在可以通过时间服务器解决
故障随时发生
任意节点都可能发生问题,断电,宕机等。开发人员需要保证服务的高可用。
问题
通信异常
通讯异常其实就是网络异常,网络系统本身是不可靠的,由于分布式系统需要通过网络进行 数据传输,网络光纤,路由器等硬件难免出现问题。只要网络出现问题,也就会影响消息的 发送与接受过程,因此数据消息的丢失或者延长就会变得非常普遍。
网络分区
脑裂现象主要是指当出现网络分区时,zookeeper集群形成了两个或者多个leader的情况,这时如果两个leader都提供服务,则会出现数据不一致问题。
三态
三态是什么?三态其实就是成功,与失败以外的第三种状态,叫超时态。
在一个 jvm 中,应用程序调用一个方法函数后会得到一个明确的相应,要么成功,要么失败, 而在分布式系统中,虽然绝大多数情况下能够接受到成功或者失败的相应,但一旦网络出现 异常,就非常有可能出现超时,当出现这样的超时现象,网络通讯的发起方,是无法确定请 求是否成功处理的。
在一个 jvm 中,应用程序调用一个方法函数后会得到一个明确的相应,要么成功,要么失败, 而在分布式系统中,虽然绝大多数情况下能够接受到成功或者失败的相应,但一旦网络出现 异常,就非常有可能出现超时,当出现这样的超时现象,网络通讯的发起方,是无法确定请 求是否成功处理的。
节点故障
服务器节点的宕机或者故障
解决办法
CAP理论
一致性(Consistency)
在分布式系统中,一致性是数据在多个副本之间是否能够保证一致的特性。如果能够在分布式系统中针对某一个数据项的变更成功执行 后,所有用户都可以马上读取到最新的值,那么这样的系统就被认为具有【强一致性】
可用性(Availability)
可用性指系统提供服务必须一直处于可用状态,对于用户的操作请求总是能够在有限的时间 内访问结果。
这里的重点是【有限的时间】和【返回结果】 为了做到有限的时间需要用到缓存,需要用到负载,这个时候服务器增加的节点是为性能考 虑; 为了返回结果,需要考虑服务器主备,当主节点出现问题的时候需要备份的节点能最快的顶 替上来,千万不能出现 OutOfMemory 或者其他 500,404 错误,否则这样的系统我们会认为 是不可用的。
这里的重点是【有限的时间】和【返回结果】 为了做到有限的时间需要用到缓存,需要用到负载,这个时候服务器增加的节点是为性能考 虑; 为了返回结果,需要考虑服务器主备,当主节点出现问题的时候需要备份的节点能最快的顶 替上来,千万不能出现 OutOfMemory 或者其他 500,404 错误,否则这样的系统我们会认为 是不可用的。
容错性(Partition tolerance)
分布式系统在遇到任何网络分区故障的时候,仍然需要能够对外提供满足一致性和可用性的 服务,除非是整个网络环境都发生了故障。
不能出现脑裂的情况
不能出现脑裂的情况
一个分布式系统,不可能同时满足以上三种特性,只能同时满足以上两种
现在服务部署不可能所有服务放在一台机器上,所以一定是存在分区的,架构师需要考虑的是如何平衡一致性 和 可用性。
BASE理论
背景
根据CAP理论,分布式系统中,需要权衡一致性和可用性。系统的完全不可用是不能接受的,所以需要放弃一致性。因此在分布式环境下不能保证强一致性
定义
在不能保证强一致性的情况下,系统需要采取适当的方法保证最终一致性
方式
Basically Avaliable 基本可用
当分布式系统出现不可预见的故障时,允许损失部分可用性,保障系统的“基本可用”;体 现在“时间上的损失”和“功能上的损失”; e.g:部分用户双十一高峰期淘宝页面卡顿或降级处理;
Soft state 软状态
其实就是前面讲到的三态,既允许系统中的数据存在中间状态,既系统的不同节点的数据副 本之间的数据同步过程存在延时,并认为这种延时不会影响系统可用性;
e.g:12306 网站卖火车票,请求会进入排队队列;
e.g:12306 网站卖火车票,请求会进入排队队列;
Eventually consistent 最终一致性
所有的数据在经过一段时间的数据同步后,最终能够达到一个一致的状态; e.g:理财产品首页充值总金额短时不一致;
简介
ZooKeeper 致力于提供一个高性能、高可用,且具备严格的顺序访问控制能力的分布式协调 服务,是雅虎公司创建,是 Google 的 Chubby 一个开源的实现,也是 Hadoop 和 Hbase 的重 要组件。
设计目标
简单的数据结构
共享的树形结构,类似文件系统,存储于内存;
可以构建集群
避免单点故障,3-5台机器就可以组成集群,超过半数正常工作就能对
外提供服务;
外提供服务;
顺序访问
对于每个读请求,zk会分配一个全局唯一的递增编号,利用这个特性可以
实现高级协调服务
实现高级协调服务
高性能
3台机器的集群,可以提供读 13wQPS
使用场景
数据发布订阅
负载均衡
命名服务
Master选举
集群管理
配置管理
分布式锁
分布式队列
特性
会话
客户端与服务端的一次会话连接,本质是 TCP 长连接,通过会话可以进行心跳检测和数据传 输;
会话在整个运行期间内,在CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE这些会话状态间转换
一旦客户端开始创建 Zookeeper 对象,那么客户端状态就会变成 CONNECTING 状态, 同时客户端开始尝试连接服务端,连接成功后,客户端状态变为 CONNECTED,通常情况 下,由于断网或其他原因,客户端与服务端之间会出现断开情况,一旦碰到这种情况, Zookeeper 客户端会自动进行重连服务,同时客户端状态再次变成 CONNCTING,直到重新连 上服务端后,状态又变为 CONNECTED,在通常情况下,客户端的状态总是介于 CONNECTING 和 CONNECTED 之间。但是,如果出现诸如会话超时、权限检查或是客户端主动退出程序等情况,客户端的状态就会直接变更为 CLOSE 状态
数据模型
ZooKeeper 的视图结构和标准的 Unix 文件系统类似,其中每个节点称为“数据节点”或 ZNode,
每个 znode 可以存储数据,还可以挂载子节点,因此可以称之为“树”
每个 znode 可以存储数据,还可以挂载子节点,因此可以称之为“树”
注意
每一个 znode 都必须有值,如果没有值,节点是不能创建成功的。
节点类型
临时节点(ephemeral)
客户端断开链接,删除节点
分类
EPHEMERAL
EPHEMERAL_SEQUENTIAL(临时有序节点)
永久节点(persistent)
客户端断开连接,不删除节点
分类
PERSISTENT(默认)
PERSISTENT_SEQUENTIAL(永久有序节点)
节点属性
cZxid: 节点被创建的zxid值
致使ZooKeeper节点状态改变的每一个操作都将使节点接收到一个zxid格式的时间戳,并且这个时间戳全局有序。也就是说,也就是说,每个对节点的改变都将产生一个唯一的zxid。如果zxid1的值小于zxid2的值,那么zxid1所对应的事件发生在zxid2所对应的事件之前。
mZxid:节点被修改的zxid值
pZxid: 该节点的子节点列表最后一次被修改的zxid,修改节点内容不会变更此值
ctime: 节点被创建的时间
mtime:节点最后一次被修改的时间
version:节点被唏嘘个的版本号
cversion:节点所拥有子节点被修改的版本号
emphemeralOwner: 如果此节点为临时节点,那么它的值为这个节点拥有者的会话IID;否则,它的值为0
dataLength: 节点数据域的长度
numChildren
节点拥有的子节点个数
ACL(Access Control List)
表示为 scheme:id:permissions,第一个字段表示采用哪一种机制,第二个 id 表示
用户,permissions 表示相关权限(如只读,读写,管理等)。
用户,permissions 表示相关权限(如只读,读写,管理等)。
机制
world: 它下面只有一个 id, 叫 anyone, world:anyone 代表任何人,zookeeper 中对所有人有权 限的结点就是属于 world:anyone 的
auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持通过kerberos 来进行 authencation, 也支持 username/password 形式的 authentication)
digest: 它对应的 id 为 username:BASE64(SHA1(password)),它需要先通过 username:password 形式的 authentication
ip: 它对应的 id 为客户机的 IP 地址,设置的时候可以设置一个 ip 段,比如 ip:192.168.1.0/16, 表示匹配前16个bit的IP段
id
scheme 为 auth 时: username:password
scheme 为 digest 时: username:BASE64(SHA1(password))
scheme 为 ip 时: 客户端的 ip 地址。
scheme 为 world 时 anyone。
scheme 为 digest 时: username:BASE64(SHA1(password))
scheme 为 ip 时: 客户端的 ip 地址。
scheme 为 world 时 anyone。
Permission
CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这 5 种权限 简写为 crwda(即:每个单词的首字符缩写)
CREATE(c):创建子节点的权限
DELETE(d):删除节点的权限
READ(r):读取节点数据的权限 WRITE(w):修改节点数据的权限
ADMIN(a):设置子节点权限的权限
CREATE(c):创建子节点的权限
DELETE(d):删除节点的权限
READ(r):读取节点数据的权限 WRITE(w):修改节点数据的权限
ADMIN(a):设置子节点权限的权限
命令
服务器端命令
启动 ZK 服务: sh bin/zkServer.sh start
查看 ZK 服务状态: sh bin/zkServer.sh status
停止 ZK 服务: sh bin/zkServer.sh stop
重启 ZK 服务: sh bin/zkServer.sh restart
查看 ZK 服务状态: sh bin/zkServer.sh status
停止 ZK 服务: sh bin/zkServer.sh stop
重启 ZK 服务: sh bin/zkServer.sh restart
客户端命令
zkCli.sh -server 127.0.0.1:2181 连接到 ZooKeeper 服务
显示根目录下、文件:ls/使用ls命令来查看当前ZooKeeper中所包含的内容
显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode 节点“ zk ”以及与
它关联的字符串 [-e] [-s] 【-e 零时节点】 【-s 顺序节点】
获取文件内容:get /zk 确认 znode 是否包含我们所创建的字符串 [watch【] watch 监听】
修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
删除文件:delete/zk将刚才创建的znode删除,如果存在子节点删除失败
递归删除:rmr /zk将刚才创建的znode删除,子节点同时删除
退出客户端:quit
帮助命令:help
显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode 节点“ zk ”以及与
它关联的字符串 [-e] [-s] 【-e 零时节点】 【-s 顺序节点】
获取文件内容:get /zk 确认 znode 是否包含我们所创建的字符串 [watch【] watch 监听】
修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
删除文件:delete/zk将刚才创建的znode删除,如果存在子节点删除失败
递归删除:rmr /zk将刚才创建的znode删除,子节点同时删除
退出客户端:quit
帮助命令:help
ACL命令
getAcl
获取指定节点的 ACL 信息
create /testDir/testAcl deer # 创建一个子节点
getAcl /testDir/testAcl # 获取该节点的 acl 权限信息
create /testDir/testAcl deer # 创建一个子节点
getAcl /testDir/testAcl # 获取该节点的 acl 权限信息
setAcl
设置指定节点的 ACL 信息
setAcl /testDir/testAcl world:anyone:crwa # 设置该节点的 acl 权限
getAcl /testDir/testAcl # 获取该节点的 acl 权限信息,成功后,该节点就少了 d 权限 create /testDir/testAcl/xyz xyz-data # 创建子节点
delete /testDir/testAcl/xyz # 由于没有 d 权限,所以提示无法删除
setAcl /testDir/testAcl world:anyone:crwa # 设置该节点的 acl 权限
getAcl /testDir/testAcl # 获取该节点的 acl 权限信息,成功后,该节点就少了 d 权限 create /testDir/testAcl/xyz xyz-data # 创建子节点
delete /testDir/testAcl/xyz # 由于没有 d 权限,所以提示无法删除
addauth
注册会话授权信息
auth
addauth digest user1:123456 # 需要先添加一个用户
setAcl /testDir/testAcl auth:user1:123456:crwa # 然后才可以拿着这个用户去设置权限
getAcl /testDir/testAcl # 密码是以密文的形式存储的 create /testDir/testAcl/testa aaa
delete /testDir/testAcl/testa # 由于没有 d 权限,所以提示无法删除
退出客户端后:
ls /testDir/testAcl #没有权限无法访问
create /testDir/testAcl/testb bbb #没有权限无法访问
addauth digest user1:123456 # 重新新增权限后可以访问了
setAcl /testDir/testAcl auth:user1:123456:crwa # 然后才可以拿着这个用户去设置权限
getAcl /testDir/testAcl # 密码是以密文的形式存储的 create /testDir/testAcl/testa aaa
delete /testDir/testAcl/testa # 由于没有 d 权限,所以提示无法删除
退出客户端后:
ls /testDir/testAcl #没有权限无法访问
create /testDir/testAcl/testb bbb #没有权限无法访问
addauth digest user1:123456 # 重新新增权限后可以访问了
digest
auth 与 digest 的区别就是,前者使用明文密码进行登录,后者使用密文密码进行登录
create /testDir/testDigest data
addauth digest user1:123456
setAcl /testDir/testDigest digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:crwa 来设置权限
注意:这里如果使用明文,会导致该 znode 不可访问
create /testDir/testDigest data
addauth digest user1:123456
setAcl /testDir/testDigest digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:crwa 来设置权限
注意:这里如果使用明文,会导致该 znode 不可访问
通过明文获得密文
# 使用 digest
shell>
java -Djava.ext.dirs=/soft/zookeeper-3.4.12/lib -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider deer:123456
deer:123456->deer:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
# 使用 digest
shell>
java -Djava.ext.dirs=/soft/zookeeper-3.4.12/lib -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider deer:123456
deer:123456->deer:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
常用四字命令
ZooKeeper 支持某些特定的四字命令字母与其的交互。用来获取 ZooKeeper 服务的当前状态
及相关信息。可通过 telnet 或 nc 向 ZooKeeper 提交相应的命令 : 当然,前提是安装好了 nc
yum install nc
echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为 follower 或者 leader
使用 echo ruok|nc 127.0.0.1 2181 测试是否启动了该 Server,若回复 imok 表示已经启动。 echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
echo kill | nc 127.0.0.1 2181 ,关掉 server
echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信 息
echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个 与 watch 相关的会话的列表。
echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个 与 session 相关的路径。
及相关信息。可通过 telnet 或 nc 向 ZooKeeper 提交相应的命令 : 当然,前提是安装好了 nc
yum install nc
echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为 follower 或者 leader
使用 echo ruok|nc 127.0.0.1 2181 测试是否启动了该 Server,若回复 imok 表示已经启动。 echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
echo kill | nc 127.0.0.1 2181 ,关掉 server
echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信 息
echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个 与 watch 相关的会话的列表。
echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个 与 session 相关的路径。
日志可视化
java -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar:/soft/zookeeper-3.4.12/lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.LogFormatter log.1
java -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar:/soft/zookeeper-3.4.12/lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.SnapshotFormatter log.1
java -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar:/soft/zookeeper-3.4.12/lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.SnapshotFormatter log.1
客户端框架
原生客户端
依赖
使用
创建会话
基本操作
监听机制
认证机制
ZKClient
依赖
使用
基本操作
监听机制
Curator
依赖
使用
基本操作
监听机制
一致性协议
算法
两阶段提交(2PC)
本身是强一致性算法。类似对数据库的修改,修改会先到undo日志,记录数据本来的样子,然后执行事务修改操作,把数据写入redo日志中,如果事务失败,则从undo里恢复数据。
2PC借鉴这个思想。在分布式事务中,分为两个阶段。第一阶段叫准备阶段,事务的请求发送个一个个资源,他们分别执行自己的事务,写日志到undo和redo,但是不提交。当事务管理器收到所有资源的反馈,事务都执行没错后,事务管理器在发送commit指令,让资源把事务提交。一旦发现任何一个资源没有执行成功,事务管理器就会发送rollback,让所有资源回滚。
强一致性:需要保证任何一个资源都成功,整个分布式事务才会成功。
优点
原理简单,实现方便,保证强一致性
缺点
同步阻塞
在二阶段提交的过程中,所有的节点都在等待其他节点的响应,无法进行其他操作。这种同
步阻塞极大的限制了分布式系统的性能
步阻塞极大的限制了分布式系统的性能
单点问题
协调者在整个二阶段提交过程中很重要,如果协调者在提交阶段出现问题,那么整个流程将 无法运转。更重要的是,其他参与者将会处于一直锁定事务资源的状态中,而无法继续完成 事务操作。
数据不一致
假设当协调者向所有的参与者发送 commit 请求之后,发生了局部网络异常,或者是协调者 在尚未发送完所有 commit 请求之前自身发生了崩溃,导致最终只有部分参与者收到了commit 请求。这将导致严重的数据不一致问题。
容错性低
二阶段提交协议没有设计较为完善的容错机制,任意一个节点是失败都会导致整个事务的失 败。
三阶段提交(3PC)
背景:针对2PC问题的改进
三阶段
第一阶段:canCommit
确认所有资源是否都是健康,在线的。
优点
避免了提交请求时,因为单个资源的失效,导致其他资源等待的情况。
第二阶段:preCommit
每个资源都开始执行事务,记录undo,redo日志,但是不commit。事务执行成功,返回ack,否则返回no
第三阶段:doCommit
协调者发现所有事务提交者都正常执行事务后,给所有资源发送commit指令。
不同点
在协调者没给资源发送commit指令时,三阶段提交算法要求资源在一段时间后,会默认提交做commit操作。
优点
解决了单点故障问题
问题
同步阻塞,容错机制不完善等问题仍旧没有被解决。并且数据不一致问题更严重。
paxos算法
算法也分为两阶段。有两个角色:提议者和接收者。为避免单点问题,所有不可能只有一个提议者。避免一致性问题,所有的接收者对议题的看法也是不同的。
二阶段
第一阶段
提议者发起一个提议1,等待接收者的回复。如果回复的数目超过一半,则进入下一阶段。否则发起提议2,继续等待回复。直到回复数目超过一半才能进入下一阶段。
第二阶段
提议者执行提议内容,绝大多数接收者同意则执行完成。否则,继续回到第一阶段,发起提议。
核心
少数服从多数
zab算法
解决的问题和paxos算法一样,解决分布式系统数据一致性问题
zookeeper 就是根据 zab 协议建立了主备模型完成集群的数据同步(保证数据的一致性), 前面介绍了集群的各种角色,这说所说的主备架构模型指的是,在 zookeeper 集群中,只有 一台 leader(主节点)负责处理外部客户端的事务请求(写操作),leader 节点负责将客户 端的写操作数据同步到所有的 follower 节点中。
zab 协议核心是在整个 zookeeper 集群中只有一个节点既 leader 将所有客户端的写操作转化 为事务(提议 proposal).leader 节点再数据写完之后,将向所有的 follower 节点发送数据广 播请求(数据复制),等所有的 follower 节点的反馈,在 zab 协议中,只要超过半数 follower 节点反馈 ok,leader 节点会向所有 follower 服务器发送 commit 消息,既将 leader 节点上的数 据同步到 follower 节点之上。
场景
消息广播
正常情况下当客户端对 zk 有写的数据请求时,leader 节点会把数据同步到 follower 节点,这 个过程其实就是消息的广播模式
步骤
客户端发起一个写操作请求
Leader 服务器将客户端的 request 请求转化为事物 proposql 提案,同时为每个 proposal 分 配一个全局唯一的 ID,即 ZXID
leader 服务器与每个 follower 之间都有一个队列,leader 将消息发送到该队列
follower 机器从队列中取出消息处理完(写入本地事物日志中)毕后,向 leader 服务器发送 ACK 确认。
leader 服务器收到半数以上的 follower 的 ACK 后,即认为可以发送 commit
leader 向所有的 follower 服务器发送 commit 消息
问题
简化版的2PC协议,没有解决单点问题。单点问题需要 崩溃恢复解决。
崩溃恢复
在新启动的时候,或者 leader 节点奔溃的时候会要选举新的 leader,选好新的 leader 之后会 进行一次数据同步操作,整个过程就是崩溃恢复。
前提
服务器启动时
当leader服务器出现网络中断,崩溃或者重启的情况
当集群中已经不存在过半的服务器与leader服务器保存正常通信
要求
确保被Leader提交的proposal必须最终被所有的follower服务器提交。
当 leader 收到合法数量 follower 的 ACKs 后,就向各个 follower 广播 COMMIT 命令,同时也会在本地执行 COMMIT 并向连接的客户端返回「成功」。但是如果在各个 follower 在收到 COMMIT 命令前 leader 就挂了,导致剩下的服务器并没有执行都这条消息。、
解决办法
1、选举拥有 proposal 最大值(即 zxid 最大) 的节点作为新的 leader。
由于所有提案被 COMMIT 之前必须有合法数量的 follower ACK,即必须有合法数量的服务器的事务日志上有该提案的 proposal,因此,zxid最大也就是数据最新的节点保存了所有被 COMMIT 消息的 proposal 状态。
2、新的 leader 将自己事务日志中 proposal 但未 COMMIT 的消息处理。
3、新的 leader 与 follower 建立先进先出的队列, 先将自身有而 follower 没有的 proposal 发送给 follower,再将这些 proposal 的 COMMIT 命令发送给 follower,以保证所有的 follower 都保存了所有的 proposal、所有的 follower 都处理了所有的消息。通过以上策略,能保证已经被处理的消息不会丢。
由于所有提案被 COMMIT 之前必须有合法数量的 follower ACK,即必须有合法数量的服务器的事务日志上有该提案的 proposal,因此,zxid最大也就是数据最新的节点保存了所有被 COMMIT 消息的 proposal 状态。
2、新的 leader 将自己事务日志中 proposal 但未 COMMIT 的消息处理。
3、新的 leader 与 follower 建立先进先出的队列, 先将自身有而 follower 没有的 proposal 发送给 follower,再将这些 proposal 的 COMMIT 命令发送给 follower,以保证所有的 follower 都保存了所有的 proposal、所有的 follower 都处理了所有的消息。通过以上策略,能保证已经被处理的消息不会丢。
没被处理的事务请求不能再次出现
当 leader 接收到消息请求生成 proposal 后就挂了,其他 follower 并没有收到此 proposal,因此经过恢复模式重新选了 leader 后,这条消息是被跳过的。 此时,之前挂了的 leader 重新启动并注册成了 follower,他保留了被跳过消息的 proposal 状态,与整个系统的状态是不一致的,需要将其删除。
解决办法
Zab 通过巧妙的设计 zxid 来实现这一目的。
一个 zxid 是64位,高 32 是纪元(epoch)编号,每经过一次 leader 选举产生一个新的 leader,新 leader 会将 epoch 号 +1。低 32 位是消息计数器,每接收到一条消息这个值 +1,新 leader 选举后这个值重置为 0。
这样设计的好处是旧的 leader 挂了后重启,它不会被选举为 leader,因为此时它的 zxid 肯定小于当前的新 leader。当旧的 leader 作为 follower 接入新的 leader 后,新的 leader 会让它将所有的拥有旧的 epoch 号的未被 COMMIT 的 proposal 清除。
一个 zxid 是64位,高 32 是纪元(epoch)编号,每经过一次 leader 选举产生一个新的 leader,新 leader 会将 epoch 号 +1。低 32 位是消息计数器,每接收到一条消息这个值 +1,新 leader 选举后这个值重置为 0。
这样设计的好处是旧的 leader 挂了后重启,它不会被选举为 leader,因为此时它的 zxid 肯定小于当前的新 leader。当旧的 leader 作为 follower 接入新的 leader 后,新的 leader 会让它将所有的拥有旧的 epoch 号的未被 COMMIT 的 proposal 清除。
确保被选举出的leader不能包含未提交的proposal
新选举的leader节点中包含有最高的Zxid
步骤
选举出新的leader
集群中已经有过半机器完成了leader服务器的状态同步(数据同步)
退出崩溃恢复状态,进入消息广播模式
优势
二阶段提交的要求协调 者必须等到所有的参与者全部反馈 ACK 确认消息后,再发送 commit 消息。要求所有的参与 者要么全部成功要么全部失败。二阶段提交会产生严重阻塞问题,但 paxos 和 zab 没有这要 求。
为了进一步防止阻塞,leader 服务器与每个 follower 之间都有一个单独的队列进行收发消息, 使用队列消息可以做到异步解耦。leader 和 follower 之间只要往队列中发送了消息即可。如 果使用同步方式容易引起阻塞。性能上要下降很多
是对CAP理论,BASE理论的实现
集群
特点
顺序一致性
客户端的更新顺序与他们被发送的顺序相一致
原子性
更新操作要么成功,要么失败
单一视图
任何客户端连接到任意一个机器,都看到相同的zookeeper视图
可靠性
一旦一个更新操作被应用,在客户端再次更新此数据前,它的值不会改变
实时性
连接一台机器进行更新操作,其他所有的机器都会实时更新。不算完全的实时,有一点延迟
角色轮换避免单点故障
当leader出现问题的时候,会选举从follower中选举一个新的leader
角色
Leader
集群工作机制中的核心
职责
事务请求的唯一调度和处理者,保证集群事务处理的顺序性
集群内部各服务器的调度者(管理follower,数据同步)
Follower
集群工作机制中的跟随者
职责
处理非事务请求,事务请求转发给leader
参与事务请求proposal投票
参与leader选举投票
Observer
观察者
职责
3.30以上版本提供。和follower功能相同,但不参与任何形式投票
处理非事务请求,事务请求转发给leader
提高集群非事务处理能力
配置
Java客户端连接集群
领导选举
步骤
每个server发出一个投票
投票内容:(myid/sid,zxid)
myid:服务id
zxid:事务id
每个server接收其他server的投票
处理投票
优先检查zxid
zxid比较大的服务器优先作为leader
如果zxid相同,则比较myid
myid大的作为leader
重新投票
每个server根据处理后的投票结果重新投票
统计投票
判断是否有过半的集群接收到相同的投票信息
改变server状态
Leader修改状态为LEADING
Follower修改状态为FOLLOWING
算法分析
在3.4.0后的Zookeeper的版本只保留了TCP版本的FastLeaderElection选举算法
核心
每个server发出投票后,会收到其他机器的投票。每台机器根据一定的规则来处理收到的其他机器投票,并决定是否需要修改自己的投票。
术语
vote_sid: 接收到的投票中所推举Leader服务器的sid,也就是服务器id
vote_zxid:接收到的投票中所推举Leader服务器的ZXID
self_sid:服务器自己的SID
self_zxid:服务器自己的ZXID
规则
规则一:如果vote_zxid大于self_zxid,就认可当前收到的投票,并再次将该投票发送出去。
规则二:如果vote_zxid小于self_zxid,那么坚持自己的投票,不做任何变更。
规则三:如果vote_zxid等于self_zxid,那么就对比两者的SID,如果vote_sid大于self_sid,那么就认可当前收到的投票,并再次将该投票发送出去。
规则四:如果vote_zxid等于self_zxid,并且vote_sid小于self_sid,那么坚持自己的投票,不做任何变更
规则二:如果vote_zxid小于self_zxid,那么坚持自己的投票,不做任何变更。
规则三:如果vote_zxid等于self_zxid,那么就对比两者的SID,如果vote_sid大于self_sid,那么就认可当前收到的投票,并再次将该投票发送出去。
规则四:如果vote_zxid等于self_zxid,并且vote_sid小于self_sid,那么坚持自己的投票,不做任何变更
通常服务器的数据越新,ZXID越大,成为leader的可能性越大,也就越能保证数据的恢复。如果zxid相同,则sid越大机会越大。
详解
服务器状态
LOOKING
寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。
FOLLOWING
跟随者状态。表明当前服务器角色是Follower。
LEADING
领导者状态。表明当前服务器角色是Leader。
OBSERVING
观察者状态。表明当前服务器角色是Observer。
投票数据结构
id:被推举的Leader的SID。
zxid:被推举的Leader事务ID。
electionEpoch:逻辑时钟/选举轮次,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加1操作。
peerEpoch:被推举的Leader的epoch。
state:当前服务器的状态
选举轮次,也就是逻辑时钟,即logicalclock。这个值,不会频繁变化,一次选举,自增一次。一次选举过程中,可能包括多次投票,投票不涉及逻辑时钟的自增。
一般情况下,逻辑时钟是相同的。但是某些机器崩溃后,可能出现逻辑时钟不一致的情况。出现这种情况时,需要请求错误逻辑时钟机器的内部投票数据,因为这些数据是过时的。
场景
加入一台新的机器到集群中
集群中已经只有Leader
与Leader集群建立连接,进行状态同步
集群中没有Leader
开始正常的选举步骤
常见面试题
ZAB协议是什么
是为zk专门设计的一种解决数据一致性的协议。包括两种模式:崩溃恢复和消息广播。当整个 zookeeper 集群刚刚启动或者 Leader 服务器宕机、重启或者网络故障导致不存在过半 的服务器与 Leader 服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先 选举产生新的 Leader 服务器,然后集群中 Follower 服务器开始与新的 Leader 服务器进行数 据同步,当集群中超过半数机器与该 Leader 服务器完成数据同步之后,退出恢复模式进入 消息广播模式,Leader 服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理。
Znode有哪几种类型
永久节点
永久顺序节点
临时节点
临时顺序节点
ACL权限控制机制
权限模式(Schema)
IP,World,Digest, Super
授权对象
如ip地址
权限
crwad
ZK角色
Leader
事务请求的唯一调度和处理者,保证事务处理的顺序性
负责集群中各服务的调度
Follower
处理客户端的非事务请求,事务请求发送给Leader处理
参与事务请求的投票
参与Leader选举的投票
Observer
处理客户端的非事务请求,事务请求发送给Leader处理
提升非事务处理能力
不参与任何投票
ZK Server的工作状态有哪些
LOOKING
FOLLOWING
LEADING
OBSERVING
ZK的watch机制是否永久
不是,只能一次
ZK的常见客户端有哪些
原生:Zookeeper
zk自带的zkclient
Apache提供的Curator
分布式锁用ZK怎么实现
使用临时有序节点,未获得锁的线程监视前一个有序节点,前一个节点释放锁后,会删除节点,然后阻塞的线程节点可以获取到节点
ZK默认的通信框架是什么
Nio,可以修改为Netty
消息广播的流程
1、Leader 接收到消息请求后,将消息赋予一个全局唯一的 64 位自增 id,叫做:zxid, 通过 zxid 的大小比较即可实现因果有序这一特性。
2、Leader 通过先进先出队列(通过 TCP 协议来实现,以此实现了全局有序这一特性)将带 有 zxid 的消息作为一个提案(proposal)分发给所有 follower。
3、当 follower 接收到 proposal,先将 proposal 写到硬盘,写硬盘成功后再向 leader 回一个 ACK。
4、当 leader 接收到合法数量的 ACKs 后,leader 就向所有 follower 发送 COMMIT 命令,会在本地执行该消息。
5、当 follower 收到消息的 COMMIT 命令时,就会执行该消息
2、Leader 通过先进先出队列(通过 TCP 协议来实现,以此实现了全局有序这一特性)将带 有 zxid 的消息作为一个提案(proposal)分发给所有 follower。
3、当 follower 接收到 proposal,先将 proposal 写到硬盘,写硬盘成功后再向 leader 回一个 ACK。
4、当 leader 接收到合法数量的 ACKs 后,leader 就向所有 follower 发送 COMMIT 命令,会在本地执行该消息。
5、当 follower 收到消息的 COMMIT 命令时,就会执行该消息
领导选举的流程
步骤
每个server发出一个投票
投票内容:(myid/sid,zxid)
myid:服务id
zxid:事务id
每个server接收其他server的投票
处理投票
优先检查zxid
zxid比较大的服务器优先作为leader
如果zxid相同,则比较myid
myid大的作为leader
重新投票
每个server根据处理后的投票结果重新投票
统计投票
判断是否有过半的集群接收到相同的投票信息
改变server状态
Leader修改状态为LEADING
Follower修改状态为FOLLOWING
ZK如何保证数据的一致性
通过投票算法,一般以上回复,则写入数据。使用zab协议
ZK如何保证高可用
集群模式,集群中有超过一半的集群存活就可以正常提供服务。
0 条评论
下一页