zookeeper

1.zooker的选举原理
第一、看有没有leader;如果有正常工作(如何工作?见下一个问题。),如果没有就选举leader.
第二、如何选举leader? 先比较zxid,然后比较serverId(大的优先)。如果有5个机器,在选票没有过半的情况下,会一直选举直到某一台机器获得超过半数以上的选票。
投票过程:最开始,他们都会选择自己,但是会相互比较zxid和server中的MYId,如果自己小那么就改投到选票到大的那一个,直某一个台机器获取半数以上的选票。
这是looking状态,选举完毕就是
备注:zxid相当于版本号,每次改写就会有新的zxid产生,大的比较新。
2.zookeepr写原理?如何工作?
第一、client向zookeeper发起写请求 服务器获取到写请求,然后送到leader;
第二、leader收到以后将写请求编写一个zxid的 编号,zookeeper发起写请求提议,收到的server会将写请求放到写队列中并且回复,然后如果leader收到半数以上同意票,leader就会向各个server发送提交信息,然后之前同意的server开始写数据,不同意的sever自杀重启然后向leader同步数据。
什么情况下,server会不同意呢?——如果leader发送的zxid比server的最新的zxid大那么就会同意,如果小就不同意(也就是说server已经写过了,他觉得自己数据更加新)这种情况下:网络情况复杂的时候,比如丢包、延迟。zxid 有可能晚到
第三、如果leader收到大多数的发对票,那么他会自己也会重启(少)。
3.zookeeper的监听原理
第一步、在main()线程中创建zk客户端,这时zkclient会创建两个线程,一个connect一个listener;
第二步:connect将注册的监听事件发送给zookeeper;zk会将注册事件添加到注册监听器列表中并且监听
第三步:如果监听到路径或者数据发生改变,就会将这个消息发送到listener线程,listener就会回调process方法。
4.部署模式与角色?至少的数量。
(1)部署方式单机模式、集群模式
(2)角色:Leader和Follower
(3)集群最少需要机器数:3
5.常用命令
ls create get delete set…
public class Get_Child_Change {
public static void main(String[] args) throws InterruptedException {
//获取到zkClient
final ZkClient zkClient = new ZkClient(“linux121:2181”);
//zkClient对指定⽬录进⾏监听(不存在⽬录:/lg-client),指定收到通知之后的逻辑
//对/lag-client注册了监听器,监听器是⼀直监听
zkClient.subscribeChildChanges(“/lg-client”, new IZkChildListener() {
//该⽅法是接收到通知之后的执⾏逻辑定义
public void handleChildChange(String path, List childs)
throws Exception {
//打印节点信息
System.out.println(path + " childs changes ,current childs " +
childs);
}
});
//使⽤zkClient创建节点,删除节点,验证监听器是否运⾏运⾏结果:
结果表明:
客户端可以对⼀个不存在的节点进⾏⼦节点变更的监听。
⼀旦客户端对⼀个节点注册了⼦节点列表变更监听之后,那么当该节点的⼦节点列表发⽣变更时,服务
端都会通知客户端,并将最新的⼦节点列表发送给客户端
 该节点本身的创建或删除也会通知到客户端。
5. 获取数据(节点是否存在、更新、删除
zkClient.createPersistent(“/lg-client”);
Thread.sleep(1000); //只是为了⽅便观察结果数据
zkClient.createPersistent(“/lg-client/c1”);
Thread.sleep(1000);
zkClient.delete(“/lg-client/c1”);
Thread.sleep(1000);
zkClient.delete(“/lg-client”);
Thread.sleep(Integer.MAX_VALUE);
/*
1 监听器可以对不存在的⽬录进⾏监听
2 监听⽬录下⼦节点发⽣改变,可以接收到通知,携带数据⼦节点列表
3 监听⽬录创建和删除本身也会被监听到
*/
}
6.实践
6.1 服务器动态上下线监听

ServerMain
-----connectZK():
-----registerServerInfo()
-----main():先调用 connectZK()方法获取zk对象,在调用registerServerInfo注册信息到zk节点,最后利用TimeServer 利用TCP套接字接受信息返回时间

TimeServer
----TimeServer():接受port
----run():利用TCP套接字接受信息返回时间

Client
------connectZk():获取zk
------sendRequest(): 从zk中监听data变化,如果变化那么就获取最新的ip和port,然后发送tcp套接字请求最新时间并且接受返回的bytes
-------main():获取zk对象,发送请求

6.2 利用zookeeper实现分布式锁的流程

DisLockTest
—main():启动10个线程模拟分布式的client,他们都去抢锁,抢锁的流程写在run方法中。由于抢锁流程无法复杂,所以又单独开了一个类DisClient,让他去实现每个客户端来抢锁的流程,调用他的getDisLock()方法;然后解除锁调用他的deteteLock()方法。

DisClient
-----DisClient():这个是类的实例化,在实例化的时候创建目录:“/distrilock”;为防止多次创建导致数据丢失或者异常,所以加了一个同步锁,里面判断是否为空,空则建立。
-----getDisLock():这个是DisClient对象获取同步锁的方法,这部分主要分为两个部分,一个是尝试获取锁(tryGetLock()),如果成功(返回true)就结束,再后面的代码应该是业务逻辑,故没有实现)失败就开始第二步即等待锁(waitForLock())(最后等待完毕,还要再递归调用自己开始一样的流程)。整个过程是递归调动,即先尝试获取锁,然后等待锁,如果等待锁被通知那么就可以继续尝试获取锁。
-----tryGetLock():首先判断对象的CurrentNodePath是否存在,不存在的话就在zk上创建注册,首先判断自己是不是最小的,如果是代表自己是最小的,那么返回true开始业务逻辑;否则算出自己前面节点并且赋值给属性便于waitForLock()操作,并且返回false
-----waitForLock():监听前面一个节点并且利用同步工具类CountDownLatch.await()等待阻塞,如果前一个节点被删除那么就监听到了之后CountDownLatch.countdown减一,解除等待阻塞,那么便结束了,然后当然解除监听。
-----deteteLock():delete删除节点,释放锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值