zk终极运用

25 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情

z k

  • 根据报错信息我们知道缺失zoo.cfg默认配置文件。在conf目录下官方给我们提供了zoo_sample.cfg模板配置文件。我们只需要复制改文件为zoo.cfg在此基础上进行修该cp zoo_sample.cfg zoo.cfg

    • 然后重复我们单机版的过程。在根目录创建data文件夹,然后修改conf中对应的data配置。只不过这里还需要我们修改一下端口号。因为在同一台机器上所以需要不同的端口号才行。
  • 最后新增集群内部通讯端口

  • 集群启动完成了。但是我们现在对zk集群好像还是没有太大的感知。比如说我们不知道谁是leader。 可以通过如下命令查看每台zk的角色

原理

  • client如果直接将数据变更请求发送到leader端,则直接从图中第三步开始发送proposal请求等待过半机制后再发送commit proposal。follower则会开始更新本地zxid并同步数据。
  • 如果client发送的是follower,则需要follower先将请求转发至leader然后在重复上面的步骤。
  • 在数据同步期间为了保障数据强一致性。leader发送的proposal都是有序的。follower执行的数据变更也都是有顺序的。这样能保证数据最终一致性。 在一段时间内比如说需要对变量a=5和1=1操作。如果a=5和a=1是两个事物。如果leader通知follower进行同步,zk1先a=1在a=5。则zk1中的a为5.zk3反之来则zk3中a=1;这样就会造成数不一致。但是zookeeper通过znode节点有序排列保证了follower数据消费也是有序的。在莫一时刻zk1执行了a=5,这时候client查了zk1的a是5,虽然表面上是脏数据实际上是zk1未执行完。等待zk1执行完a=1.这就叫数据最终一致性。
  • 下面一张图可能更加的形象,来自于网络图片

应用

  • mysql隔离控制

  • mysql锁

  • edis锁

  • zookeeper锁

  • 因为zookeeper基于观察者模式,我们上锁失败后可以监听对应的值直到他失效时我们在进行我们的操作这样能够保证我们有序处理业务,从而实现锁的功能。

  • 上图是两个线程上锁的简易图示。在zookeeper中实现分布式锁主要依赖CuratorFrameworkInterProcessMutex两个类
 ​
 CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.44.131:2181", newExponentialBackoffRetry(10003));
     client.start();
     InterProcessMutex mutex = new InterProcessMutex(client, "/config/test");
     long s = System.currentTimeMillis();
     boolean acquire = mutex.acquire(100, TimeUnit.SECONDS);
     if (acquire) {
         long e = System.currentTimeMillis();
         System.out.println(e - s+"@@@ms");
         System.out.println("lock success....");
    }
 ​
  • 最终InterProcessMutex实现加锁。加锁会在指定的key上添加一个新的key且带有编号。此时线程中的编号和获取的/config/test下集合编号最小值相同的话则上锁成功。T2则上锁失败,此时会想前一个序号的key添加监听。即当00001失效时则00002对应的T2就会获取到锁。这样可以保证队列的有序进行。