文章目录
Zookeeper官网:
https://zookeeper.apache.org/
zookeeper命令大全
https://blog.youkuaiyun.com/xuan_lu/article/details/107675047
源代码可借鉴
链接:https://pan.baidu.com/s/13-4HuxmKFBCtbqemdUvCKg
提取码:kpj7
Zookeeper学习
什么是ZooKeeper?
ZooKeeper是用于维护配置信息,命名,提供分布式同步和提供组服务的集中式服务。所有这些类型的服务都以某种形式被分布式应用程序使用。每次实施它们时,都会进行很多工作来修复不可避免的错误和竞争条件。由于难以实现这类服务,因此应用程序通常最初会在其上跳过,从而使它们在发生更改时变得脆弱且难以管理。即使部署正确,这些服务的不同实现也会导致管理复杂。
安装和单机版配置
下载安装
https://apache.org/dist/zookeeper/stable
(3.5.5之后要下载带bin的就是bin.tar.gz 3.5.5之前的是下载tar.gz 如果下载错启动不起来哦!)
在这里插入图片描述
下载好后将镜像上传到我们的服务器上面
- 解压
- 输入: tar -zxvf apache-zookeeper-bin-3.5.9.tar.gz -C /usr/local(tar -zxvf是解压命令 -C是解压到/usr/local位置)
- )
- 移动到: cd /usr/local
- 修改名字:mv apache-zookeeper-3.5.9 zookeeper
修改配置文件
-
备份配置文件:cp zoo_sample.cfg zoo.cfg
-
输入命令: vim zoo.cfg然后修改dataDir如下路径: (没有vim的可以vi或者 yum -y install vim* 安装vim工具)
-
-
创建目录: mkdir -p /usr/mywj/zookeeper
-
(移动到bin目录下)最后启动:** ./zkServer.sh start**
-
-
启动失败如下:
原因是3.5.5版本后要下载带bin.tar.gz的包而不是 直接tar.gz的不然就会报如下: -
-
如果不配置直接启动:
启动重启关闭连接zk和查看启动状态
切换至zookeeper安装目录下的bin目录输入以下命令启动服务器或者客户端
1. 启动ZK服务: ./zkServer.sh start
2. 查看ZK服务状态: ./zkServer.sh status
3. 停止ZK服务: ./zkServer.sh stop
4. 重启ZK服务: ./zkServer.sh restart
5. 连接内部客户端: ./zkCli.sh或者./zkCli.sh -server 127.0.0.1(指定连接服务器IP):2181
查看状态
./zkServer.sh status
- Mode:standalone
- standalone代表是单机版 不适合符合高可用的特点
Zookper单机版的使用
zookper/bin目录下面 通过 ./zkCli.sh 进入客户端后,就可以使用命令来操作zookeeper了。
quit退出客户端
1.创建节点
使用create命令,可以创建一个zookeeper节点。
//语法
-
create [-s] [-e] path data acl
-
//其中-s表示顺序节点,-e表示临时节点。默认情况下,创建的是持久节点。
-
//path是节点路径,data是节点数据,acl是用来进行权限控制的。
-
//案例
-
create /sanguo luoguanzhong 创建一个持久节点目录为/sanguo 值为 luoguanzhong
-
create -s /shuihu shinaian 创建一个持久顺序节点目录为/shuihu 值为 shinaian
-
create -e /xiyou wuchengren 创建一个临时节点目录为/xiyou 值为 wuchengren
-
create -e -s /honglou caoxueqing 创建一个临时顺序节点目录为/honglou 值为 caoxueqing
2 查看节点内容
使用get命令,可以获取zookeeper指定节点的内容和属性信息。
如下:
[zk: 127.0.0.1:2181(CONNECTED) 1] get /sanguo
luoguanzhong
cZxid = 0xd
ctime = Tue Aug 13 20:27:20 CST 2019 创建时候
mZxid = 0xd
mtime = Tue Aug 13 20:27:20 CST 2019 修改时间
pZxid = 0xd
cversion = 0
dataVersion = 0 #没有被修改过,所以版本为0如果有修改过版本会自增
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0
4,更新节点内容
使用set命令,更新节点内容。格式为:
#语法
set path data
其中的data就是要更新的新内容。
例如:
[zk: localhost:2181(CONNECTED) 2] set /sanguo hixx
[zk: localhost:2181(CONNECTED) 3] get /sanguo
hixx
5,删除节点
语法:
- delete path
可以发现,一个节点存在子节点时,无法删除该节点。
还有一个命令rmr path或者deleteall path 删除当前节点及子节点
Zookeeper集群搭建及使用
- 创建一个集群文件夹
[root@192 local]# mkdir zookeeper-cluster
- 复制zookeeper三分到zookeeper-cluster目录
cp -r zookeeper zookeeper-cluster/zk1
cp -r zookeeper zookeeper-cluster/zk2
cp -r zookeeper zookeeper-cluster/zk3
- 分别修改zk1 zk2 zk3中conf下面的zoo.cfg
dataDir=/usr/local/zookeeper-cluster/zk1/data
#zookeeper的日志目录
dataLogDir=/usr/local/zookeeper-cluster/zk1/log
dataDir=/usr/local/zookeeper-cluster/zk2/data
#zookeeper的日志目录
dataLogDir=/usr/local/zookeeper-cluster/zk2/log
clientPort=2182
dataDir=/usr/local/zookeeper-cluster/zk3/data
#zookeeper的日志目录
dataLogDir=/usr/local/zookeeper-cluster/zk3/log
clientPort=2183
- 分别在zk1 zk2 zk3创建data和log目录
mkdir zk1/data
mkdir zk2/data
mkdir zk3/data
mkdir zk1/log
mkdir zk2/log
mkdir zk3/log
# 集群的配置文件
#第几个服务器(1,2,3来自数据目录的一个myid文件,该文件里面保存着当前集群的标识(1,2,3))
# 后面的ip代表将绑定那个ip地址 第一个端口:代表在集群内部,数据复制的接口 第二个端口代表:选举端口
server.1=192.168.188.1:2888:3888
server.2=192.168.188.1:2889:3889
server.3=192.168.188.1:2887:3887
- 配置myid
[root@192 zookeeper-cluster]# touch zk1/data/myid
[root@192 zookeeper-cluster]# touch zk2/data/myid
[root@192 zookeeper-cluster]# touch zk3/data/myid
#修改成1
[root@192 zookeeper-cluster]# vim zk3/data/myid
#修改成2
[root@192 zookeeper-cluster]# vim zk2/data/myid
#修改成3
[root@192 zookeeper-cluster]# vim zk1/data/myid
- zk1的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=/usr/local/zookeeper-cluster/zk1/data
#zookeeper的日志目录
dataLogDir=/usr/local/zookeeper-cluster/zk1/log
# the port at which the clients will connect
clientPort=2181
# 集群的配置文件
#第几个服务器(1,2,3来自数据目录的一个myid文件,该文件里面保存着当前集群的标识(1,2,3))
# 后面的ip代表将绑定那个ip地址 第一个端口:代表在集群内部,数据复制的接口 第二个端口代表:选举端口
server.1=192.168.188.1:2888:3888
server.2=192.168.188.1:2889:3889
server.3=192.168.188.1:2887:3887
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
测试 修改zk1 其中zk2和zk3同步
下载zooinspector图形界面
链接:https://pan.baidu.com/s/1ViBCC7_IByx8MBcC4PF5dw
提取码:dafj
- 启动
- 集群连接
JAVA操作zookeeper
<!-- https://mvnrepository.com/artifact/com.101tec/zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
创建项目maven
- ** 加入依赖 pom.xml借鉴**
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lsz.zk</groupId>
<artifactId>zookeeper-demo</artifactId>
<version>1.0</version>
<!-- https://mvnrepository.com/artifact/com.101tec/zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
</project>
- 节点操作说明
- 节点的增删改查
package com.lsz.zk;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
/**
* 测试连接zk
* 操作zk
* @author dell
*
*/
public class TestCRUD {
private static final String SERVERSTRING = "192.168.188.101:2181,192.168.188.101:2182,192.168.188.101:2183";
private static ZkClient zkClient=null;
static {
zkClient = new ZkClient(SERVERSTRING,10000,10000);
}
public static void main(String[] args) {
//创建 create
//zkClient.create("/java", "java", CreateMode.PERSISTENT);
//修改
//zkClient.writeData("/java", "hello");
//查询
Object readData = zkClient.readData("/java");
System.out.println(readData);
//删除
zkClient.delete("/java");
System.out.println("操作成功zkClient");
}
}
- **监听修改和删除的类 TestWatch **
package com.lsz.zk;
import java.io.IOException;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
/**
* 测试连接zk
* 操作zk
* @author dell
*
*/
public class TestWatch {
private static final String SERVERSTRING = "192.168.188.101:2181,192.168.188.101:2182,192.168.188.101:2183";
private static ZkClient zkClient=null;
static {
zkClient = new ZkClient(SERVERSTRING,10000,10000,new CustomerSerializer());
}
public static void main(String[] args) throws IOException {
zkClient.subscribeDataChanges("/sanguo", new IZkDataListener() {
/**
* 这个节点删除时调用的方法
*/
@Override
public void handleDataDeleted(String dataPath) throws Exception {
// TODO Auto-generated method stub 删除进行的方法
System.out.println("handleDataDeleted:"+dataPath);
}
/**
* 这个节点修改时调用的方法
*/
@Override
public void handleDataChange(String dataPath, Object data) throws Exception {
// TODO Auto-generated method stub 修改进行的方法
System.out.println("handleDataChange"+dataPath+" "+data);
}
});
System.out.println("监听启动成功");
System.in.read();//不让程序结束
}
}
- **创建序列化的类 CustomerSerializer **
package com.lsz.zk;
import java.io.UnsupportedEncodingException;
import org.I0Itec.zkclient.exception.ZkMarshallingError;
import org.I0Itec.zkclient.serialize.ZkSerializer;
public class CustomerSerializer implements ZkSerializer {
/**
* default utf-8
*/
private String charset="UTF-8";
public CustomerSerializer() {
}
public CustomerSerializer(String charset) {
// TODO Auto-generated constructor stub
this.charset = charset;
}
/*
* 序列化
*/
@Override
public byte[] serialize(Object data) throws ZkMarshallingError {
try {
byte[] bytes = String.valueOf(data).getBytes(charset);
return bytes;
} catch (Exception e) {
throw new ZkMarshallingError("Wrong Charset:"+charset);
}
}
/**
* 反序列化
*
*/
@Override
public Object deserialize(byte[] bytes) throws ZkMarshallingError {
// TODO Auto-generated method stub
String result;
try {
result = new String(bytes,charset);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
throw new ZkMarshallingError("Wrong Charset:"+charset);
}
return result;
}
}
Zookeeper和CAP原理及一致性原则
CAP理论告诉我们,一个分布式系统不可能同时满足以下三种
一致性(C:Consistency)
可用性(A:Available)
分区容错性(P:Partition Tolerance)
- 在此ZooKeeper保证的是CP
分析:可用性(A:Available)
不能保证每次服务请求的可用性。任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。所以说,ZooKeeper不能保证服务可用性。
进行leader选举时集群都是不可用。在使用ZooKeeper获取服务列表时,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。所以说,ZooKeeper不能保证服务可用性。
window版本安装
单机版
-
Zookeeper 在Windows下的安装过程及测试
-
安装jdk
-
安装Zookeeper. 在官网http://zookeeper.apache.org/下载zookeeper.我下载的是zookeepe。(开头安装tar.gz的)
注:zookeeper 好像从 3.5 版本以后,命名就发生了改变,如果是 apache-zookeeper-3.5.5.tar.gz 这般命名的,都是未编译的,而 apache-zookeeper-3.5.5-bin.tar.gz 这般命名的,才是已编译的包。 -
解压zookeeper至D:\machine\zookeeper
-
在D:\machine 新建data及log目录。
-
ZooKeeper的安装模式分为三种,分别为:单机模式(stand-alone)、集群模式和集群伪分布模式。ZooKeeper 单机模式的安装相对比较简单,如果第一次接触ZooKeeper的话,建议安装ZooKeeper单机模式或者集群伪分布模式。
-
安装单击模式。 至D:\machine\zookeeper-3.4.6\conf 复制 zoo_sample.cfg 并粘贴到当前目录下,命名zoo.cfg.
dataDir=D:\java\zookeeper\data
dataLogDir=D:\java\zookeeper\log
- cmd命令下进入D:\java\zookeeper\apache-zookeeper-3.5.9\bin目录下运行zkServer.cmd.如下图所示:
- 启动完成后cmd命令下,netstat-ano查看端口监听服务。
- cmd下进入D:\java\zookeeper\zookeeper-3.5.9\bin目录下运行zkCli.cmd.如下图所示:
安装集群伪分布模式。
1.0 修改 zoo.cfg 文件。如下图所示:
另存为zoo-1.cmd.
另存为zoo-2.cmd.
另存为zoo-3.cmd.
2 cmd下分别运行zkserver-1.cmd,zkserver-2.cmd,zkserver-3.cmd.
3 cmd下netstar-ano查看端口监听情况。
4 cmd下运行zkcli.cmd -server:localhost:2181;zkcli.cmd ;-server:localhost:2182;zkcli.cmd -server:localhost:2183.
5 zookeeper与java的连接
同上方
看自己版本