Zookeeper学习

Zookeeper特性

  1. 一致性:数据按照顺序分批入库
  2. 原子性:事务要么成功要么失败
  3. 单一视图:客户端连接任一zookeeper节点,数据都是一致的
  4. 可靠性:每次操作都会保存
  5. 实时性:客户端可以读取到最新数据

zoo.fig配置

  1. tickTime: 计算时间单元,毫秒
  2. initLimit: 用于集群,允许从节点到主节点的初始连接时间,是tickTime的倍数
  3. syncLimit: 心跳机制请求和应答时间长度
  4. dataDit: 数据存储目录
  5. dataLogDir: 日志目录
  6. clientPort: 服务器端口,默认2181

Zookeeper基本功能

  1. 树结构,类似linux结构
  2. ./zkCli.sh 启动客户端
  3. 节点选举,主节点挂了,从节点会接手工作,保证高可用
  4. 统一配置文件管理,即只需部署一台服务器,则可以把相同的配置文件同步更新到其他所有服务器
  5. 发布订阅,发布者将数据存在znode上,订阅者读取
  6. 分布式锁,不同进程会争夺资源
  7. 集群管理, 保证数据的强一致性

命令

  1. ls 查看子节点
  2. ls2 查看子节点+stat
  3. get stat 显示基本信息
  4. create /demo/demo demo (-s 有序 , -e 临时)
  5. set修改 set /demo newdemo 1(1是版本号,乐观锁)
  6. delete /demo 1(只会删除版本号为1的节点)

session原理

  1. 客户端与服务端之间的连接存在会话
  2. 每个会话都可以设置超时时间
  3. 心跳结束,session就会过期
  4. session过期,临时结点znode会被抛弃

watcher机制

  1. 针对每个节点的操作
  2. 当某个节点znode发生变化,会触发watcher
  3. 一次性(通过插件实现永久)
  4. 增删改都会触发
  5. 创建stat /demo watch 给demo节点加触发器get /demo watch ls /demo watch
  6. 修改子节点不会触发父节点的触发器

ACL权限控制

四种ACL模式 world,auth,digest,ip

  1. 针对节点设置相关的读写权限
  2. getAcl 获取某节点权限信息
  3. setAcl 设置某节点信息
  4. addauth 输入认证授权信息
  5. 通过三个元素构成权限列表 scheme:某种机制 id:允许访问的用户 permissions:权限组和字符串
  6. crdwa权限字符串,c创建,r获取,w写数据,d删除,a修改权限
  7. addauth digest user:pwd 先将用户密码添加到库里
  8. setAcl /demo auth:wxs:123:cdrwa 设置第一次有效setAcl /names/test
  9. digest:wxs:du6Uisv8vNTo9rDUPJ8ikL2Ro94=:cdra安全性高
  10. 通过ip设置权限 setAcl /names/ip ip:192.168.37.1:cdrwa 只有通过此ip才能访问
  11. super超级用户,需要修改配置文件

四字命令

  1. 查看节点信息 echo stat | nc localhost 2181
  2. 查看是否在线 echo ruok | nc localhost 2181
  3. 查看临时节点信息 echo dump | nc localhost 2181
  4. 查看服务器配置 echo conf | nc localhost 2181
  5. 查看服务器连接信息echo cons | nc localhost 2181
  6. 查看环境变量 echo envi | nc localhost 2181
  7. mntr 健康信息 wchs 触发器信息 wchc 查看session wchp 查看path

集群搭建

  1. 配置文件 myid 1/2/3 对应 server 1/2/3
  2. 环境变量,ip配置不同,端口号相同
    server.1=192.168.48.128:2888:3888
    server.2=192.168.48.129:2888:3888
    server.3=192.168.48.130:2888:3888

Java客户端连接

/**
 * @Title: ZKConnectDemo.java
 * @Package com.imooc.zk.demo
 * @Description: zookeeper 连接demo演示
 */
public class ZKConnect implements Watcher {
        
    final static Logger log = LoggerFactory.getLogger(ZKConnect.class);

    public static final String zkServerPath = "192.168.1.110:2181";
//  public static final String zkServerPath = "192.168.1.111:2181,192.168.1.111:2182,192.168.1.111:2183";
    public static final Integer timeout = 5000;
    
