title: Zookeeper闲谈
date: 2018-02-27 10:11:16
tags:
前面应该还是有有关zk的master选举相关的内容,等有空再补一下
Zk中的专业术语
epoch周期值acceptedEpoch(比喻:年号):follower已经接受leader更改年好的(newepoch)提议。currentEpoch(比喻:当前的年号):当前的年号lastZxid:history中最近接收到的提议zxid(最大的值)history:当前节点接受到事务提议的log
4.ZkClient
- 优点1:递归创建
- 优点2:递归删除
- 优点3:避免不存在异常
ZkClient注册事件:
原文demo在com.dongnao.demo.client下
subscribeChildChanges/unsubscribeChildChanges(节点变化)subscribeDataChanges/unsubscribeDataChanges(数据变化)
Curator
原文demo在com.dongnao.demo.curator下
curator连接ZK应用最广泛的工具。
- zk应用场景(分布式锁,Master选举等等),curator包含了这些场景。
- 2. 应用场景出现极端的情况下,curator考虑。
Backoff退避算法:
- 重试一次,如果网络出现阻塞。
22:25 request1(block) 22:26 request2(毫无意义) 22:27 request3(毫无意义) 22:28 request4(通顺)request2、3、4
- 数间隔重试,比如第一次1分钟,第二次2分钟......随着时间的推移,重试间隔越长。
重点:Curator时间监听:
NodeCache:节点处理监听(会使用缓存)。回调接口NodeCacheListenerPathChildrenCache:子节点缓存,处理子节点变化。回调接口PathChildrenCacheListenerTreeCache:NodeCache和PathChildrenCache的结合体。回调接口TreeCacheCacheListener
5.Zookeeper实现分布式锁
2018年1月31日
缺点:“惊群效应”
2018年1月31日更新
关于订单类com.dongnao.demo.lock.OrderServiceImpl
中的分布式锁com.dongnao.demo.lock.ImproveLock的相关解释
在OrderServiceImpl的业务场景中申明了CountDownLatch线程计数器,以及模拟了100个线程并发的情况在分布式锁ImproveLock中tryLock(),如果currentPath为空则为第一次尝试加锁,第一次加锁赋值currentPath:如果currentPath等于当前建立的第一个临时顺序节点:0000000400,返回true加锁成功如果当前节点在所有节点中排名中不是排名第一,则获取前面的节点名称,并赋值给beforePath,返回Lock()中等待waitForLock(),在waitForLock(),设置beforePath监听器监听subscribeDataChanges===>IZkDataListener可以解决惊群效应
有些分布式系统master-slave,master是一个单节点(备份master-back)。 实际的案例:Hadoop(NameNode、ResourceManager),普通的部署NameNode、ResourceManager仅仅是单节点。Hadoop HA(NameNode和ResourceManager有多个备份) 说明:统一的一个临时节点:ActiveOrStandByLock(/distibuted_system/ActiveOrStandByLock仅仅这样一个节点) 第一步:zk有这样一个持久节点/distibuted_system 第二步:master1和master2同时启动,同时向向/distributed_system这个节点申请创建临时子节点ActiveOrStandByLock(同一时间只有一个请求能够创建成功)。 如果master1创建成功,这个节点(ActiveOrStandByLock)就不允许master2创建(锁的机制) master1:active===》真正的master。路径:/distributed_system/ActiveOrStandByLock master2:改为standby(master-back)。 同时对/distributed_system/ActiveOrStandByLock注册事件监听。 第三步:master1挂掉或者超过一定时间。节点会被删除(事件机制就会起作用),就会通知master2,master2就会在/distributed_system/ActiveOrStandByLock,同时修改状态为active。 备注:假如master1并没有挂掉,只有由于网络延时导致,当网络顺畅的时候就会出现“脑裂”状态。都认为自己是active。 解决脑裂的办法:对/distributed_system/ActiveOrStandByLock加一个权限ACL控制。master1对于这个节点/distributed_system/ActiveOrStandByLock没有权限。自己把状态改成standby。
Election的实现FastLeaderElection选举类源码分析
QuorumCnxManager:主要完成服务器间的网络交互 senderWorkerMap 主要用于发送 queueSendMap主要用于发送 SendWorker用于发送器,底层连接的 RecvWorker用于接收器 lastMessageSent最后一条发送的消息 QuorumPeer 半数对等协议,在初始化的过程中出现,饱含选举IP地址 选举port等状态Notification:表示服务器节点收到的选票信息 version: leader:Proposed leader zxid:zxid of the proposed leader electionEpoch:Epoch QuorumPeer.ServerState:LOOKING, FOLLOWING, LEADING(广播状态), OBSERVING; sid:Address of sender peerEpoch:epoch of the proposed leaderlookForLeader(): recvset:存储本节点来自其他节点的选票(投票用) outofelection:存储本节点从其他节点由following、leading状态发送来的选票(选举确认用) updateProposal(参与者的选票,最后的logger的zxid,返回当前的年号):更新选票,第一次投票给自己 sendNotifications();放置发送队列中 循环...(选举没有stop) recvqueue.poll():获取到一张消息 进行检查: 网断 发送队列为0 重连所有的socket连接 tmpTimeOut退避策略*2 self.getVotingView().containsKey(n.sid):是否包含当前的sid: LOG.warn(发送自不在本集群的消息) Notification消息的状态: LOOKING: n.electionEpoch > logicalclock: logicalclock = n.electionEpoch; recvset.clear(); totalOrderPredicate():投票对比:周期Epoch大||Zxid大||myid: updateProposal()跟新选票成为本地的选票 sendNotifications()发送队列 n.electionEpoch < logicalclock: ignore n.electionEpoch = logicalclock: 对比totalOrderPredicate() pdateProposal(); sendNotifications(); recvset.put():将选票放置进收件箱 termPredicate():是否要结束选举 vote.equals(votes):遍历选票 containsQuorum(set):过半监测 校验/返回endVote选票 FOLLOWING: LEADING: 前头的半数检测协议 checkLeader(): leader的状态 比较周期 构造新选票并且返回
Vote 选票
****
QuorumPeer 是zk服务器实例类
QuorumPeer.QuorumServer 存储zk server连接信息
主要实现函数:
lookForLeader:选举过程(主要函数)
totalOrderPredicate:比较选票
termPredicate:是否结束选举
senderWorkerMap:主要用于发送
queueSendMap:发送队列
SendWorker:发送器
RecvWorker:接收器
lastMessageSent:最后一条发送消息
Notification:表示该服务器节点收到选票信息
recvset:存储本节点来自其他节点的选票(投票用)
outofelection:存储本节点从其他节点由following、leading状态发送来的选票(选举确认用)
Zookeeper Master选举
2018年1月31日
- 用Tomcat模拟一个实现Master选举过程(应用tomcat 阀com.dongnao.demo.election.ZkTomcatValve)
- 使用acl处理脑裂的代码
Zookeeper基本模型
- 持久节点(除非主动删除,zk不会做清理工作)
- 临时节点(随着session会话消亡,而消亡)
- 持久顺序节点
- 临时顺序节点
数据模型——节点
树模型(采用文件系统的形式,只不过去掉文件和目录),叫数据节点。
ACL——权限控制
org.apache.zookeeper.ZooDefs.Ids
对于一个节点可操作的权限有5种:
READ(只读)WRITE(只写)CREATE(创建)DELETE(删除)ADMIN(节点管理权限)(对节点的删除和创建的权限)
- 1. world:开放模式。意思所有人都可以访问。
- 2. IP: 针对某个开放权限
- 3. digest:用户/密码模式
- 4. Super:超级用户模式
使用密文:
setAcl path digest|ip:username:password:c|d|r|w|a
密文生成org.apache.zookeeper.server.auth.DigestAuthenticationProvider使用明文:
addauth digest username:passwordsetAcl /path auth:username:password:cdrwa
删除节点的bugrmr / delete
密文命令(执行目录在zk根目录):
java -cp ./zookeeper-3.4.6.jar:./lib/log4j-1.2.16.jar:./lib/slf4j-api-1.6.1.jar:./lib/slf4j-log4j12-1.6.1.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider user1:12345
版本
cversion 当前节点的权限
dataversion 当前节点数据内容的版本号
aclVersion 就是ACL版本号
zookeeper版本的含义:版本指的是变更的次数。
CAS(compare and swap)比较然后交换。
Watcher
org.apache.zookeeper.ZooKeeper
org.apache.zookeeper.Watcher
org.apache.zookeeper.server.DataTree
客户端:
Zookeeper (getChild)CliencnxnWatchRegistrationSendThreadPacket(creatBB经过处理,简单化)ZKWatchManager
服务端:
FinalRequestProcessorWatchManager(triggerWatcher)SendThread.readResponseEventThread
2018年2月1日 内容:zookeeper的事件监听的机制源码分析
ps:也是似懂非懂蒙蔽中
Zookeeper Class中的构造方法中我们可以看到
会传入一个Watch的一个事件监听体系
接下来,进入到submitRequest()中,
话分两头单表一支
封装的packet会进行线程中发送
在这个SendThread是完全的继承自java的Thread线程
在这个方法中是将前面的Packet封装的具体实现,并且是在同步块中会将outgoingqueue进行输出
其中底层的实现还是NIO通信
但是还是由于并发的信息量过大的缘故,所以还需要进行再次反序列化以及进行封装
createBB的具体的实现
到了finnish阶段,会存储到ClientWatchManager中的三个map中
在线程处理阶段会对操作数进行判断处理
已getData操作进行验证,
在完成事件中添加触发的机制
在sendThread中的readermeResponse中添加回调判断已经执行的操作数,并且在event中的EventThread中进行性处理
添加时间监听机制在判断完操作数
在EventThread中对事件进行处理
閱讀更多 Java程序猿鼓勵師 的文章