1.1什么是zookeeper?
1.Zookeeper是一个分布式协调服务;就是为用户的分布式应用程序提供协调服务
2.Zookeeper是为别的分布式程序服务的
3.Zookpeer本身就是一个分布式程序(只要有半数以上节点存活,zk就能正常服务)
Zookeeper集群的角色:Leader(领导者)和follower(从属) (Observer)观察者
4.Zookeeper在底层最核心的两个功能:
管理(存储,读取)用户程序提交的数据
为用户程序提供数据节点监听服务
1.2 zookeeper服务的应用场景
1.主从协调 2.服务器节点动态上下线 3.统一配置管理
4.分布式共享锁 5.统一名称服务等
1.3zookeeper集群特性
1、zookeeper:一个leader和多个follower组成的集群
2、全局数据一致:每个server保存一根相同的数据副本,client无论连接到那个server,数据都是一致的
3、分布式读写,更新请求转发,由leader实施
4、更新请求顺序进行,来在同一个client的更新请求按其发送顺序依次执行
5、数据更新原子性,一次数据更新要么成功,要么失败
6、实时性,在一定时间范围内,client能读到最新数据
1.4 zookeeper数据结构
1、层次化的目录结构,命名符合常规文件系统规范
2、每个节点在zookeeper中叫做znode,并且有其一个唯一的路径标识
3、节点Znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)
4、客户端应用可以在节点上设置监视器
1.5 节点类型
znode有两种类型:短暂(ephemeral)(断开连接自己删除)
持久(persistent)(断开连接不删除)
Znode有四种形式的目录节点(默认是persistent ):
1.PERSISTENT 持久类型
2.PERSISTENT_SEQUENTIAL(持久序列类型/test0000000019 )sequential
3.EPHEMERAL 短暂类型
4.EPHEMERAL_SEQUENTIAL 短暂序列类型
创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
排序:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
1.6 zookeeper数据结构特点
1.每个子目录项如 NameService 都被称作为 znode,这个 znode 是被它所在的路径唯一标识,如 Server1 这个 znode 的标识为 /NameService/Server1
2.znode 可以有子节点目录,并且每个 znode 可以存储数据,注意 EPHEMERAL类型的目录节点不能有子节点目录
3.znode 是有版本的,每个 znode 中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据
4.znode 可以是临时节点,一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为 session,如果 znode 是临时节点,这个 session 失效,znode 也就删除了
5.znode 的目录名可以自动编号,如 App1 已经存在,再创建的话,将会自动命名为 App2
6.znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于这个特性实现的
1.7 zookeeper的常用java api
1.7.1创建一个znode节点(zk节点的crate方法,可以创建上述4中节点)
/**CountDownLatch介绍:
CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,
await()方法会阻塞程序继续执行。CountDownLatch可以看作是一个倒计数的锁存器,
当计数减至0时触发特定的事件。利用这种特性,可以让主线程等待子线程的结束。
*/
public void testConnect() throws Exception {
final CountDownLatch cdl = new CountDownLatch(1);//创建一个同步计数器
//连接zk服务器的url只要有半数以上存活,服务就能正常执行,写单独一个也可以
String connectinfo = "192.168.196.100:2181,192.168.196.101:2181,192.168.196.102:2181";
//连接服务器的超时时间
int sessionTimeout = 2000;
ZooKeeper zk = new ZooKeeper(connectinfo, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected) {//连接服务器成功的回调方法
System.out.println("=============process===========");
//以下方法cdl.countDown() 使计数器从默认值1变为0,取消阻塞
cdl.countDown();//连接成功了,可以接触阻塞语句(cdl.await()),然后此“阻塞语句”的后续代码
}
}
});
//如果前面代码执行未成功,cd1为1,不执行后面代码. cd1程序计数器为0时才进行后续代码
cdl.await();//CountDownLatch的阻塞代码
String actual_path = zk.create("/zk02", "aa_info".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("============end==============" + actual_path);
}