ZooKeeper 有三种安装模式: 单机安装(standalone), 伪集群模式, 集群模式:
standalone 模式: 只在一台机器上安装 ZooKeeper, 并只启动一个 ZooKeeper 实例.
伪集群: 在一台机器上开启多个 ZooKeeper 实例来模拟集群. 通过加载不同配置文件, 分配不同数据目录来实现这种模式. 因为在同一机器上运行, 所以机器宕机, 整个 ZooKeeper 就挂了. 基本上不会布置这样的 ZooKeeper 集群.
集群模式: 在至少 3 台机器上安装 ZooKeeper 构成集群, 只要故障节点数量在一定范围内就能保证 ZooKeeper 服务的可用性.
真正布置的基本上都是集群模式, standalone 偶尔用来做些测试, 它有单点故障, 伪集群模式也有单点故障.
集群模式并非一定至少 3 台机器, 但用 2 台机器比 1 台机器更危险, 因为随便故障一台都无法满足 "大多数" 的要求, 都会阻塞整个 ZooKeeper 服务. 而 2 台机器的故障几率是 1 台机器的 2 倍. 所以, 也建议采用奇数台机器来部署 ZooKeeper.
ZooKeeper 下载: https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/
我下载的是 3.4.12 版本.
1. 安装 jdk
ZooKeeper 运行在 java 环境下, 所以需要先安装 jdk, 且要求版本高于 1.6.
jdk 下载: http://www.oracle.com/technetwork/java/javase/downloads/index.html
以 rpm 包的为例.
yum localinstall -y jdk-8u131-linux-x64.rpm
rpm 包的安装路径为 / usr/java.
- [root@s1 ~]# ls -l /usr/java/
- total 4
- lrwxrwxrwx 1 root root 16 Jun 26 22:53 default -> /usr/java/latest
- drwxr-xr-x 9 root root 4096 Jun 26 22:53 jdk1.8.0_131
- lrwxrwxrwx 1 root root 22 Jun 26 22:53 latest -> /usr/java/jdk1.8.0_131
通过这种软链接方式, 以后有新版 jdk 要安装, 直接改 latest 的链接对象即可.
然后再设置 JAVA_HOME 环境变量并导出 java 程序所在目录的 PATH 环境变量.
- echo 'JAVA_HOME=/usr/java/latest'> /etc/profile.d/jdk.sh
- echo 'PATH=$JAVA_HOME/bin:$PATH'>> /etc/profile.d/jdk.sh
- chmod +x /etc/profile.d/jdk.sh
- source /etc/profile.d/jdk.sh
2.StandAlone 模式
standalone 模式是在单机上安装 ZooKeeper.
先解压 zookeeper-3.4.12.tar.gz.
tar xf zookeeper-3.4.12.tar.gz
再把它移到 / usr/local / 下方便管理.
mv zookeeper-3.4.12 /usr/local/zookeeper
在 ZooKeeper 的 bin 目录下提供了几个 Windows 和 Linux 下的脚本:
- [root@s2 zookeeper]# cd /usr/local/zookeeper
- [root@s2 zookeeper]# ls bin
- README.txt zkCleanup.sh zkCli.cmd zkCli.sh zkEnv.cmd zkEnv.sh zkServer.cmd zkServer.sh
zkServer: 用于启动, 停止 ZooKeeper, 且能查看 ZooKeeper 状态.
zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
zkEnv: 设置 ZooKeeper 启动, 关闭时的环境变量. 在其余的每个脚本中都引用了这个脚本.
zkCleanup: 清除 ZooKeeper 的事务日志和快照.
zkCli:ZooKeeper 的一个命令行客户端.
设置 ZooKeeper 的环境变量, 这不是必须的, 只是为了方便操作上面的几个脚本.
- echo 'ZOOKEEPER_HOME=/usr/local/zookeeper'>/etc/profile.d/zk.sh
- echo 'PATH=$ZOOKEEPER_HOME/bin:$PATH'>> /etc/profile.d/zk.sh
- chmod +x /etc/profile.d/zk.sh
- source /etc/profile.d/zk.sh
把 windows 下的脚本删除:
rm -rf /usr/local/zookeeper/bin/{*.cmd,README.txt}
为了启动 ZooKeeper, 先提供一个配置文件. 默认配置文件的路径为 $ZOOKEEPER_HOME 下的 conf 目录. 在这个目录下, 有几个文件:
- [root@s2 zookeeper]# ls conf
- configuration.xsl log4j.properties zoo_sample.cfg
configuration.xsl: 无视它.
log4f.properties: 是 ZooKeeper 的日志配置文件.
zoo_sample.cfg: 是 ZooKeeper 的示例配置文件.
zkServer.sh 默认的配置文件名为 zoo.cfg. 所以, 在 conf 目录下创建一个 zoo.cfg. 写入几个保证 ZooKeeper 能正常运行的配置项:
- tickTime=2000
- dataDir=/usr/local/zookeeper/data1
- clientPort=2181
其中:
tickTime:ZooKeeper 中很多配置项 (如心跳时间, 连接超时时间等) 都要用到的时间单位, 这里配置为 2000 毫秒, 即 2 秒.
dataDir:ZooKeeper 实例的数据目录.
clientPort:ZooKeeper 向外提供服务的端口.
然后用 zkServer.sh 来启动 ZooKeeper.
- [root@s2 zk]# zkServer.sh start
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
- Starting zookeeper ... STARTED
也可以手动指定启动时读取的配置文件:
[root@s2 zk]# zkServer.sh start /usr/local/zookeeper/conf/zoo.cfg
查看 ZooKeeper 的运行状态:
- [root@s2 zk]# zkServer.sh status
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
- Mode: standalone
可以看到运行模式是 "standalone".
ZooKeeper 启动后, 就可以向外提供 ZooKeeper 服务了. 这里用 ZooKeeper 提供的命令行客户端去连接一下 ZooKeeper 做个简单的测试.
连接 ZooKeeper 实例:
zkCli.sh -server localhost:2181
连接过程中会输出一大堆信息. 当连接成功后, 将进入 ZooKeeper 的交互式模式:
- WatchedEvent state:SyncConnected type:None path:null
- [zk: localhost:2181(CONNECTED) 0] # 在这里输入 ZooKeeper 允许的命令
例如, 创建一个 znode:
- [zk: localhost:2181(CONNECTED) 0] create /zk_test mydata1
- Created /zk_test
- [zk: localhost:2181(CONNECTED) 1] ls /
- [zookeeper, zk_test]
- [zk: localhost:2181(CONNECTED) 2] quit
3. 配置伪集群模式
ZooKeeper 的伪集群模式是在一个服务器上运行多个 ZooKeeper 实例来模拟 ZooKeeper 集群. 伪集群模式下, 每个实例的配置文件不同, 数据目录不同, 端口不同. 一般来说, ZooKeeper 集群至少需要 3 个服务器节点.
这里, 我配置 3 个实例的 ZooKeeper 伪集群, 它们的数据目录分别为 $ZOOKEEPER_HOME 下的 data1,data2 和 data3. 因为稍后要向这些目录中写 myid 文件, 所以先创建这 3 个目录:
mkdir /usr/local/zookeeper/data{1,2,3}
先提供 3 个实例的配置文件, 分别为
- $ZOOKEEPER_HOME/conf/{zoo1.cfg,zoo2.cfg,zoo3.cfg}
- .
以下是 zoo1.cfg 内容, 各配置项稍后解释.
- tickTime=2000
- dataDir=/usr/local/zookeeper/data1
- clientPort=2181
- initLimit=5
- syncLimit=2
- server.1=localhost:2887:3887
- server.2=localhost:2888:3888
- server.3=localhost:2889:3889
以下是 zoo2.cfg 内容, 各配置项稍后解释.
- tickTime=2000
- dataDir=/usr/local/zookeeper/data2
- clientPort=2182
- initLimit=5
- syncLimit=2
- server.1=localhost:2887:3887
- server.2=localhost:2888:3888
- server.3=localhost:2889:3889
以下是 zoo3.cfg 内容, 各配置项稍后解释.
- tickTime=2000
- dataDir=/usr/local/zookeeper/data3
- clientPort=2183
- initLimit=5
- syncLimit=2
- server.1=localhost:2887:3887
- server.2=localhost:2888:3888
- server.3=localhost:2889:3889
上面的配置项中:
initLimit: 当非 leader 节点 (即 follower 和 observer) 启动时, 需要先从 leader 那里复制数据, 以保证所有 ZooKeeper 节点数据都是同步的. 这个选项设置非 leader 节点从启动到完成同步的超时时长, 它以 tickTime 为时间单位, 所以上面的超时时长为 5*2=10 秒.
一般来说, ZooKeeper 保存的都是协调数据, 数据量并不大, 所以多数时候可以忽略这个参数, 如果待同步数据真的很大, 可以考虑增加这个超时时间.
syncLimit:follower 和 leader 之间数据延迟的最大时间长度. 例如, 有个节点的更新操作缓慢, 它的数据已经严重落后于 leader,ZooKeeper 就会将它从 ZooKeeper 集群中踢出去. ZooKeeper 使用时间来度量 follower 和 leader 之间数据的延迟, 这个选项的值依赖于 tickTime, 例如
tickTime=2000,syncLimit=2
表示 follower 比 leader 延迟了 4 秒.
server.X=[hostname]:port_A[:port_B]
: 该选项用来指定 ZooKeeper 集群中的服务器节点. 其中:
X: 整数. 是 ZooKeeper 中服务器的一个简单标识. 这个数值需要和 dataDir 下的 myid 文件内容一致. 在启动 ZooKeeper 集群中的每个实例时, 需要读取数据目录中的 myid 文件, 并将该文件中的数值和配置文件中的 server.X 做匹配, 匹配到哪个就表示是哪个 ZooKeeper 服务器节点.
hostname:ZooKeeper 服务器节点的地址.
port_A: 这是第一个端口, 用于 Follower 和 Leader 之间的数据同步和其它通信.
port_B: 这是第二个端口, 用于 Leader 选举过程中投票通信.
所以, 分别在每个实例的 dataDir 下创建对应的 myid 文件.
- echo 1>/usr/local/zookeeper/data1/myid
- echo 2>/usr/local/zookeeper/data2/myid
- echo 3>/usr/local/zookeeper/data3/myid
然后启动这 3 个 ZooKeeper 实例.
- zkServer.sh start /usr/local/zookeeper/conf/zoo1.cfg
- zkServer.sh start /usr/local/zookeeper/conf/zoo2.cfg
- zkServer.sh start /usr/local/zookeeper/conf/zoo3.cfg
查看当前 java 进程列表:
- [root@s1 zk]# jps -l
- 5473 org.apache.zookeeper.server.quorum.QuorumPeerMain
- 5395 org.apache.zookeeper.server.quorum.QuorumPeerMain
- 5427 org.apache.zookeeper.server.quorum.QuorumPeerMain
- 5524 sun.tools.jps.Jps
查看这 3 个实例之间的关系: zoo2.cfg 被选为 leader, 其它是 follower.
- [root@s1 zk]# zkServer.sh status /usr/local/zookeeper/conf/zoo3.cfg
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/conf/zoo3.cfg
- Mode: follower
- [root@s1 zk]# zkServer.sh status /usr/local/zookeeper/conf/zoo1.cfg
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/conf/zoo1.cfg
- Mode: follower
- [root@s1 zk]# zkServer.sh status /usr/local/zookeeper/conf/zoo2.cfg
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/conf/zoo2.cfg
- Mode: leader
可以用 ZooKeeper 提供的命令行客户端工具来测试, 写入其中一个实例的数据, 其它实例也能收到.
[root@s1 zk]# zkCli.sh -server localhost:2181 create /my_znode hello
...... 省略.........
- WatchedEvent state:SyncConnected type:None path:null
- Created /my_znode
- [root@s1 zk]# zkCli.sh -server localhost:2182 ls /
...... 省略........
- WatchedEvent state:SyncConnected type:None path:null
- [my_znode, zookeeper]
4. 配置 ZooKeeper 集群
以 3 节点的集群为例: 192.168.100.21,192.168.100.22,192.168.100.23. 因为前面配置单机 ZooKeeper 和伪集群 ZooKeeper 已经解释过所有步骤和配置项的意义, 所以这里就直接给步骤.
假设已经在 3 个节点上都安装好了 jdk(这是前提), 并下载好了 ZooKeeper.
先解压 zookeeper-3.4.12.tar.gz.
- # 3 个节点都执行
- tar xf zookeeper-3.4.12.tar.gz
- mv zookeeper-3.4.12 /usr/local/zookeeper
添加 ZooKeeper 环境变量, 非必须过程, 但建议.
- # 在 3 节点上都执行
- echo 'ZOOKEEPER_HOME=/usr/local/zookeeper'>/etc/profile.d/zk.sh
- echo 'PATH=$ZOOKEEPER_HOME/bin:$PATH'>> /etc/profile.d/zk.sh
- chmod +x /etc/profile.d/zk.sh
- source /etc/profile.d/zk.sh
提供配置文件. 以下是 3 个节点上的配置文件:
- [root@s1 zk]# cat /usr/local/zookeeper/conf/zoo.cfg
- tickTime=2000
- dataDir=/usr/local/zookeeper/data
- clientPort=2181
- initLimit=5
- syncLimit=2
- server.1=192.168.100.21:2888:3888
- server.2=192.168.100.22:2888:3888
- server.3=192.168.100.23:2888:3888
在三个节点上都创建好数据目录, 并写入 myid 文件.
- # 3 个节点上都执行:
- mkdir /usr/local/zookeeper/data
- # 192.168.100.21 上执行
- echo 1>/usr/local/zookeeper/data/myid
- # 192.168.100.22 上执行
- echo 2>/usr/local/zookeeper/data/myid
- # 192.168.100.23 上执行
- echo 3>/usr/local/zookeeper/data/myid
启动这 3 个 ZooKeeper 实例.
- # 3 个节点都执行:
- zkServer.sh start
然后在 3 个节点上都验证一下是否正确启动 ZooKeeper.
- # 节点 1 上执行:
- [root@s1 zk]# zkServer.sh status
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
- Mode: follower
- # 节点 2 上执行:
- [root@s2 zk]# zkServer.sh status
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
- Mode: follower
- # 节点 3 上执行:
- [root@s3 zk]# zkServer.sh status
- ZooKeeper JMX enabled by default
- Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
- Mode: leader
如果某个服务器实例出现了错误, 请 zkServer.sh stop 关闭 ZooKeeper 实例, 然后 jps 命令查看下是否还有 ZooKeeper 实例在运行, 如果有, kill 掉. 然后再启动 ZooKeeper. 另外, 建议在第一次启动 ZooKeeper 之前, 先将 dataDir/version-2 目录删除(如果已存在, 因为可能是以前的实例因为各种原因而留下来的).
最后测试下, 某节点上创建一个 znode, 其它节点是否也同步了该节点.
- # 在 192.168.100.21 上创建一个 znode:
- [root@s2 zk]# zkCli.sh -server 192.168.100.21:2181 create /test_znode "hello world"
- Connecting to 192.168.100.21:2181
......... 省略..........
- Created /test_znode
- # 在 192.168.100.22 上获取这个 znode
- [root@s2 zk]# zkCli.sh -server 192.168.100.22:2181 get /test_znode
- Connecting to 192.168.100.22:2181
......... 省略..........
- hello world
- cZxid = 0x100000002
- ctime = Wed Jun 27 08:14:38 CST 2018
- mZxid = 0x100000002
- mtime = Wed Jun 27 08:14:38 CST 2018
- pZxid = 0x100000002
- cversion = 0
- dataVersion = 0
- aclVersion = 0
- ephemeralOwner = 0x0
- dataLength = 11
- numChildren = 0
- # 在 192.168.100.23 上获取这个 znode
- [root@s2 zk]# zkCli.sh -server 192.168.100.23:2181 ls /
- Connecting to 192.168.100.23:2181
......... 省略..........
[zookeeper, test_znode]
来源: https://www.cnblogs.com/f-ck-need-u/p/9235308.html