博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZooKeeper运行原理和基本编程接口
阅读量:6623 次
发布时间:2019-06-25

本文共 4453 字,大约阅读时间需要 14 分钟。

什么是ZooKeeper 

ZooKeeper作为一个分布式的服务框架(与Google Chubby类似),主要用于解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但 ZK并不是用来专门存储数据的,它的作用主要是用来维护和监控系统存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理。

Client在ZooKeeper里添加一个节点意味着在一棵类似文件树的结构上添加节点,每一个节点有着唯一的路径(/mutex-lock/uuid-lock-sn),称之为ZNode;每一个ZNode上可以存储少量的数据(缺省为1M),根据创建类型的不同有四种ZNode类型,persisten,persisten_sequential,ephemeral,ephemeral_sequential;persisten的ZNode为永久性数据需要显示删除,ephemeral的ZNode在创建的session会话结束后会被自动删除,sequential的ZNode会在节点名后自动生成唯一的SN号。

ZooKeeper是以Fast Paxos (Leslie Lamport)算法为基础,经过Leader Election 和Data Sync之后,多台ZooKeeper Server就组成了分布式的ZooKeeper service group;每一台ZooKeeper Server上都保存了完整的ZNode Tree信息,因此每一台ZooKeeper Server都可以提供读写操作,从而极大提升了集群的性能;对于写操作而言,ZooKeeper采用的策略是Write Ahead Log,先写日志再进行更新的方式极大保证了服务的可靠性。

一个简单的ZooKeeper内部操作流如下:(侵删)

 

ZooKeeper安装配置和简单操作

将ZooKeeper(3.4.12)包解压到指定目录,在$ZK_HOME/conf目录下添加zoo.cfg的文件,里面可配置ZooKeeper的运行参数;如果是集群(Quorum)的话需要多配置两个地方,一个是在zoo.cfg文件里添加带有编号的server list,另外一个是在dataDir/目录下创建文件myid并且写入与server list的编号一致的数字 ,表示当前的ZooKeeper实例对应的是server list中的哪个server。zoo.cfg示例如下

1 # 一次tick的毫秒数 2 tickTime=2000 3 # initial sync的最大tick数 4 initLimit=10 5 # 日常通信的最大tick数 6 syncLimit=5 7 # snapshot存储文件的目录 8 dataDir=~/active/zookeeper-0/snapshot 9 dataLogDir=~/active/zookeeper-0/log10 # client与当前zk实例连接的端口11 clientPort=218012 # 集群内所有zk实例的编号,IP,在与leader通信时使用的端口,在leader election时使用端口13 server.0=127.0.0.1:8880:788014 server.1=127.0.0.1:8881:788115 server.2=127.0.0.1:8882:788216 server.3=127.0.0.1:8883:788317 server.4=127.0.0.1:8884:7884

 

执行命令$ZK_HOME/bin/zkServer.sh start,启动ZooKeeper的实例,如果是n个server的集群的话需要启动至少n/2个server,否则ZooKeeper会认为当前的集群不可用,比如上述配置中有5个server,则需要至少启动3个server后集群才可用。执行命令$ZK_HOME/bin/zkCli.sh -server 127.0.0.1:2180,连接并访问对应的ZooKeeper实例(by TCP);连接到集群之后可以查看、创建和修改指定ZNode的数据。

其他命令:$ZK_HOME/bin/zkCleanup.sh表示清理当前zk实例的dataDir和dataLogDir目录;$ZK_HOME/bin/zkEnv.sh表示动态设置当前zk实例的运行变量。

 

利用Apache Curator集成使用ZooKeeper

由于ZooKeeper仅提供最原始的分布式一致性功能,如果需要实现分布式锁等功能需要再次进行封装,Apache Curator提供了一套成熟的框架对ZooKeeper的功能进行了封装;基于maven的依赖如下。

1 
2
org.apache.zookeeper
3
zookeeper
4
3.4.8
5
6
7
org.apache.curator
8
curator-recipes
9
2.9.1
10
11
12
org.apache.curator
13
curator-client
14
2.9.1
15

 

通过ZooKeeper实现分布式锁:racing process在指定节点/mutex-lock下创建ephemeral_sequential类型的ZNode,xxx-lock-SN,ZooKeeper可以保证SN的唯一性和顺次递增性;racing process创建好自己的ZNode之后判断自己的SN 是否是/mutex-lock节点下最小的,如果是最小的则表示获取到了锁,如果不是最小的,则在比自己次小的ZNode上设置watcher并等待锁;当前获取到锁的racing process在处理完事务之后释放锁,也就是删除/mutex-lock下对应的ZNode,这样ZooKeeper的watcher机制给下一个racing process发起通知。Java示例代码如下

1 public class App { 2     public static void main(String[] args) throws Exception { 3         for (int i = 0; i < 10; i++) { 4             ClientJob cj = new ClientJob(i); 5             new Thread(cj).start(); 6             Thread.sleep(500); 7         } 8     } 9     public static class ClientJob implements Runnable {10         private int num;11         public ClientJob(int num) {12             this.num = num;13         }14         public void run() {15             RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);16 CuratorFramework client = 17       CuratorFrameworkFactory.newClient("127.0.0.1:2180", retryPolicy);18             client.start();19 20             InterProcessMutex lock = new InterProcessMutex(client, "/mutex-lock");21             try {22                 System.out.println("## " + num + " ##, try fetching lock.");23                 lock.acquire();24                 System.out.println("## " + num + " ##, has fetched lock.");25                 Thread.sleep(10000);26             } catch (Exception e) {27                 e.printStackTrace();28             } finally {29                 try {30                     lock.release();31                     System.out.println("## " + num + " ##, has released lock.");32                     client.close();33                 } catch (Exception e) {34                     e.printStackTrace();35                 }36             }37         }38     }39 }

 

通过ZooKeeper实现读写锁:读锁表示允许其他racing process读,但禁止写;写锁表示禁止其他racing process读和写。写锁的实现与常规分布式锁的实现一致,读锁的实现可以判断排在自己之前的racing process的所有ZNode信息,如果存在WRITE racing process则不能获取锁,否则可以获取到锁。Curator还实现了包含Leader Election,Barrier,Counter,Queue等在内的分布式系统内需要的协调服务。

 

转载于:https://www.cnblogs.com/leo-chen-2014/p/9163132.html

你可能感兴趣的文章
Entity Framework 5.0基础系列
查看>>
使用Swift和SpriteKit写一个忍者游戏
查看>>
2014辛星在读CSS第八节 使用背景图片
查看>>
TBluetoothLEDevice.UpdateOnReconnect
查看>>
QtTableView 简介
查看>>
Linux系统上安装软件(ftp服务器)
查看>>
[iOS] App引导页的简单实现 (Swift 2)
查看>>
MHA 代码解析(online swtich+master is alive 模式)
查看>>
利用openssl进行RSA加密解密
查看>>
盒模型--边界
查看>>
14.使用通配符
查看>>
软件的模块化开发
查看>>
腾讯、百度、阿里面试经验—(3)阿里面经
查看>>
稍复杂的ionic例子:显示一个列表,并且允许点击进入列表项
查看>>
一些新的web性能优化技术
查看>>
Liferay 6开发学习(二十六):数据库连接相关问题
查看>>
【转】半路学编程,可以成为大牛吗?
查看>>
【20170506】贝业新兄弟IT总监李济宏:第三方家居物流的IT架构探索
查看>>
【Excle数据透视】如何在数据透视表字段列表中显示更多的字段
查看>>
vue 记一次编译没反应、无进度、没有任何报错的提示,但后台却TM一直消耗内存的BUG:...
查看>>