####排它锁 + 在需要获取排它锁时,通过调用create()接口,创建临时子节点。zk会保证在所有客户端中,只有一个会创建成功,从而获取锁。 + 其他客户端注册该节点的变更watch监听,在锁释放后重新竞争 + 获取锁的客户端宕机或者完成后,临时节点删除释放锁
共享锁(读锁)
也是创建临时顺序节点,可以被多个事务持有,根据节点序号确定读写锁的执行顺序(原理是减小锁的范围)
分布式队列(FIFO)
- 类似创建多个共享读锁,根据创建的临时节点的序号
- 通过getChindren获取所有子节点,获取队列中的所有元素
- 如果自己不是序号最小的节点则等待,同时向序号比自己小的最后一个节点注册watcher监听
zk和kafka
- kafka主题topic,用于建立生产者和消费者之间的订阅关系,生产者发送消息到指定topic下,消费者从这个topic消费(可以按照业务区分)
- 消息分区partitin,类似3个节点6个分区,(00,01;11,12;21,22)
- broker是kafka的服务器,用于存储消息
- 消费者分组group,拥有同一个分组名称,也被称为消费者集群
####加载依赖 ```bash
import java.util.List;
@Controller
public class ZkClientController {
public static void main(String[] args) throws Exception {
ZkClient zkClient = new ZkClient("172.16.67.131:2181,172.16.67.131:2182,172.16.67.131:2183");
System.out.println("ZkClient connect begin");
String basePath = "/zk-test";
//递归创建节点,永久节点
String newPath = "/zk-test/c1";
zkClient.createPersistent(newPath, true);
//获取子节点
List<String> list = zkClient.getChildren(basePath);
System.out.println("count: " + zkClient.countChildren(basePath));
for (String item : list) {
System.out.println(item);
}
//子节点变更订阅
zkClient.subscribeChildChanges(basePath, new IZkChildListener() {
@Override
public void handleChildChange(String parentPath, List<String> currentChildren) throws Exception {
System.out.println(parentPath + " changed,child: " + currentChildren);
}
});
System.out.println(zkClient.getChildren(basePath));
Thread.sleep(1000);
if(!zkClient.exists(basePath+"/c2")){
zkClient.createPersistent(basePath + "/c2");
Thread.sleep(1000);
}
zkClient.delete(basePath + "/c2");
Thread.sleep(1000);
//节点内容变更订阅,创建临时节点
zkClient.createEphemeral(basePath + "/c3", "123".getBytes());
zkClient.subscribeDataChanges(basePath + "/c3", new IZkDataListener() {
@Override
public void handleDataChange(String dataPath, byte[] data) throws Exception {
System.out.println("node " + dataPath + " change to " + new String(data));
}
@Override
public void handleDataDeleted(String dataPath) throws Exception {
System.out.println("node " + dataPath + " deleted");
}
});
System.out.println(new String(zkClient.readData(basePath + "/c3")));
zkClient.writeData(basePath+"/c3","456".getBytes());
Thread.sleep(1000);
zkClient.delete(basePath+"/c3");
Thread.sleep(1000);
}
}
####输出结果
```bash
ZkClient connect begin
count: 1
c1
[c1]
/zk-test changed,child: [c1, c2]
/zk-test changed,child: [c1]
/zk-test changed,child: [c3, c1]
123
node /zk-test/c3 change to 456
node /zk-test/c3 deleted
/zk-test changed,child: [c1]