上一篇写了zookeeper的集群配置,这一篇写一下zookeeper的基本理解,有问题希望大家支持,刚学不久,分享一下.
这一篇主要是说zookeeper能为我们带来什么,和一些基本的代码:
Zookeeper的主要用处:
1.数据发布与订阅(配置中心);
监听节点的改变获取节点改变的值例如定义全局配置 zookeeper的节点只能存放少量的数据
2.负载均衡:
软负载均衡: kafka就是通过zookeeper来实现负载均衡
将所有broker和对应的分区信息(partition)以及消费者的信息都注册在zookeeper上面
生产者通过拿到broker和partition来(通过算法来指定broker和partition)发送消息
由于一个partition只能有一个消费者来消费消息,所以当消费者死亡时,zookeeper必须第一时间知道.
将死亡的消费者剔除,重新在消费者端进行负载均衡
3.命名服务(Naming Service):
客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息
4.分布式通知/协调:
因为可以监听节点的变化,当一个节点改变时,另一个节点因为监听了这个节点的变化,做出了相应的反应 降低系统的耦合度
5.集群管理与Master选举:
集群管理,将所有机器注册在zookeeper中,此时有两种方案
1. 将所有的机器都注册为临时节点,当连接断开时节点自动消失,这台机器也就退出了集群
2. 将所有的机器注册为永久节点,通过心跳检测来判断节点是否存活心跳检测:也就是通过感知节点的变化
Master选举:这个可以百度fast paxos算法
6.分布式锁:顺序节点是唯一的,排他锁 共享锁
排他锁:根据顺序节点的唯一性,先创建节点的拥有节点的所有权可以进行读写 其他的需要排队
共享锁:以读写进行区分 需要排队 如果读操作前面都是读操作 那么可以直接读取 如果有写操作那么需要排队 直到前面排 队的所有写操作完成
如果写操作前面有排队的 不管是读操作还是写操作都需要排队
7.分布式队列:根据顺序节点,先来的先拿到节点,先来的节点序号比较小,先出队,比较节点大小,小的先执行。
zookeeper的好处: 本身就是分布式的 只有一个master 可以百度ZAB的原子广播 也就是ZAB协议
顺序一致性:
原子性:
单一视图:所有服务看见的数据是一致的
可靠性:
实时性:在一定时间内读到最新的数据
zookeeper创建节点的类型:
持久化节点:
临时节点:连接断开节点消失
顺序节点:按照顺序来创建节点
代码:
maven依赖:
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
zookeeperdemo
package zk; import org.I0Itec.zkclient.ZkClient; import org.I0Itec.zkclient.serialize.SerializableSerializer; import org.apache.zookeeper.CreateMode; public class ZookeeperDemo { public static void main(String[] args) throws InterruptedException { //ip 加 端口号 String zkServers = "localhost:2181,localhost:2182,localhost:2183"; //会话超时 连接超时都为10秒 节点序列化 ZkClient zkClient = new ZkClient(zkServers, 10000, 10000, new SerializableSerializer()); System.err.println("连接成功"); User user = new User(); user.setId(1); user.setName("222"); //节点路径 存放的数据 节点类型 持久化节点 String path = zkClient.create("/testNode", user, CreateMode.PERSISTENT); System.err.println("创建节点成功" + path); //获取数据 User user1 = zkClient.readData("/testNode"); System.err.println(user.getName()); //判断节点是否存在 System.err.println(zkClient.exists("/testNode")); //修改节点数据 zkClient.writeData("/testNode", 111); //获取节点数据 Integer i = zkClient.readData("/testNode"); System.err.println(i); //删除节点 zkClient.delete("/testNode"); String path1 = zkClient.create("/testNode", "22", CreateMode.PERSISTENT); //监听节点的子节点改变 zkClient.subscribeChildChanges("/testNode", new ZkListener()); //监听节点数据的改变 zkClient.subscribeDataChanges("/testNode/node1", new ZkListenerData()); Thread.sleep(3000); zkClient.writeData("/testNode", "你来了"); zkClient.delete("/testNode/node1"); Thread.sleep(Integer.MAX_VALUE); } }
User
package zk;
import java.io.Serializable;
public class User implements Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ZkListener
package zk;
import org.I0Itec.zkclient.IZkChildListener;
import java.util.List;
public class ZkListener implements IZkChildListener {
//监听子节点的变化
public void handleChildChange(String parentPath, List<String> children) throws Exception {
System.err.println("父节点" + parentPath);
System.err.println("子节点" + children);
}
}
ZkListenerData
package zk;
import org.I0Itec.zkclient.IZkDataListener;
public class ZkListenerData implements IZkDataListener {
public void handleDataChange(String dataPath, Object data) throws Exception {
System.out.println("节点被修改");
System.err.println(data);
}
public void handleDataDeleted(String dataPath) throws Exception {
System.out.println("节点被删除");
}
}