`
agapple
  • 浏览: 1583564 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

zookeeper学习记录

 
阅读更多

背景

   前段时间看了S4流计算引擎,里面使用到了zookeeper进行集群管理,所以也就花了点时间研究了下zookeeper,不求看懂所有源码,但求了解其实现机制和原理,清楚其基本使用。这也是为后续hadoop,gridgain的分布式计算的产品。

学习

首先就是收集一些前人的一些学习资料和总结内容,方便自己快速入门。 

这里罗列了几篇不错的文章: 

 

看了这两篇文章,基本可以对zookeeper有了一个感性的认识,它是一个什么?

zookeeper功能点:
  • 统一命名空间(Name Service)
  • 配置推送 (Watch)
  • 集群管理(Group membership)

统一命名空间

在zookeeper中实现了一个类似file system系统的数据结构,比如/zookeeper/status。 每个节点都对应于一个znode节点。

znode节点的数据结构模型:


 

znode的数据结构内容:

 

  • czxid

    The zxid of the change that caused this znode to be created.

  • mzxid

    The zxid of the change that last modified this znode.

  • ctime

    The time in milliseconds from epoch when this znode was created.

  • mtime

    The time in milliseconds from epoch when this znode was last modified.

  • version

    The number of changes to the data of this znode.

  • cversion

    The number of changes to the children of this znode.

  • aversion

    The number of changes to the ACL of this znode.

  • ephemeralOwner

    The session id of the owner of this znode if the znode is an ephemeral node. If it is not an ephemeral node, it will be zero.

  • dataLength

    The length of the data field of this znode.

  • numChildren

    The number of children of this znode.

 

 

说明: zxid (ZooKeeper Transaction Id,每次请求对应一个唯一的zxid,如果zxid a < zxid b ,则可以保证a一定发生在b之前)。

 

针对树状结构的处理,来看一下客户端使用的api : 

 

String create(String path, byte data[], List<ACL> acl, CreateMode createMode)
void   create(String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx)

void delete(String path, int version)
void delete(String path, int version, VoidCallback cb, Object ctx)

Stat setData(String path, byte data[], int version)
void setData(String path, byte data[], int version, StatCallback cb, Object ctx)

Stat setACL(String path, List<ACL> acl, int version)
void setACL(String path, List<ACL> acl, int version, StatCallback cb, Object ctx)

Stat exists(String path, Watcher watcher)
Stat exists(String path, boolean watch)
void exists(String path, Watcher watcher, StatCallback cb, Object ctx)
void exists(String path, boolean watch  , StatCallback cb, Object ctx)

byte[] getData(String path, Watcher watcher, Stat stat)
byte[] getData(String path, boolean watch  , Stat stat)
void   getData(String path, Watcher watcher, DataCallback cb, Object ctx)
void   getData(String path, boolean watch  , DataCallback cb, Object ctx)

List<String> getChildren(String path, Watcher watcher)
List<String> getChildren(String path, boolean watch  )
void  getChildren(String path, Watcher watcher, ChildrenCallback cb, Object ctx)
void  getChildren(String path, boolean watch  , ChildrenCallback cb, Object ctx)

List<String> getChildren(String path, Watcher watcher, Stat stat)
List<String> getChildren(String path, boolean watch  , Stat stat)
void getChildren(String path, Watcher watcher, Children2Callback cb, Object ctx)
void getChildren(String path, boolean watch  , Children2Callback cb, Object ctx)

 

说明:每一种按同步还是异步,添加指定watcher还是默认watcher又分为4种。默认watcher可以在ZooKeeper zk = new ZooKeeper(serverList, sessionTimeout, watcher)中进行指定。如果包含boolean watch的读方法传入true则将默认watcher注册为所关注事件的watch。如果传入false则不注册任何watch

 

CreateMode主要有几种:

 

  • PERSISTENT (持续的,相比于EPHEMERAL,不会随着client session的close/expire而消失)
  • PERSISTENT_SEQUENTIAL
  • EPHEMERAL (短暂的,生命周期依赖于client session,对应session close/expire后其znode也会消失)
  • EPHEMERAL_SEQUENTIAL  (SEQUENTIAL意为顺序的)
AsyncCallback异步callback,根据操作类型的不同,也分几类:
  • StringCallback
  • VoidCallback
  • StatCallback
  • DataCallback  (getData请求)
  • ChildrenCallback
  • Children2Callback
对应的ACL这里有篇不错的文章介绍,http://rdc.taobao.com/team/jm/archives/947

配置推送(Watcher)

zookeeper为解决数据的一致性,使用了Watcher的异步回调接口,将服务端znode的变化以事件的形式通知给客户端,主要是一种反向推送的机制,让客户端可以做出及时响应。比如及时更新后端的可用集群服务列表。

 

这里有篇文章介绍Watcher/Callback比较详细,可以参考下:

 

 

如果想更好的理解Watcher的使用场景,可以了解下使用Watcher机制实现分布式的Barrier , Queue , Lock同步。

 

Barrier例子:

 

public class Barrier implements Watcher {

    private static final String addr = "10.20.156.49:2181";
    private ZooKeeper           zk   = null;
    private Integer             mutex;
    private int                 size = 0;
    private String              root;

    public Barrier(String root, int size){
        this.root = root;
        this.size = size;

        try {
            zk = new ZooKeeper(addr, 10 * 1000, this);
            mutex = new Integer(-1);
            Stat s = zk.exists(root, false);
            if (s == null) {
                zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public synchronized void process(WatchedEvent event) {
        synchronized (mutex) {
            mutex.notify();
        }
    }

    public boolean enter(String name) throws Exception {
        zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        while (true) {
            synchronized (mutex) {
                List<String> list = zk.getChildren(root, true);
                if (list.size() < size) {
                    mutex.wait();
                } else {
                    return true;
                }
            }
        }
    }

    public boolean leave(String name) throws KeeperException, InterruptedException {
        zk.delete(root + "/" + name, 0);
        while (true) {
            synchronized (mutex) {
                List<String> list = zk.getChildren(root, true);
                if (list.size() > 0) {
                    mutex.wait();
                } else {
                    return true;
                }
            }
        }
    }

}

 

 

测试代码:

 

public class BarrierTest {

    public static void main(String args[]) throws Exception {
        for (int i = 0; i < 3; i++) {
            Process p = new Process("Thread-" + i, new Barrier("/test/barrier", 3));
            p.start();
        }
    }
}

class Process extends Thread {

    private String  name;
    private Barrier barrier;

    public Process(String name, Barrier barrier){
        this.name = name;
        this.barrier = barrier;
    }

    @Override
    public void run() {
        try {
            barrier.enter(name);
            System.out.println(name + " enter");
            Thread.sleep(1000 + new Random().nextInt(2000));
            barrier.leave(name);
            System.out.println(name + " leave");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

通过该Barrier,可以协调不同任务之间的同步处理,这里主要还是利用了Watcher机制的反向推送,避免客户端的循环polling动作,只要针对有事件的变化做一次响应。

 

集群管理

我不罗嗦,taobao有几篇文章已经介绍的很详细。

 

zookeeper集群对server进行了归类,可分为:
  • Leader
  • Follower
  • Obserer
说明:
1. Leader/Follower会通过选举算法进行选择,可以看一下http://zookeeper.apache.org/doc/r3.3.2/recipes.html 里的Leader Election章节。
2. Observer主要是为提升zookeeper的性能,observer和follower的主要区别就是observer不参与Leader agreement vote处理。只提供读节点的处理,类似于master/slave的读请求。 (http://zookeeper.apache.org/doc/r3.3.2/zookeeperObservers.html)
server.1:localhost:2181:3181:observer

3. 可通过命令行,查看当前server所处的状态

 

[ljh@ccbu-156-49 bin]$ echo stat | nc localhost 2181
Zookeeper version: 3.3.3--1, built on 06/24/2011 13:12 GMT
Clients:
 /10.16.4.30:34760[1](queued=0,recved=632,sent=632)
 /127.0.0.1:43626[0](queued=0,recved=1,sent=0)
 /10.16.4.30:34797[1](queued=0,recved=2917,sent=2917)

Latency min/avg/max: 0/0/33
Received: 3552
Sent: 3551
Outstanding: 0
Zxid: 0x200000003
Mode: follower  ##当前模式
Node count: 8
 

 

使用zookeeper,我们能干些什么?

官方文档中,有举了几个应用场景,就是使用zookeeper提供分布式锁机制,从而实现分布式的一致性处理。

典型的几个场景:

  • Barrier
  • Queue
  • Lock
  • 2PC

其他

zookeeper基本是基于API和console进行znode的操作,并没有一个比较方便的操作界面,这里也发现了taobao 伯岩写的一个工具,可以比较方便的查询zookeeper信息。

工具的开发语言主要是node.js(最近比较火),其标榜的是无阻塞的api使用。其原理主要是基于google的V8(chrome的javascript的解析器,C语言编写),node.js本身是基于js语法进行开发,通过V8解析为C语言的执行代码

其标榜的无阻塞I/O实现,那可想而知就是linux系统下的select/poll的I/O模型。有兴趣的可以看下node.js的官网,下载一个玩玩。

 

文档地址: http://www.blogjava.net/killme2008/archive/2011/06/06/351793.html

代码地址:  https://github.com/killme2008/node-zk-browser

通过git下载源码后,需要安装下node.js的几个模块express, express-namespace, zookeeper。 node.js下有个比较方便的模块管理器npm,类似于redhat的rpm,ubuntu的apt-get。 

安装模块:

 

npm install -g express

 

几个界面:


 

 

  • 大小: 34.6 KB
  • 大小: 71.3 KB
分享到:
评论
9 楼 jingwangfei 2016-01-04  
thanksm, 楼主的这个学习思路是很给力的. --> 快速学习的方式.
大赞
8 楼 zjc_8886 2015-04-03  
请问楼主,你好,web server首先访问zookeeper,zookeeper来管理服务列表吗? 那么web server是不是也有可能单点故障??? 对于web server(apache,nginx)单点zookeeper怎么支持??? 一直不明白这个架构,不明白zookeeper怎么被用户直接调用,zookeeper不可能直接提供类似web的服务啊。  我们一直使用  web server(HA) + n台(Tomcat)的架构,请楼主解答,谢谢!
7 楼 乱劈才 2014-10-27  
正在学zookeeper,感谢楼主的文章,让我受益匪浅
6 楼 di1984HIT 2014-07-06  
支持你,咳咳
5 楼 wanglf365 2014-05-17  
/quote]
4 楼 agapple 2013-03-25  
lixieinstein 写道
LZ,你好,请问Barrier实现中,Barrier类的process方法为什么要加上synchronized呢?里面已经对mutex加锁了,所以这个方法肯定同步了,即使异步事件触发了,也是不会同步执行process,process被修饰为synchronized是不是没有必要呢?我看ZooKeeper的官方文档里面也加了这个synchronized,但是我觉得好像是没有必要的。


you are right.

这个例子我是参照官方文档实现的,不过Watch.process()回调基本也是串行操作,也不会有并发的问题
3 楼 lixieinstein 2013-03-24  
LZ,你好,请问Barrier实现中,Barrier类的process方法为什么要加上synchronized呢?里面已经对mutex加锁了,所以这个方法肯定同步了,即使异步事件触发了,也是不会同步执行process,process被修饰为synchronized是不是没有必要呢?我看ZooKeeper的官方文档里面也加了这个synchronized,但是我觉得好像是没有必要的。
2 楼 agapple 2012-11-03  
543089122 写道
LZ,你的分布式Barrier有点问题吧!你enter方法里面的synchronized (mutex)在分布式的情况下等于摆设。。


分布式锁操作一定会有单机jvm的lock机制配合。这里为啥用sync原语,可以看下object的wait方法的使用
1 楼 543089122 2012-11-02  
LZ,你的分布式Barrier有点问题吧!你enter方法里面的synchronized (mutex)在分布式的情况下等于摆设。。

相关推荐

    zookeeper学习笔记

    zookeeper学习笔记

    Zookeeper学习笔记.docx

    Zookeeper学习笔记

    Zookeeper学习笔记

    自己整理的ZooKeeper学习笔记,适合刚刚接触ZooKeeper的人学习

    ZooKeeper学习笔记

    java ZooKeeper学习笔记\ZooKeeper原理、运用

    Zookeeper学习笔记.pdf

    ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:**分布式锁服务**。由于ZooKeeper的开源特性,后来我们的开发者在分布式锁的基础上,摸索了出了其他的使用方法:**...

    zookeeper学习笔记.pptx

    本文适合但不限于软件开发人员阅读。本文档能够使阅读者对zookeeper有一个宏观且全面的了解,内容主要包含zookeeper架构、数据模型、读写及工作原理、典型应用场景、指令汇总等,

    Zookeeper学习资源和笔记(附代码)

    适合初学入门,知识巩固。涵盖安装配置、命令操作、Java API操作、事件监听、分布式锁、集群搭建等知识

    zookeeper一站式学习资料

    zookeeper一站式学习资料包含国内首部Zookeeper从入门到精通+搜索引擎等一条龙学习资料以及视频讲解包含笔记代码资源

    学习笔记--zookeeper

    zookeeper学习,包括zookeeper架构,原理,安装,配置,命令管理,API编程以及可以应用的场景

    zookeeper完整学习笔记

    - 概述 - 术语 - 分布式应用 - 介绍 - 架构 - 工作流 - Leader选举 - 安装服务 - CLI 操作 - java-api - 动态感知服务器上下线 - 实现Hadoop高可用(Hadoop-HA-High Availability)

    java后端学习笔记

    activeMq,rabbitMq,activity工作流,docker,dubbo,netty,rpc,springcloud,zookeeper学习笔记

    云的学习笔记-云的学习笔记系统-云的学习笔记系统源码-云的学习笔记管理系统-基于ssm的云的学习笔记系统-ssm-java代码

    zookeeper云的学习笔记-云的学习笔记系统-云的学习笔记系统源码-云的学习笔记管理系统-云的学习笔记管理系统java代码-云的学习笔记系统设计与实现-基于ssm的云的学习笔记系统-基于Web的云的学习笔记系统设计与实现-...

    zookeeper 学习分享

    这是我自己学习zookeeper的一些过程记录,希望能够帮到大家

    ZooKeeper.pdf

    Zookeeper技术的基础详细学习笔记,总结了Zookeeper的各个知识点,可以用来复习以及对基础知识的巩固,对新人的学习很有帮助。

    zookeeper笔记

    zookeeper原理以及应用笔记学习总结,适合初学者!欢迎下载

    zookeeper-01.xmind

    zk学习笔记

    1.笔记_zookeeper_

    Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。该文档适合学习者学习zookeeper,结构清晰,层次递增,需要学习者配合xmind软件学习

    Zookeeper集群架构全面实战

    非常强的一套Zookeeper集群实战,包含了全套的学习代码,学习笔记还有学习资料。内容从Zookeeper入门教学,本地安装,Zookeeper集群实战,项目需求,Zookeeper企业面试实战,Zookeeper算法实战,Zookeeper核心源码...

    sunweiguo#swgBook-for-spring-cloud#Zookeeper笔记01-CAP和BASE理论1

    前言学习zookeeper才算是真正跨进分布式这个大门。比较经典的应用是可以作为dubbo推荐的注册中心。首先,我们必须要明确几个我们之前可能不会遇到的但是在分

Global site tag (gtag.js) - Google Analytics