模拟leader选举:
1、zookeeper服务器上有一个/leader节点
2、在/leader节点下创建短暂顺序节点/leader/lock-xxxxxxx
3、获取/leader的所有子节点并注册监听
4、拿自己的顺序号跟其他子节点的顺序号比较,如果自己的是最小的则获得leader
5、监听到/leader子节点发生变化则执行步骤3、 4尝试获取leader
 
Client .java 
package leader;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
/**
* 模拟leader选举
*
* 1、zookeeper服务器上有一个/leader节点
* 2、在/leader节点下创建短暂顺序节点/leader/lock-xxxxxxx
* 3、获取/leader的所有子节点并注册监听
* 4、拿自己的顺序号跟其他子节点的顺序号比较,如果自己的是最小的则获得leader
* 5、监听到/leader子节点发生变化则执行步骤3、 4尝试获取leader
*
*/
public class Client { public static final String HOSTS = "hadoop1:2181";
public static final String LEADER_PATH = "/leader"; private String path = null; public void run() throws Exception {
ZooKeeper zk = ZKUtils.open(HOSTS);
path = zk.create(LEADER_PATH + "/lock-", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); getLeader(zk); TimeUnit.DAYS.sleep(1);
}
private void getLeader(final ZooKeeper zk)
throws KeeperException, InterruptedException {
//获取/leader下的所有子节点
//注册/leader子节点观察
List<String> children = zk.getChildren(LEADER_PATH, new Watcher() {
@Override
public void process(WatchedEvent event) {
//如果/leader子节点发生变化,则再进行一次getLeader
if(event.getType().equals(EventType.NodeChildrenChanged)) {
try {
getLeader(zk);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}); //拿自己的顺序号跟/leader所有子节点的顺序号比较,如果是最小的则拿到leader
long seq = getSeq(path);
boolean isMin = true;
for (String child : children) {
long childSeq = getSeq(child);
if(childSeq < seq) {
isMin = false;
break;
}
}
if(isMin) {
System.out.printf("我拿到锁了, path: %s, thread: %s", path, Thread.currentThread().getName() );
}
} public long getSeq(String path) {
return Long.parseLong(path.split("-")[1]);
}
}

  

Test .java

package leader;
public class Test {
//多次执行这个类,模拟多个客户端竞选leader
public static void main(String[] args) throws Exception {
new Client().run();
}
}

  

其实在上面的实现中存在几个问题:

1、羊群效应
    在上面的实现中,监听的是/leader的子节点变化,每当一个子节点添加或删除的时候都会通知所有客户端(客户端监听了子节点变化),客户端开始竞争leader,如果客户端成百上千个,这样形成了瞬间峰值流量,对zookeeper服务器造成压力。
    而其实,并不是所有的客户端都需要对某个子节点变化进行处理,服务器只需要通知被删除节点的下一个节点即可,而添加新节点不需要通知客户端。
 
2、重试问题
    客户端在创建暂时顺序节点时不能处理因连接丢失导致的失败,因为客户端没法知道create操作是成功还是失败,create操作不是幂等操作(多次create会创建多个节点),不能进行重试。
    解决方法是给将要创建的节点一个标识符,以表明是我这个客户端创建的,通常使用sessionid来标识,最终创建的节点名称形如lock-<sessionid>-<sequenceNumber>,重试时,查询/leader是否存在包含<sessionid>的子节点,没有再创建。
 
    由此可见,创建高效可靠的分布式锁是多么的困难,zookeeper的recipes目录下有个WriteLock锁实现,在生产环境下也可使用。
 
 
参考资料:《Hadoop权威指南(第二版)》

zookeeper应用 - leader选举 锁的更多相关文章

  1. 【分布式】Zookeeper的Leader选举

    一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...

  2. 简单理解Zookeeper的Leader选举【转】

    Leader选举是保证分布式数据一致性的关键所在.Leader选举分为Zookeeper集群初始化启动时选举和Zookeeper集群运行期间Leader重新选举两种情况.在讲解Leader选举前先了解 ...

  3. Zookeeper系列(十一)zookeeper的Leader选举详解(核心之一)

    作者:leesf    掌控之中,才会成功:掌控之外,注定失败. 出处:http://www.cnblogs.com/leesf456/p/6107600.html尊重原创,奇文共欣赏: 一.前言 前 ...

  4. 【分布式】Zookeeper的Leader选举-选举过程介绍(经典的Paxos算法解析)

    一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...

  5. 简单理解Zookeeper的Leader选举

    Leader选举是保证分布式数据一致性的关键所在.Leader选举分为Zookeeper集群初始化启动时选举和Zookeeper集群运行期间Leader重新选举两种情况.在讲解Leader选举前先了解 ...

  6. 面试官:说一说Zookeeper中Leader选举机制

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 今天又是一个阳光明媚的一天,我又 ...

  7. Zookeeper之Leader选举过程

    Leader在集群中是一个非常重要的角色,负责了整个事务的处理和调度,保证分布式数据一致性的关键所在.既然Leader在ZooKeeper集群中这么重要所以一定要保证集群在任何时候都有且仅有一个Lea ...

  8. zookeeper进行leader选举

    一.如何进行leader选举 创建 /lj/producer和/lj/master/producer外层节点 创建临时顺序节点 判断自己是否是master节点(判断流程:遍历/lj/producer节 ...

  9. zookeeper的leader选举机制个人总结

    第一步:每个服务器都首先投自己,格式为<sid,zxid>: 第二步:然后将自己的投票以<sid,zxid>形式发送给其他服务器,这样每个服务器除了自己的投票,还有集群中除了自 ...

随机推荐

  1. 搜索类网站记录 && 代理服务器

    搜索类网站记录 && 代理服务器 技巧 1.使用site   我们在搜索的时候,其实不全依赖搜索引擎也是可以的, 比如我们要搜索一个 “中国” ,可以在搜索框输入   中国  site ...

  2. Java之IO(八)PipedIutputStream和PipedOutputStream

    转载请注明源出处:http://www.cnblogs.com/lighten/p/7056278.html 1.前言 本章介绍Java的IO体系中最后一对字节流--管道流.之前在字节数组流的时候就说 ...

  3. 可视化的Redis数据库管理工具redis-desktop-manager的初步使用(图文详解)

    不多说,直接上干货! 无论是Linux 还是 Windows里安装Redis, Windows里如何正确安装Redis以服务运行(博主推荐)(图文详解) Windows下如何正确下载并安装可视化的Re ...

  4. 2-nginx 安装

    1, nginx简介: •Nginx("engine x") 是一个高性能的HTTP 和反向代理服务器,也是一个IMAP/POP3/SMTP 代理服务器.•第一个公开版本0.1.0 ...

  5. redis-java中的callback回掉机制

    springboot整合redis后, 会提供StringRedisTEmplate和 RedisTemplate 两个模板类供食用, 有时候这并不能满足我们的需求, 需要使用 connect 处理, ...

  6. WPF为ItemsControl设置ItemsPanelTemplate

    1. 直接在XAML中以对象属性的方式 <ItemsControl x:Name="lstNew"> <ItemsControl.ItemsPanel> & ...

  7. Error : Weblogic Maven Plugin deployment WebLogic 12c

    Error : Weblogic Maven Plugin deployment i want to use weblogic-maven-plugin in my maven project in ...

  8. python 笔记-转

    python笔记   Python 学习笔记 - 14.技巧(Tips)   Python 学习笔记 - 13.异常(Exception)   Python 学习笔记 - 12.流程控制(Contro ...

  9. typeof null 为什么等于 object?

    之前只知道typeof null = object,但是却从来不知道是为什么.最新查阅资料的时候,看到了这个原理,记录下来,方便自己以后查看. 原理是这样的,不同的对象在底层都表示为二进制,在 Jav ...

  10. Mac配置多个版本JDK

    2016年mac上已经安装有jdk1.6的版本  目录在/Library/Java/JavaVirtualMachines/1.6.0.jdk 有时候mac版本跟新会自动删除jdk1.6 所以要去ma ...