如下这篇文章感觉写的不错,说明了ZK在Hbase和Kafka如何应用的:
http://www.tuicool.com/articles/beY3Mj
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分 别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上 了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个 新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
每个Server在工作过程中有三种状态:
- LOOKING:当前Server不知道leader是谁,正在搜寻
- LEADING:当前Server即为选举出来的leader
- FOLLOWING:leader已经选举出来,当前Server与之同步
事务操作
在ZooKeeper中,能改变ZooKeeper服务器状态的操作称为事务操作。一般包括数据节点创建与删除、数据内容更新和客户端会话创建与失效等操作。对应每一个事务请求,ZooKeeper都会为其分配一个全局唯一的事务ID,用ZXID表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,从这些ZXID中可以间接地识别出ZooKeeper处理这些事务操作请求的全局顺序。
Watcher
Watcher(事件监听器),是ZooKeeper中一个很重要的特性。ZooKeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper服务端会将事件通知到感兴趣的客户端上去。该机制是ZooKeeper实现分布式协调服务的重要特性
private static String zkList = "localhost:2181"; private static int Session_TIMOUT = 5000; private static String Parentpath = "/registry"; private static CountDownLatch latch = new CountDownLatch(1); public static void main(String[] args) throws IOException, InterruptedException, KeeperException { createZKNode(getZKServer(), zkList); List<String> listNode = watchNode(getZKServer()); for (String str : listNode) { System.out.println(str); } } public static ZooKeeper getZKServer() throws InterruptedException, IOException { ZooKeeper zk = new ZooKeeper(zkList, Session_TIMOUT, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { if (watchedEvent.getState() == Event.KeeperState.SyncConnected) { latch.countDown(); } } }); latch.await(); return zk; } /* * OPEN_ACL_UNSAFE :完全开放; * CREATOR_ALL_ACL :给创建该znode连接所有权限; * READ_ACL_UNSAFE :所有的客户端都可读; * */ protected static void createZKNode(ZooKeeper zk, String url) throws IOException, InterruptedException, KeeperException { byte[] dataurl = url.getBytes(); zk.create(Parentpath + "/zklist", dataurl, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); } protected static List<String> watchNode(ZooKeeper zk) throws KeeperException, InterruptedException { List<String> listNode = zk.getChildren(Parentpath, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { if (watchedEvent.getType() == Event.EventType.NodeChildrenChanged) { try { watchNode(zk); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } }); List<String> dataList = new ArrayList<String>(); for (String node : listNode) { //获取node中关联的数据 byte[] zkData = zk.getData(Parentpath + "/" + node, false, null); dataList.add(new String(zkData)); } return dataList; }