    public static void main(String[] args) throws Exception {
        /**
         * 客户端和zk服务端链接是一个异步的过程
         * 当连接成功后后,客户端会收的一个watch通知
         * 
         * 参数:
         * connectString:连接服务器的ip字符串,
         *      比如: "192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181"
         *      可以是一个ip,也可以是多个ip,一个ip代表单机,多个ip代表集群
         *      也可以在ip后加路径
         * sessionTimeout:超时时间,心跳收不到了,那就超时
         * watcher:通知事件,如果有对应的事件触发,则会收到一个通知;如果不需要,那就设置为null
         * canBeReadOnly:可读,当这个物理机节点断开后,还是可以读到数据的,只是不能写,
         *                         此时数据被读取到的可能是旧数据,此处建议设置为false,不推荐使用
         * sessionId:会话的id
         * sessionPasswd:会话密码   当会话丢失后,可以依据 sessionId 和 sessionPasswd 重新获取会话
         */
        ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZKConnect());
        
        log.warn("客户端开始连接zookeeper服务器...");
        log.warn("连接状态:{}", zk.getState());
        
        new Thread().sleep(2000);
        
        log.warn("连接状态:{}", zk.getState());
    }

    @Override
    public void process(WatchedEvent event) {
        log.warn("接受到watch通知:{}", event);
    }
}

console:
2018-04-04 11:25:08,846 [main] [com.imooc.zk.demo.ZKConnect.main(ZKConnect.java:43)] - [WARN] 客户端开始连接zookeeper服务器...
2018-04-04 11:25:08,850 [main] [com.imooc.zk.demo.ZKConnect.main(ZKConnect.java:44)] - [WARN] 连接状态:CONNECTING
2018-04-04 11:25:08,873 [main-EventThread] [com.imooc.zk.demo.ZKConnect.process(ZKConnect.java:53)] - [WARN] 接受到watch通知:WatchedEvent state:SyncConnected type:None path:null
2018-04-04 11:25:10,851 [main] [com.imooc.zk.demo.ZKConnect.main(ZKConnect.java:48)] - [WARN] 连接状态:CONNECTED

会话重连

/**
 * 
 * @Title: ZKConnectDemo.java
 * @Description: zookeeper 恢复之前的会话连接demo演示
 */
public class ZKConnectSessionWatcher implements Watcher {
    
    final static Logger log = LoggerFactory.getLogger(ZKConnectSessionWatcher.class);

    public static final String zkServerPath = "192.168.1.110:2181";
    public static final Integer timeout = 5000;
    
    public static void main(String[] args) throws Exception {
        
        ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZKConnectSessionWatcher());
        
        // 获取sessionID和密码
        long sessionId = zk.getSessionId();
        byte[] sessionPassword = zk.getSessionPasswd();
        
        log.warn("客户端开始连接zookeeper服务器...");
        log.warn("连接状态:{}", zk.getState());
        new Thread().sleep(1000);
        log.warn("连接状态:{}", zk.getState());
        
        new Thread().sleep(200);
        
        // 开始会话重连
        log.warn("开始会话重连...");
        
        //多传入两个参数,SSID和密码
        ZooKeeper zkSession = new ZooKeeper(zkServerPath, 
                                            timeout, 
                                            new ZKConnectSessionWatcher(), 
                                            sessionId, 
                                            sessionPassword);
        log.warn("重新连接状态zkSession:{}", zkSession.getState());
        new Thread().sleep(1000);
        log.warn("重新连接状态zkSession:{}", zkSession.getState());
    }
    
    @Override
    public void process(WatchedEvent event) {
        log.warn("接受到watch通知:{}", event);
    }
}

