1.zookeeper简介1.1简介
Zookeeper是一个分布式协调服务,换言之,就是为用户的分布式应用程序提供协调服务
zookeeper是为别的分布式程序服务的
Zookeeper本身就是一个分布式程序(只要有半数以上节点存活,zk就能正常服务)
Zookeeper所提供的服务涵盖:主从协调、服务器节点动态上下线、统一配置管理、分布式共享锁、统一名称服务
虽然说可以提供各种服务,但是zookeeper在底层其实只提供了两个功能(管理数据和监听数据):管理(存储,读取)用户程序提交的数据;并为用户程序提供数据节点监听服务;
1.2 Zookeeper集群的角色: Leader 和 follower
Zookeeper在配置文件中并没有指定master和slave,启动之后通过内部的选举机制选举出leader和follower,而且只有一个leader,其他则为follower。zookeeper集群中只要有半数以上节点存活,集群就能提供服务。2.zookeeper集群机制半数机制:集群中半数以上机器存活,集群可用。zookeeper适合装在奇数台机器上!!!
2.zookeeper安装与配置2.1zookeeper安装
安装到3台虚拟机上(需要提前安装好JDK) 将zookeeper压缩包上传至/apps/package目录并解压
重命名
修改环境变量
重新编译文件: source /etc/profile 三台机器都需要修改
2.2 修改配置文件
先复制一份 cd zookeeper/conf cp zoo_sample.cfg zoo.cfg
编辑 vi zoo.cfg
创建文件夹:
在data文件夹下新建myid文件,myid的文件内容为:
mini2和mini3服务器的请修改成2,3,将来会按这个myid选中出leader和follow。
将集群复制到其他机器上
如果在mini1中ping不通mini2和mini3,需要在hosts文件中配置mini2和mini3的ip地址
修改其他机器的配置文件 到mini2上:修改myid为:2 到mini3上:修改myid为:3 而且/etc/profile的路径也不要忘了修改
启动(每台机器)
查看集群状态
3.zookeeper数据结构和常用操作3.1zookeeper特性
Zookeeper:一个leader,多个follower组成的集群
全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的
分布式读写,更新请求转发,由leader实施
更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行
数据更新原子性,一次数据更新要么成功,要么失败
实时性,在一定时间范围内,client能读到最新数据
3.2zookeeper数据结构
层次化的目录结构;
每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识;
节点Znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点);
客户端应用可以在节点上设置监视器。
3.3节点类型
Znode有两种类型: 短暂(ephemeral)(断开连接自己删除) 持久(persistent)(断开连接不删除)
Znode有四种形式的目录节点(默认是persistent ) PERSISTENT PERSISTENTSEQUENTIAL(持久序列/test0000000019 ) EPHEMERAL EPHEMERALSEQUENTIAL
创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
使用客户端操作节点
使用命令连接zookeeper服务端:
使用 ls 命令来查看当前 ZooKeeper 中所包含的内容:
创建一个新的 znode ,使用 create /zk myData 。这个命令创建了一个新的 znode 节点“ zk ”以及与它关联的字符串:
我们运行 get 命令来确认 znode 是否包含我们所创建的字符串:
-监听这个节点的变化,当另外一个客户端改变/zk时,输出监听到的变化
使用set 命令来对 zk 所关联的字符串进行设置:
使用delete删除 znode 节点:
删除节点(与上面的区别是这个可以删除目录):rmr
参考文档:http://www.cnblogs.com/likehua/tag/zookeeper/
4.使用java操作zookeeper的api
首先需要引入zookeeper的jar包,这个jar包需要依赖其它的jar,可以直接到maven仓库下载。
常用的增删查改api操作如下: create 在目录树中创建一个节点 delete 删除一个节点 exists 测试是否存在目标节点 get/set data 从目标节点上读取 / 更新数据 get/set ACL 获取 / 设置目标节点访问控制列表信息 get children 检索一个子节点上的列表 sync 等待要被传送的数据 使用java操作代码如下:
Thread.sleep(Long.MAX_VALUE);是为了不让程序执行完之后立马结束,让它睡一会,测试监听是否实现,同时在process回调函数中写了收到通知的操作, zkCli.getChildren("/", true);这时如果我们通过linux命令行操作了zookeeper操作节点就会触发这里的监听事件。
5.zookeeper的使用场景5.1场景一:客户端动态感知服务端节点变化,实现高可用
现在假设有这样一种需求:服务端节点有多个,可以动态的上下线;需要让任意一台客户端都能实时感知服务端节点的变化,进而连接目前可提供服务的节点。实现思路:我们可以借助于zookeeper这个第三方中间件,在每台服务器启动时都向zookeeper注册服务器的节点信息(比如:/servers/server01;/servers/server02);客户端每次调用之前都通过getChildren方法获取最新的服务器节点信息,同时客户端在zookeeper注册监听,监听服务器节点的变化;如果某刻服务器server01下线了,zookeeper就会发出节点变化通知客户端,回调process方法拉取最新的服务器节点信息。服务端代码如下:
客户端代码如下:
5.2场景二:分布式锁实现
假设现在集群中有50台机器对某台机器上的同一文件进行修改,如何才能保证这个文件不会被写乱呢,使用java中的synchronized锁肯定是不行的,因为这个锁是对某个程序而言的,而我们这根本就不是在一个服务器上,怎么会锁的住,用zookeeper实现的分布式锁可以实现。设计思路:服务器启动时都去zookeeper上注册一个“短暂+序号”的znode节点(如/lock/1;/lock/2),并设置监听父节点变化;获取到父节点下所有子节点,并比较序号的大小;约定比如序号最小的获取锁,去操作某一文件,操作完成后删除自己的节点(相当于释放锁),并注册一个新的“短暂+序号”的znode节点;其它程序收到zookeeper发送的节点变化的通知之后,去比较序号的大小,看谁获得新锁。
参考文档:http://www.cnblogs.com/likehua/tag/zookeeper/
6 zookeeper的选举机制6.1全新集群paxos
以一个简单的例子来说明整个选举的过程.假设有五台服务器组成的zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的.假设这些服务器依序启动,来看看会发生什么.1) 服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是LOOKING状态2) 服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1,2还是继续保持LOOKING状态.3) 服务器3启动,根据前面的理论分析,服务器3成为服务器1,2,3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader.4) 服务器4启动,根据前面的分析,理论上服务器4应该是服务器1,2,3,4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了.5) 服务器5启动,同4一样,当小弟.
6.2非全新集群的选举机制(数据恢复)
那么,初始化的时候,是按照上述的说明进行选举的,但是当zookeeper运行了一段时间之后,有机器down掉,重新选举时,选举过程就相对复杂了。需要加入数据id、leader id和逻辑时钟。数据id:数据新的id就大,数据每次更新都会更新id。Leader id:就是我们配置的myid中的值,每个机器一个。逻辑时钟:这个值从0开始递增,每次选举对应一个值,也就是说: 如果在同一次选举中,那么这个值应该是一致的 ; 逻辑时钟值越大,说明这一次选举leader的进程更新.选举的标准就变成:1、逻辑时钟小的选举结果被忽略,重新投票2、统一逻辑时钟后,数据id大的胜出3、数据id相同的情况下,leader id大的胜出根据这个规则选出leader。
领取专属 10元无门槛券
私享最新 技术干货