分布式系列七: zookeeper简单用法
zookeeper是分布式开源框架, 是Google Chubby的一个实现, 主要作为分布式系统的协调服务. Dobbo等框架使用了其功能.
zookeeper特性
- 顺序一致性: 事务请求最终会严格按顺序执行
- 原子性:
- 可靠性:
- 实时性:
- 单一视图:
安装
使用windows的linux子系统时: cd /mnt/e/chromedownload/
转到windows下载路径
拷贝 cp /mnt/e/chromedownload/zookeeper.tar.gz /program/zookeeper.tar.gz
转到 cd /program
如果没有的先mkdir program
解压 tar -zxvf zookeeper.tar.gz
转到 cd ZK_HOME/conf
拷贝 cp zoo_sample.cfg zoo.cfg
转到 cd ZK_HOME/bin
启动 sh zkServer.sh start
集群搭建
- zoo.cfg中配置集群, 配置格式如
server.id=ip:port:port
; 有几台就配置几个.例如:
server.1=192.168.1.145:2897:3181
server.2=192.168.1.146:2897:3181
server.3=192.168.1.147:2897:3181 - zoo.cfg中的dataDir所配置的目录下新增myid文件, 值对应server.id的id
- zoo.cfg中, 如果需要observer,则添加
peerType=observer
, 并且修改server.id=ip:port:port:observer
zoo.cfg 配置
- tickTime=2000 zk的方法最小时间单位
- initTime=10 时长为10*tickTime, follow节点和leader节点同步的时间
- syncLimit=5 时长为5*tickTime, leader和follow几点进行心跳检测的最大延迟时间
- dataDir=/tmp/zookeeper 存储快照文件的目录
- dataLogDir = /log/zookeeper 事务日志的存储路径, 默认在dataDir下
- clientPort=2181 连接zookeeper的默认端口
zookeeper几个概念
- znode: zookeeper数据存储为树形结构, 深度层级没有限制, znode是数据存储节点,是zookeeper的最小存储单元. 分为1.持久化节点;2.持久化有序节点;3.临时节点;4.临时有序节点;
- 临时节点, 是会话时生成的节点, 会话结束后节点会自动删除.
客户端命令操作
help
可以查看客户端支持的命令
- create [-s] [-e] node : 创建节点 -s是有序 -e临时节点
- get path [watch] 获取节点的信息
- set path data [version] : 修改节点的值
- delete path [version] : 删除节点, 当节点有子节点时无法删除
[version] 乐观锁
[Watcher] 提供了发布/订阅, 允许客户端向服务器端注册一个监听, 当服务端触发指定事件时会触发watcher,服务端向客户端发送一个通知.
Watcher是一次性的, 触发一次后自动失效
信息节点
- stat path 可以查看节点的信息
cversion=0 子节点的版本
AclVersion=0 acl的版本号, 权限控制相关
dataVersion=1 数据的版本号
cxid 创建的事务id
mzxid 最后一次修改的事务id
pzxid 子节点最后一次修改的事务id
ephemeralOwner 临时会话的id
dataLength 数据长度
numChidren 子节点数量
java开发
引用依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.4-beta</version>
</dependency>
java代码
/**
* 定义Watcher
*/
public class MyWatcher implements Watcher {
@Override
public void process(WatchedEvent event) {
if(event.getState()== Event.KeeperState.SyncConnected){
System.out.println("---->>>>>"+event.getType());
System.out.println("---->>>>>"+event.getPath());
}
}
}
//测试
public class MySession {
private static final String CONN = "localhost:2181";
private static Stat stat = new Stat();
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
ZooKeeper zooKeeper = new ZooKeeper(CONN,1000,new MyWatcher());
// 创建
zooKeeper.create("/xlx","this is a string".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 查询,注册watcher
byte[] rst = zooKeeper.getData("/xlx",true,stat);
System.out.println(new String(rst));
//删除(只能删除永久节点)
zooKeeper.delete("/xlx",-1);
// 创建
zooKeeper.create("/xlx","this is a string".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 查询
byte[] rs = zooKeeper.getData("/xlx",true,stat);
System.out.println(new String(rs));
// 注册watcher
zooKeeper.exists("/xlx/yy",true);
// 创建
zooKeeper.create("/xlx/yy","this is a sub child string".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 获取子节点
List<String> children = zooKeeper.getChildren("/xlx", true);
System.out.println(children);
//删除(只能删除永久节点)
zooKeeper.delete("/xlx/yy",-1);
// 修改
zooKeeper.setData("/xlx","this is a modified string".getBytes(),-1);
byte[] rss = zooKeeper.getData("/xlx",true,stat);
System.out.println(new String(rss));
//删除(只能删除永久节点)
zooKeeper.delete("/xlx",-1);
// watcher 异步的, 这里停留段时间才可以查看到watcher打印的信息
Thread.sleep(2000);
}
}
三方API
- zkClient
- curator 这个用的较多,Netflix开源
curator开发
特点:
- 抽象层次更高
- 链式编程风格
- 异步回调
public class CuratorSession {
private static final String CONN = "localhost:2181";
public static void main(String[] args) throws Exception {
// 创建
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(CONN, 2000, 5000, new ExponentialBackoffRetry(1000,3));
curatorFramework.start();
System.out.println(curatorFramework.getState());
//另一种方式
//curatorFramework = CuratorFrameworkFactory.builder().build();
// 新增节点
curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/curator/chd/dd","dfadfe".getBytes());
//读取
byte[] data = curatorFramework.getData().forPath("/curator/chd/dd");
java.lang.String string = new java.lang.String(data);
System.out.println(string);
// 修改
Stat stat = curatorFramework.setData().forPath("/curator/chd/dd","fdaefv".getBytes());
System.out.println(stat);
curatorFramework.setData().inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println(event);
}
}).forPath("/curator/chd/dd","fafdae".getBytes());
//删除
curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath("/curator/chd");
Thread.sleep(2000);
}
}
zookeeper应用场景
分布式锁
可以使用redis,数据库,zookeeper等实现.
排他锁(写锁), 共享锁(读锁)发布/订阅(配置中心)
配置中心数据的特点: 1. 数据量比较小;2.各台服务器的配置内容一致;3.配置信息在运行时会发生变更;
配置中心有两种实现方式: pull,push; zookeeper结合这两种方式实现配置中心. 具体为: 客户端向服务器注册自己关注的节点, 当节点发生变化时, 服务器向客户端发送watcher事件通知,再由客户端pull变化的节点数据.
负载均衡
leader处理请求, 并将请求路由到特定节点. 核心是负载均衡的算法.
leader选举
命名服务
分布式队列
分布式锁实现(java api)
原理: 当需要锁时, 客户端会向服务端的节点A写有序的子节点, 此时可能有其他的客户端也同时需要获取锁,因此节点A下可能会有若干子节点001,002,003...., 然后客户端获取父节点A的所有子节点,并取得其中最小的节点001, 如果001是当前客户端创建的, 则当前客户端获取到锁;如果001不是当前客户端创建, 比如当前客户端创建了003, 则取003的前一个节点,也就是002添加监控watcher, 当002监控事件为删除时, 创建了003的客户端得到一个通知, 说明前一个节点已经释放, 此时003可以获取到锁.而002节点则监控001, 也就是说每个节点监控其前一个节点, 前一个节点释放, 则表示当前节点可以获取到锁了.
public class DistributeLock {
private static final String ROOT_LOCKS="/LOCK";
private ZooKeeper zooKeeper;
private int sessionTimeout;
private String lockID;
private final static byte[] date={1,2};
private CountDownLatch countDownLatch = new CountDownLatch(1);
public DistributeLock() throws IOException, InterruptedException {
this.zooKeeper = ZookeeperClient.getZookeeperClient();
this.sessionTimeout = ZookeeperClient.SESSIONTIMEOUT;
}
public boolean lock(){
try{
lockID = zooKeeper.create(ROOT_LOCKS+"/",date, ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(Thread.currentThread().getName()+"->成功创建了lock节点["+lockID+"], 开始去竞争锁");
List<String> childrenNodes = zooKeeper.getChildren(ROOT_LOCKS,true);
SortedSet<String> sortedSet = new TreeSet<>();
for(String children:childrenNodes){
sortedSet.add(ROOT_LOCKS+"/"+children);
}
String first = sortedSet.first();
if (first.equals(lockID)){
System.out.println(Thread.currentThread().getName()+"->成功获得锁,lock节点为:["+lockID+"]");
return true;
}
SortedSet<String> lessThanLockId = ((TreeSet<String>) sortedSet).headSet(lockID);
if (!lessThanLockId.isEmpty()){
String prevLockID = lessThanLockId.last();
zooKeeper.exists(prevLockID,new LockWatcher(countDownLatch));
countDownLatch.await(sessionTimeout,TimeUnit.MILLISECONDS);
System.out.println(Thread.currentThread().getName()+" 成功获取锁:["+lockID+"]");
}
}catch (Exception e){e.printStackTrace();}
return false;
}
public boolean unlock(){
System.out.println(Thread.currentThread().getName()+"->开始释放锁:["+lockID+"]");
try {
zooKeeper.delete(lockID,-1);
System.out.println("节点["+lockID+"]成功被删除");
return true;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
final CountDownLatch latch=new CountDownLatch(10);
Random random=new Random();
for(int i=0;i<10;i++){
new Thread(()->{
DistributeLock lock=null;
try {
lock=new DistributeLock();
latch.countDown();
latch.await();
lock.lock();
Thread.sleep(random.nextInt(500));
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
if(lock!=null){
lock.unlock();
}
}
}).start();
}
}
}
这些代码写下来就算入门了, curator真正有用的使用场景还没接触到, 比如分布式锁,leader选举等, curator有示例程序, 可以在github上查看Curator源码.
分布式系列七: zookeeper简单用法的更多相关文章
- 【Zookeeper系列】Zookeeper简单介绍(转)
原文链接:https://www.cnblogs.com/sunddenly/p/4033574.html 一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技 ...
- zookeeper编程入门系列之zookeeper实现分布式进程监控和分布式共享锁(图文详解)
本博文的主要内容有 一.zookeeper编程入门系列之利用zookeeper的临时节点的特性来监控程序是否还在运行 二.zookeeper编程入门系列之zookeeper实现分布式进程监控 三. ...
- Zookeeper概念学习系列之zookeeper实现分布式进程监控
不多说,直接上干货! 假设要监控多台服务器上的A程序运行状态, 当发现有服务器上的A程序下线的时候, 给管理员发短信, 并且尝试重启A程序. zookeeper实现分布式进程监控主要利用zk的临时节点 ...
- Zookeeper概念学习系列之zookeeper实现分布式共享锁
首先假设有两个线程, 两个线程要同时到mysql中更新一条数据, 对数据库中的数据进行累加更新.由于在分布式环境下, 这两个线程可能存在于不同的机器上的不同jvm进程中, 所以这两个线程的关系就是垮主 ...
- [转载] 跟着实例学习zookeeper 的用法
原文: http://ifeve.com/zookeeper-curato-framework/ zookeeper 的原生客户端库过于底层, 用户为了使用 zookeeper需要编写大量的代码, 为 ...
- 分布式协调服务Zookeeper集群监控JMX和ZkWeb应用对比
分布式协调服务Zookeeper集群监控JMX和ZkWeb应用对比 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. JMX是用来远程监控Java应用的框架,这个也可以用来监控其他的J ...
- [转]ZooKeeper学习第一期---Zookeeper简单介绍
ZooKeeper学习第一期---Zookeeper简单介绍 http://www.cnblogs.com/sunddenly/p/4033574.html 一.分布式协调技术 在给大家介绍ZooKe ...
- Java分布式:分布式锁之Zookeeper
Java分布式:分布式锁之Zookeeper 分布式锁系列教程重点分享锁实现原理 引入ZooKeeper ZooKeeper是什么呢? ZooKeeper 是一个开源的分布式协调服务,它可以在分布式系 ...
- C#基础系列——委托实现简单设计模式
前言:上一篇介绍了下多线程的相关知识:C#基础系列——多线程的常见用法详解,里面就提到了委托变量.这篇简单介绍下委托的使用.当然啦,园子里面很多介绍委托的文章都会说道:委托和事件的概念就像一道坎,过了 ...
随机推荐
- day12-内置模块学习(三)
我的博客呀,从以前的预习变成了复习了,复习的东西还没有写完,哎 今日目录 1.序列化模块 2.加密模块 3.包的使用 4.random模块 5.shutil模块 开始今日份总结 1.序列化模块 在学习 ...
- 转://ORA-00603,ORA-27501,ORA-27300,ORA-27301,ORA-27302故障案例一则
背景介绍: 这是一套windows的rac系统.数据库后台日志报ORA-00474:SMON process terminated with error.接着报ORA-00603,ORA-27501, ...
- .net core下用HttpClient和asp.net core实现https的双向认证
关于https双向认证的知识可先行google,这时矸接代码. 为了双向认证,我们首先得准备两个crt证书,一个是client.crt,一个是server.crt,有时为了验证是否同一个根证书的验证, ...
- Spring的事件机制详解
同步事件和异步事件 同步事件:在一个线程里,按顺序执行业务,做完一件事再去做下一件事. 异步事件:在一个线程里,做一个事的同事,可以另起一个新的线程执行另一件事,这样两件事可以同时执行. 用一个例子来 ...
- TensorRT&Sample&Python[network_api_pytorch_mnist]
本文是基于TensorRT 5.0.2基础上,关于其内部的network_api_pytorch_mnist例子的分析和介绍. 本例子直接基于pytorch进行训练,然后直接导出权重值为字典,此时并未 ...
- Python两大佬互相撕逼 技术何苦为难技术?
最近两天 Python 圈发生了一件大事,两个 Python 大佬撕逼了起来了. 不,其实是一个大佬(刘志军)被怼. 事情是这样的. 背景 人物介绍: 董明伟:公众号「Python 之美」的作者,似乎 ...
- 用JS解决url地址中参数乱码的问题
var url = window.location.herf;//获取url地址 var obj = {}; //最后输出的对象 var reg = /\?/; //要匹配的正则表达式 if(url. ...
- final和static关键字
1.如果类只有静态方法,可以将构造函数标记为private以避免被初始化: 2.常量同时标记为static和final,常量名全部大写,下划线连接: 3.final修饰一个成员变量(属性),必须要显示 ...
- SpringBoot2.0的CacheManager配置
http://rickgong.iteye.com/blog/2414263 @Configurationpublic class RedisConfig extends CachingConfigu ...
- Drag(拖拽)和Move(移动)两个脚本
Drag using System.Collections; using System.Collections.Generic; using UnityEngine; public class Dra ...