什么是zk
Zookeeper是分布式应用程序的协调服务框架,是Hadoop的重要组件。ZK要解决的问题:
-
分布式环境下的数据一致性。 -
分布式环境下的统一命名服务
- 分布式环境下的配置管理
-
分布式环境下的分布式锁 -
统一集群管理
6.软负载均衡
? 软负载均衡指的是,zk记录了管理的服务中的cnt,每次都会将请求分发到cnt最小的那个服务节点。实现了软负载均衡
zk的工作机制
server会在zk上注册节点,创建的一般都是临时节点
Client会在连接上zk后获取server注册的节点信息,并且注册监听器,如果监听到节点消失后,zk就会通知clinet的listen进程,调用process
zk的特点
集群必须半数以上才能存活,所以zk集群最少都需要3台服务器
zk的数据结构
-
ZK有一个最开始的节点 -
ZK的节点叫做znode节点 (每一个znode默认能存储1mb的数据) -
每个znode节点都可存储数据 -
每个znode节点都可创建自己的子节点 -
多个znode节点共同形成了znode树 -
Znode树的维系实在内存中,目的是供用户快速的查询 -
每个znode节点都是一个路径(通过路径来定位这个节点) -
每个路径名都是唯一的。
Stat结构体
-
czxid-创建节点的事务 zxid 每次修改 ZooKeeper 状态都会收到一个 zxid 形式的时间戳,也就是 ZooKeeper 事务 ID。 事务 ID 是 ZooKeeper 中所有修改总的次序。每个修改都有唯一的 zxid,如果 zxid1 小 于 zxid2,那么 zxid1 在 zxid2 之前发生。 -
ctime-znode 被创建的毫秒数(从 1970 年开始) -
mzxid-znode 最后更新的事务 zxid -
mtime-znode 最后修改的毫秒数(从 1970 年开始) -
pZxid-znode 最后更新的子节点 zxid -
cversion-znode 子节点变化号,znode 子节点修改次数 -
dataversion-znode 数据变化号 -
aclVersion-znode 访问控制列表的变化号 -
ephemeralOwner- 如果是临时节点,这个是 znode 拥有者的 session id。如果不是临时节 点则是 0。 -
dataLength- znode 的数据长度 -
numChildren-znode 子节点数量
zk节点的4种类型
-
普通持久节点: -
普通临时节点:创建此临时节点的客户端失去和zk连接后,此节点消失,zk是通过临时节点监控哪个服务器挂掉的。 -
顺序持久节点:会根据用户指定的节点路径,自动分配一个递增的顺序号。(顺序节点实现分布式锁的效果,服务器1抢到zk05分配zk050001,服务器2抢到zk05分配zk050002) ? create –s -e /zk05 abcd --> zk050000000003 ? 再创建一个就是:zk050000000004 -
顺序临时节点:结合了顺序节点和临时节点的特征
zk的常用命令
zk的选举机制
事务
- 每一个创建节点、修改节点、删除节点操作都是一个事务,每一个事务都用一个事务id来代表,叫:zxid
- zxid 是全局唯一,并且全局递增的。作用就是可以根据最大事务id,找到最新的事务。
事务体检了Paxos算法中的写流程的序列号
fllower会检查下一步将到来的建议的序列号,以分辨是否准备接受这个新值,所有流程都是这样消除歧义,共识由此达成。
选举
选举分为两个阶段
-
数据恢复阶段 zk服务器启动时,会先从本地磁盘找到本机的最大事务id -
选举协议
- 首先比较最大的事务id (zxid),大的当领导
- 如果事务id比较不出来,看myid,大的当领导
- 逻辑时钟值,记录当前的选举轮数,确保每个zk在同一个轮选举中
- 当前zk服务器状态,分4种: Looking=>选举阶段 Following=>当小弟阶段 Leading=>当领导阶段 Observering=>观察者阶段
-
leader选举之后会原子广播 目的:leader身上一般是有最新数据的(有最大的事务id),所以首先做的就是原子广播(通过原子广播端口 2888 3888),为了保证多台zk数据一致性以及防止leader挂掉之后,数据的丢失问题 https://blog.csdn.net/mayp1/article/details/51871761
例子:
- 服务器 1 启动,此时只有它一台服务器启动了,它发出去的报文没有任何响应, 所以它的选举状态一直是 LOOKING 状态。
- 服务器 2 启动,它与最开始启动的服务器 1 进行通信,互相交换自己的选举结果, 由于两者都没有历史数据(没有事务id),所以myid 值较大的服务器 2 胜出,但是由于没有达到超过半数以 上的服务器都同意选举它(这个例子中的半数以上是 3),所以服务器 1、2 还是继续保持 LOOKING 状态。
- 服务器 3 启动,根据前面的理论分析,服务器 3 成为服务器 1、2、3 中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的 Leader。
- 服务器 4 启动,根据前面的分析,理论上服务器 4 应该是服务器 1、2、3、4 中最 大的,但是由于前面已经有半数以上的服务器选举了服务器 3,所以它只能接收当小弟的命 了。
- 服务器 5 启动,同 4 一样当小弟。
服务器配置
半数机制, 安装奇数台 10 台服务器几台: 3 台 20 台服务器几台: 5 台 100 台服务器几台: 11 台 不是越多越好, 也不是越少越好。 如果多, 通信时间长, 效率低; 如果太少, 可靠性差。
zk选举的算法相关
zk的选举机制根据Paxos 算法来实现。 Paxos算法解决的问题:在分布式环境下就某一个决议达成一致性问题。 Paxos算法存在活锁问题,Zk用的是Fast Paxos算法,解决了活锁问题。
paxos算法详解:https://www.jdon.com/artichect/paxos.html
拓展:
死锁:死锁是有线程拿到资源,但相互等待互不释放造成死锁
活锁:在程序里,由于某些条件的发生碰撞,导致重新执行,再碰撞=》再执行,如此循环往复,就形成了活锁。活锁的危害:多个线程争用一个资源,但是没有任何一个线程能拿到这个资源。(死锁是有一个线程拿到资源,但相互等待互不释放造成死锁),活锁 是死锁的变种。补充:活锁更深层次的危害,很耗尽Cpu资源(在做无意义的调度)
观察者模式
为了提高ZK性能,处理思想就是减少投票人数。(前提是满足过半机制),由此,zk引出了观察者模式。
观察者特点:
-
不参与投票(选举的投票以及事务更新的投票) -
观察者会跟随最后的投票结果
补充说明
配置观察者,一定要满足过半机制,比如5个zk服务器,至多只能配置两个观察者 为了确保zk服务集群的健壮性,建议不要配置观察者或者少配置观察者,如果是从从性能来看,可以配置观察者。
zk保证了CP
CAP理论告诉我们,一个分布式系统不可能同时满足以下三种
一致性(C:Consistency)
可用性(A:Available)
分区容错性(P:Partition Tolerance)
这三个基本需求,最多只能同时满足其中的两项,因为P是必须的,因此往往选择就在CP或者AP中。
在此ZooKeeper保证的是CP
分析:可用性(A:Available)
不能保证每次服务请求的可用性。任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。所以说,ZooKeeper不能保证服务可用性。
进行leader选举时集群都是不可用。在使用ZooKeeper获取服务列表时,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。所以说,ZooKeeper不能保证服务可用性。
监听器原理(watch机制)
写数据流程
zookeeper虽然使用了ZAB原子广播算法,但是其也是由Paxos衍生而来的。
zookeeper为什么不直接与leader通信呢?
==Paxos能保证客户端发送它们的写请求到Paxos集群中任何成员, 客户端会随机挑选任意一个集群中的成员节点,这种方式是重要且巧妙的,意味著没有任何单点风险,意味着我们的Paxos管治系统能继续保持在线可用,无论任何一个节点当机或其他不可用原因无响应。==如果我们设计一个特定节点作为“推荐人proposer”或者 “the master” 等, 如果这个主节点死机,那么整个系统就崩溃了。
zk应用场景
-
实现消息订阅和发布实现思路 创建一个znode节点 /data 其他订阅节点监听/data节点的数据变化事件 如果有事件发生,就获取/data节点的数据 -
实现集群整体的配置信息管理
? 比如某一个机器的配置信息发生变化,其他机器的配置信息也实现同步更改,实现总思路同上
-
集群管理:能够快速检测出集群里节点的状态 (创建临时节点+监听机制) -
实现集群的负载均衡:
? 利用zk检测到每台的机器的负载情况,指标是:cpu和内存。
? 每台客户端定期将自己的负载情况指标发给zk
? zk根据收集到指标后,根据负载情况做相关业务控制
- 实现命名服务
zk不适合做的事情
不能用zk存储大量数据,znode树维系在内存中的,如果数据大,会吃掉大量的内存
zk的特性
-
一致性(单一视图):不同的zookeeper查询的数据都是一样的 (CAP中的C) -
原子性:要么都成功,要么都失败 -
可靠性:一旦成功的应用一个事务,变更将会一直保留下来 -
实时性:保证客户端在非常短的时间内获取服务器的更新信息 -
顺序性:根据命令版本号来实现 -
过半性:zookeeper集群的数量最好是奇数个
zk的脑裂
什么是脑裂?
在管理集群里,出现两个Leader的状况,造成数据混乱,造成整个集群出现问题。
脑裂问题是不可控和不可模拟的。出现脑裂问题的根源是选举机制, 并且普遍存在于Master-Slave架构里。
如何预防脑裂?
为选举的leader分配递增id,根据id的大小判断是否老leader或者新leader,如果老leader,就不接受其指令。
Flume 采集数据会丢失吗?
理论上不会, Channel 存储可以存储在 File 中, 数据传输自身有事务
– by 俩只猴
|