console:
2018-04-04 13:52:21,097 [main] [com.imooc.zk.demo.ZKConnectSessionWatcher.main(ZKConnectSessionWatcher.java:30)] - [WARN] 客户端开始连接zookeeper服务器...
2018-04-04 13:52:21,103 [main] [com.imooc.zk.demo.ZKConnectSessionWatcher.main(ZKConnectSessionWatcher.java:31)] - [WARN] 连接状态:CONNECTING
2018-04-04 13:52:21,141 [main-EventThread] [com.imooc.zk.demo.ZKConnectSessionWatcher.process(ZKConnectSessionWatcher.java:52)] - [WARN] 接受到watch通知:WatchedEvent state:SyncConnected type:None path:null
2018-04-04 13:52:22,103 [main] [com.imooc.zk.demo.ZKConnectSessionWatcher.main(ZKConnectSessionWatcher.java:33)] - [WARN] 连接状态:CONNECTED
2018-04-04 13:52:22,304 [main] [com.imooc.zk.demo.ZKConnectSessionWatcher.main(ZKConnectSessionWatcher.java:38)] - [WARN] 开始会话重连...
2018-04-04 13:52:22,306 [main] [com.imooc.zk.demo.ZKConnectSessionWatcher.main(ZKConnectSessionWatcher.java:45)] - [WARN] 重新连接状态zkSession:CONNECTING
2018-04-04 13:52:22,311 [main-EventThread] [com.imooc.zk.demo.ZKConnectSessionWatcher.process(ZKConnectSessionWatcher.java:52)] - [WARN] 接受到watch通知:WatchedEvent state:SyncConnected type:None path:null
2018-04-04 13:52:23,307 [main] [com.imooc.zk.demo.ZKConnectSessionWatcher.main(ZKConnectSessionWatcher.java:47)] - [WARN] 重新连接状态zkSession:CONNECTED

节点操作

  1. 创建节点
  • 同步

    //创建一个"/node"节点,数据是nodeData,权限是world:anyone:cdrwa,持久型节点
    zk.create("/node", "nodeData".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

  • 异步

    String ctx = "{'create':'success'}";
    //额外传入一个回调函数,实现StringCallback接口,ctx为回调对象
    zk.create(path, data, acls, CreateMode.PERSISTENT, new CreateCallBack(), ctx);

  1. 修改节点
  • 同步

      /**
       * 参数:
       * path:节点路径
       * data:数据
       * version:数据状态
       */
      Stat status  = zkServer.getZookeeper().setData("/testnode", "xyz".getBytes(), 0);
      System.out.println(status.getVersion());
    
  1. 删除节点
  • 同步
zk.getZookeeper().delete("/test-delete-node", 0);
  • 异步(推荐)

      String ctx = "{'delete':'success'}";
      zk.getZookeeper().delete("/test-delete-node", 0, new DeleteCallBack(), ctx);
      Thread.sleep(2000);
    

CountDownLatch

  1. 需要设定初始值
  2. 调用countDown()使初始值减1
  3. 调用await()阻塞线程,直到初始值减少到0

节点查询

  1. 获取节点数据

    //创建一个节点"/demo",设定watch为true,传入一空的stat对象会自动填充属性
    byte[] resultByte = zk.getZookeeper().getData("/demo",true,stat);
    String result = new String(resultByte);

  2. 获取子节点数据

  • 同步

      List<String> strChildList = zkServer.getZookeeper().getChildren("/imooc", true);
          for (String s : strChildList) {
              System.out.println(s);
          }
    
  1. 判断节点状态
//不存在返回null,存在则获取信息
Stat stat = zkServer.getZookeeper().exists("/imooc-fake", true);

操作权限

  1. 自定义用户

    //首先注册用户,类似addauth
    zkServer.getZookeeper().addAuthInfo("digest", "user1:123456".getBytes());
    zkServer.getZookeeper().addAuthInfo("digest", "user2:123456".getBytes());

    // 自定义用户认证访问
    List<ACL> acls = new ArrayList<ACL>();//创建权限列表

    //用户1
    // Id user1 = new Id("digest", AclUtils.getDigestUserPwd("user1:123456"));

    //用户2
    Id user2 = new Id("digest", AclUtils.getDigestUserPwd("user2:123456"));
    //acls.add(new ACL(Perms.ALL, user1));
    acls.add(new ACL(Perms.READ, user2));
    acls.add(new ACL(Perms.DELETE | Perms.CREATE, user2));
    //可以创建
    zkServer.createZKNode("/aclimooc/testdigest", "testdigest".getBytes(), acls);

  2. 自定义ip

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,561评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,218评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,162评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,470评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,550评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,806评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,951评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,712评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,166评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,510评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,643评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,306评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,930评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,745评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,983评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,351评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,509评论 2 348

推荐阅读更多精彩内容