zookeeper应用 - leader选举 锁

模拟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权威指南(第二版)》

时间: 2024-08-05 11:15:00

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

【分布式】Zookeeper的Leader选举

一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概述 Leader选举是保证分布式数据一致性的关键所在.当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举. (1) 服务器初始化启动. (2) 服务器运行期间无法和Leader保持连接. 下面就两种情况进行分析讲解. 1. 服务器启动时期的Leader选举 若进行

【分布式】Zookeeper的Leader选举-选举过程介绍

[分布式]Zookeeper的Leader选举-选举过程介绍 选举开始,服务器会各自为自己投票,在投票完成后,会将投票信息发送给集群中的所有服务器(观察者服务器不参与选举). 选票由两部分组成:服务器唯一标识myid和事务编号zxid,即(myid,xzid). zxid越大说明数据越新,在选择算法中的权重越大.myid越大,在选择算法中的权重越大. 比较选票时会先比较zxid,zxid大的获胜,zxid相同时比较myid,myid大的获胜,胜利方选票不变,失败方选票将变成与胜利方一样,并再次将

面试题:说说你对ZooKeeper集群与Leader选举的理解?

ZooKeeper是一个开源分布式协调服务.分布式数据一致性解决方案.可基于ZooKeeper实现命名服务.集群管理.Master选举.分布式锁等功能. 高可用 为了保证ZooKeeper的可用性,在生产环境中我们使用ZooKeeper集群模式对外提供服务,并且集群规模至少由3个ZooKeeper节点组成. ? 集群至少由3个节点组成?? ZooKeeper其实2个节点也可以组成集群并对外提供服务,但我们使用集群主要目的是为了高可用.如果2个节点组成集群,其中1个节点挂了,另外ZooKeeper

kafka中对于zookeeper的理解和leader选举过程

1. 首先zookeeper是什么 zookeeper是一个开放源代码的分布式应用程序协调服务,可以把它看成是整个集群的管理者,监视者. 2. zookeeper能做什么 它可以实现诸如分布式应用配置管理.统一命名服务.状态同步服务.集群管理等功能. 3. zookeeper服务与kafka集群的联系 这里首先说一下broker的概念:Kafka 集群包含一个或多个服务器,这种服务器被称为 broker,每个broker服务器都要连接到zk服务. 一个典型的kafka集群中包含若干个produc

跟着实例学习ZooKeeper的用法: Leader选举

http://colobu.com/2014/12/12/zookeeper-recipes-by-example-1/ ZooKeeper官方给出了使用zookeeper的几种用途. Leader Election Barriers Queues Locks Two-phased Commit 其它应用如Name Service, Configuration, Group Membership 在实际使用ZooKeeper开发中,我们最常用的是Apache Curator. 它由Netflix

zookeeper leader选举机制

最近看了下zookeeper的源码,先整理下leader选举机制 先看几个关键数据结构和函数 服务可能处于的状态,从名字应该很好理解 public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING; } 选票参数,还有Notification,参数也都差不多 static public class ToSend { long leader; //leader id long zxid; //选票的zxid long electio

zookeeper curator学习(配合spring boot模拟leader选举)

基础知识:http://www.cnblogs.com/LiZhiW/p/4930486.html 项目路径:https://gitee.com/zhangjunqing/spring-boot  查找下面四个项目就可以了 zookeeper版本为zookeeper-3.4.9(需要查找合适的curator版本) 三个spring bootweb项目: 官方案例leader: 思路:新建三个spring boot web项目,在这三个web项目中定义一个过滤器来在初始化时抢夺leader权限,如

Zookeeper详解-工作流和leader选举(三)

一.工作流 一旦ZooKeeper集合启动,它将等待客户端连接.客户端将连接到ZooKeeper集合中的一个节点.它可以是leader或follower节点.一旦客户端被连接,节点将向特定客户端分配会话ID并向该客户端发送确认.如果客户端没有收到确认,它将尝试连接ZooKeeper集合中的另一个节点. 一旦连接到节点,客户端将以有规律的间隔向节点发送心跳,以确保连接不会丢失. 如果客户端想要读取特定的znode,它将会向具有znode路径的节点发送读取请求,并且节点通过从其自己的数据库获取来返回

Zookeeper leader选举

Zookeeper leader选举 由 xpproen 创建,youj 最后一次修改 2016-12-27 让我们分析如何在ZooKeeper集合中选举leader节点.考虑一个集群中有N个节点.leader选举的过程如下: 所有节点创建具有相同路径 /app/leader_election/guid_ 的顺序.临时节点. ZooKeeper集合将附加10位序列号到路径,创建的znode将是 /app/leader_election/guid_0000000001,/app/leader_el