关于 zookeeper 的集群部署的博客, 网上有很多. 但光看不动手, 永远是个门外汉.
( 注: 本文操作均在 windows 下操作, zookeeper 在 windows 与 linux 下操作一致 )
- 部署
- 集群
- 验证
部署
下载地址 : http://zookeeper.apache.org/releases.html 或者 百度网盘 - zookeeper-3.4.5.tar.gz, 下载完成后, 直接解压.
运行 : 进入 zookeeper-3.4.5\bin
文件夹, 找到 zkServer.cmd
文件 ( 注 : windows 下 zk 服务器启动文件是 zkServer.cmd, Linux 下是 zkServer.sh ), 运行文件, 发现无法启动 ( 注: 找不到 zoo.cfg文件 ) ; 进入zookeeper-3.4.5\conf
文件夹, 找打zoo-sample.cfg
文件, 修改文件名为zoo.cfg
. 运行 zkServer.cmd
. OK .
zoo.cfg 内容如下
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tool_space/zookeeper/server_1/data
dataLogDir=/tool_space/zookeeper/server_1/dataLog
# the port at which the clients will connect
clientPort=2181
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
- tickTime: 这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每
个 tickTime 时间就会发送一个心跳。
- dataDir: 顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
- dataLogDir: 顾名思义就是 Zookeeper 保存日志文件的目录 (这个如果没有可以自己添加)
- clientPort: 这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
- initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
- syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
检测 : 运行 zkCli.cmd
, 随意输入命令, 例如: help
, 如下图
ls /
: 可见 ‘/’ 节点下的子节点
get /
: 可以查看 ‘/’ 节点存储的内容
create /root rootdata acl
: 可以创建 ‘/root’ 节点, 并存储内容 ‘rootdata’, acl 代表 acl 权限控制
( 注: 其他命令请自行百度/Google )
zookeeper 文件系统 : 如下图, zookeeper使用了一个类似文件系统的树结构,数据可以挂在某个节点上,可以对这个节点进行删改
集群
( 注 : 由于资源限制, 没法布置多台机器, 进行集群, 这里在一台机器上部署多台 zookeeper 进行集群, 也称为伪集群; 多数小公司一般都采用这种伪集群, 宕机的概率十分小, 而且节省资源. )
步骤 :
1. 创建三个文件夹 server_1, server_2, server_3, 分别对应一台 zk 服务器.
2. 在 server_1, server_2, server_3 中创建文件夹 data , dataLog 对应 zoo.cfg 中配置的数据/日志路径.
3. 在 data 文件夹下创建一个名为 myid 的文件, 注意 : 文件名叫 myid , 没有后缀. 内容为对应 server 的 id, server_1 为 1, server_2 为 2.
4. 分别解压一份 zookeeper
5. 修改 zoo-sample.cfg
–> zoo.cfg
6. 修改 zoo.cfg 配置, 配置如下 ( 已忽略注释 ):
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tool_space/zookeeper/server_1/data
dataLogDir=/tool_space/zookeeper/server_1/dataLog
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器, 即为 myid 中存储的内容;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
进入 /bin 目录中,运行 zkServer.cmd 启动一个server,这时会报大量错误?其实没什么关系,因为现在集群只起了1台server,zookeeper服务器端起来会根据zoo.cfg的服务器列表发起选举leader的请求,因为连不上其他机器而报错,那么当我们起第二个zookeeper实例后,leader将会被选出,从而一致性服务开始可以使用,这是因为3台机器只要有2台可用就可以选出leader并且对外提供服务(2n+1台机器,可以容n台机器挂掉)。
验证
方法一 使用 zkCli 进行验证
步骤:
1) 打开任意 zkCli, 默认会连到 leader( 注 : zookeeper 默认以 ID 小的作为 leader ) , 创建节点 test
, 并存储数据
create /test data
2) 使用 connect 命令, 连接到其他 zkServer
connect 127.0.0.1:2182
3) 使用 ls path 和 get path 命令, 检测节点和数据是否已同步
ls /
get /test
4) ok ! 祝贺!
方法二 使用 java 代码验证
步骤:
1) 创建项目
2) 引入 zookeeper jar包, maven 项目如下:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.5</version>
</dependency>
3) 连接到集群zookeeper, 关闭某台 zookeeper , 连接任然 ok.
//创建一个Zookeeper实例,第一个参数为目标服务器地址和端口,多台zk集群连接用逗号隔开
//第二个参数为Session超时时间,第三个为节点变化时的回调方法
ZooKeeper zk = new ZooKeeper("127.0.0.1:2182,127.0.0.1:2182,127.0.0.1:2183", 500000, new Watcher() {
// 监控所有被触发的事件
public void process(WatchedEvent event) {
//dosomething
}
});
或者, 连接某台 zookeeper, 进行节点操作, 其他节点数据有同步
附 : java 节点操作
// 创建一个root节点
zk.create("/root", "mydata".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 在root下面创建一个child znode,数据为childone,不进行ACL权限控制,节点为永久性的
zk.create("/root/child","child".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
// 取得/root节点下的子节点名称,返回List<String>
List<String> test = zk.getChildren("/root", true);
System.out.println(JSON.toJSONString(test));
// 取得/root节点下的数据,返回byte[]
byte[] bytes = zk.getData("/root", true, null);
System.out.println(new String(bytes));
// 修改节点/root/childone下的数据,第三个参数为版本,如果是-1,那会无视被修改的数据版本,直接改掉
zk.setData("/root/childone", "setData".getBytes(), -1);
// 删除/root/childone这个节点,第二个参数为版本,-1的话直接删除,无视版本
zk.delete("/root/childone", -1);
// 关闭session
zk.close();