网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
dataDir=/opt/zookeeper/data/zk3
clientPort=2183
server.1=ubuntu:2888:3888
server.2=ubuntu:2889:3889
server.3=ubuntu:2890:3890
配置说明:
tickTime
:这个时间是作为 Zookeeper server之间或client与server之间维持心跳的时间间隔,也就是每一个 tickTime 时间就会发送一个心跳。initLimit
:这个配置项是用来配置 Zookeeper 接受client(这里所说的client不是用户连接 Zookeeper server的client,而是 Zookeeper server集群中连接到 Leader 的 Follower server)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10个心跳的时间(也就是 tickTime)长度后 Zookeeper server还没有收到client的返回信息,那么表明这个client连接失败。syncLimit
:这个配置项标识 Leader 与 Follower 之间发送消息。请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度。dataDir
:Zookeeper 保存数据的文件夹,默认情况下,Zookeeper 将写数据的日志文件也保存在这个文件夹里。clientPort
:这个port就是client连接 Zookeeper server的port。Zookeeper 会监听这个port,接受client的访问请求。server.A=B:C:D
:当中 A 是一个数字。表示这个是第几号server;B 是这个server的 ip 地址;C 表示的是这个server与集群中的 Leader server交换信息的port;D 表示的是万一集群中的 Leader server挂了。须要一个port来又一次进行选举。选出一个新的 Leader。而这个port就是用来运行选举时server相互通信的port。假设是伪集群的配置方式,因为 B 都是一样,所以不同的 Zookeeper 实例通信port号不能一样,所以要给它们分配不同的port号。
创建zookeeper保存数据文件:
sudo mkdir -p /opt/zookeeper/data/zk1
sudo mkdir -p /opt/zookeeper/data/zk2
sudo mkdir -p /opt/zookeeper/data/zk3
创建节点标识:
在下面三个文件夹下分别创建myid文件
里面分别写1、2、3用于标识第几号server
cd /opt/zookeeper/data/zk1
echo 1 > myid
cd /opt/zookeeper/data/zk2
echo 2 > myid
cd /opt/zookeeper/data/zk3
echo 3 > myid
🕘 5.3 启动Zookeeper
cd /opt/zookeeper/
sudo chmod -R 777 data/
./bin/zkServer.sh start conf/zoo1.cfg
./bin/zkServer.sh start conf/zoo2.cfg
./bin/zkServer.sh start conf/zoo3.cfg
查看启动状态:
./bin/zkServer.sh status conf/zoo1.cfg
./bin/zkServer.sh status conf/zoo2.cfg
./bin/zkServer.sh status conf/zoo3.cfg
运行截图:
验证zookeeper安装的正确性:
./bin/zkCli.sh -server 127.0.0.1:2182
如果连接成功,会有Welcome to zookeeper!和state状态等信息。证明已经成功连接到zookeeper服务。
停止server的命令:
./bin/zkServer.sh stop conf/zoo1.cfg
./bin/zkServer.sh stop conf/zoo2.cfg
./bin/zkServer.sh stop conf/zoo3.cfg
🕒 6. ZooKeeper的Shell操作
🕘 6.1 帮助手册
[zk: 127.0.0.1:2182(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT\_RECURSIVE] - default is PERSISTENT\_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b|-N|-B] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b|-N|-B val path
stat [-w] path
sync path
version
whoami
Command not found: Command not found help
[zk: 127.0.0.1:2182(CONNECTED) 1]
🕘 6.2 查看当前节点数据
🕘 6.3 查看当前Zookeeper中所包含的内容
🕘 6.4 创建节点
创建节点命令格式:create [-s] [-e] [-c] [-t ttl] path [data] [acl]
-s
:指定ZNode的类型为顺序节点。-e
:指定ZNode的类型为临时节点,若不指定,则表示永久节点。path
:表示创建的路径data
:表示创建节点的数据,这是因为Znode可以像目录一样存在也可以像文件一样保存数据。Acl
:进行权限控制。一般不需要了解。
示例:创建临时节点
🕘 6.5 获取节点
获取节点命令格式:get [-s] [-w] path
-s
:查看指定ZNode的属性。-w
:向指定ZNode注册Watcher。
获取Zookeeper指定节点的数据内容以及属性信息:
🕘 6.6 修改节点
修改节点命令格式:set [-s] [-v version] path data
data
:表示要修改的内容,该数据内容不允许出现空格。version
:表示数据版本
对前面创建的临时节点testnode-temp进行修改,使得节点内容变成“123”的操作:
🕘 6.7 监听节点
监听节点就是监听节点变化,概括为三个过程。客户端向服务端注册Watch、服务端事件发生触发Watch、客户端回调Watch得到触发事件的情况。
🕘 6.8 删除节点
删除节点命令格式:delete [-v version] path
使用delete命令删除节点时,若要删除的节点存在子节点,就无法删除该节点,必须先删除子节点,才可删除父节点。使用rmr
命令递归删除节点,不论该节点下是否存在子节点,可以直接删除。
🕒 7. ZooKeeper的Java API操作
Zookeeper API包含五个包:
org.apache.zookeeper
org.apache.zookeeper.data
org.apache.zookeeper.server
org.apache.zookeeper.server.quorum
org.apache.zookeeper.server.upgrade
org.apache.zookeeper包含Zookeeper类,这也是编程时最常用的类文件,Zookeeper类提供的常用Java API方法。
方法名称 | 方法描述 |
---|---|
create | 创建节点 |
delete | 删除节点 |
exists | 判断节点是否存在 |
get/setData | 获取/修改节点数据 |
getChildren | 获取指定节点下的所有子节点列表 |
🕘 7.1 在Eclipse中搭建ZooKeeper环境
新建Java项目,取名ZooKeeperDemo
,之后Next,添加依赖
导入全部依赖,之后新建类ZKTest
,开始写代码
🕘 7.2 创建会话
import org.apache.zookeeper.\*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
getConnect();
}
// 连接ZooKeeper服务
public static ZooKeeper getConnect()
throws IOException,InterruptedException {
String zkServer = "Ubuntu:2181"; // 此处Ubuntu改成自己的主机名
CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper = new ZooKeeper(zkServer, 3000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("通知状态:"+watchedEvent.getState() + "\t"
+ "事件类型:" + watchedEvent.getType() + "\t"
+ "节点路径:" + watchedEvent.getPath());
if (Event.KeeperState.SyncConnected == watchedEvent.getState()){
countDownLatch.countDown();
}
}
});
countDownLatch.await();
return zooKeeper;
}
}
如图所示即成功连接。
🕘 7.3 创建ZNode
创建持久节点zkapi,并且在持久节点zkapi中挂载子节点zkChild,该子节点的ZNode类型为持久节点,createNode()方法的代码如下。
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
createNode();
}
// 使用create方法创建ZNode
public static void createNode()
throws IOException, InterruptedException, KeeperException {
ZooKeeper connect = getConnect();
connect.create(
"/zkapi",
"fruit".getBytes(),
ZooDefs.Ids.OPEN\_ACL\_UNSAFE,
CreateMode.PERSISTENT);
connect.create(
"/zkapi/zkChild",
"apple".getBytes(),
ZooDefs.Ids.OPEN\_ACL\_UNSAFE,
CreateMode.PERSISTENT);
}
}
🕘 7.4 判断ZNode是否存在
判断永久节点zkapi是否存在,existsNode()方法的代码如下所示。
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
Stat stat = existsNode();
if (stat != null){
System.out.println("已存在");
}else {
System.out.println("不存在");
}
}
// 使用exists方法判断ZNode是否存在
public static Stat existsNode()
throws IOException, InterruptedException, KeeperException {
ZooKeeper connect = getConnect();
Stat exists = connect.exists("/zkapi", true);
return exists;
}
}
🕘 7.5 获取ZNode的数据内容
获取永久节点zkapi的数据内容,getNode()方法的代码如下所示。
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
byte[] nodeData = getNode();
System.out.println("持久节点zkapi的数据内容为:"+new String(nodeData));
}
// 使用getData方法获取ZNode的数据内容
public static byte[] getNode()
throws IOException, InterruptedException, KeeperException {
ZooKeeper connect = getConnect();
byte[] data = connect.getData("/zkapi", true, null);
return data;
}
}
🕘 7.6 修改ZNode的数据内容
将持久节点zkapi的数据内容修改为fruit_new,updateNode()方法的代码如下。
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
Stat beforeStat = existsNode();
System.out.println("持久节点zkapi修改数据内容前的数据版本号:"
+beforeStat.getVersion());
System.out.println("持久节点zkapi修改数据内容前的数据内容长度:"
+beforeStat.getDataLength());
byte[] beforeNode = getNode();
System.out.println("持久节点zkapi修改数据内容前的数据内容:"
+new String(beforeNode));
Stat afterStat = updateNode();
System.out.println("持久节点zkapi修改数据内容后的数据版本号:"
+afterStat.getVersion());
System.out.println("持久节点zkapi修改数据内容后的数据内容长度:"
+afterStat.getDataLength());
byte[] afterNode = getNode();
System.out.println("持久节点zkapi修改数据内容后的数据内容:"
+new String(afterNode));
}
// 使用setData方法修改ZNode的数据内容
public static Stat updateNode()
throws IOException, InterruptedException, KeeperException {
ZooKeeper connect = getConnect();
Stat stat = connect.setData(
"/zkapi",
"fruit\_new".getBytes(),
-1);
return stat;
}
}
🕘 7.7 查看ZNode的子节点列表
查看持久节点zkapi的子节点列表,getChildNode()方法的代码如下。
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
List<String> childNodes = getChildNode();
for (String childNode : childNodes) {
System.out.println("持久节点zkapi的子节点:"+childNode);
}
}
// 使用getChildren方法查看ZNode的子节点列表
public static List<String> getChildNode()
throws IOException, InterruptedException, KeeperException {
ZooKeeper connect = getConnect();
List<String> nodeList = connect.getChildren("/zkapi", false);
return nodeList;
}
}
🕘 7.8 删除ZNode
该方法用于删除持久节点zkapi的子节点zkChild,deleteNode()方法的代码如下。
public class ZKTest {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
deleteNode();
List<String> childNodes = getChildNode();
for (String childNode : childNodes) {
System.out.println("持久节点zkapi的子节点:"+childNode);
}
}
// 使用delete方法删除ZNode
public static void deleteNode()
throws IOException, InterruptedException, KeeperException {
ZooKeeper connect = getConnect();
connect.delete("/zkapi/zkChild",-1);
}
}
🕒 8. ZooKeeper典型应用场景
🕘 8.1 数据发布/订阅
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
connect.delete("/zkapi/zkChild",-1);
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a7795934f2b64fd5bbac388319d339ed.png)
## 🕒 8. ZooKeeper典型应用场景
### 🕘 8.1 数据发布/订阅
[外链图片转存中...(img-PPI1R9pB-1715499761870)]
[外链图片转存中...(img-yY85zMCJ-1715499761870)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**