1、创建实例
/**
* 初始化单例的便捷方法
*/
public static void init() {
getInstance();
}

  

/**
* 获取单例
* @return
*/
public static ZooKeeperSession getInstance() {
return Singleton.getInstance();
}

  

/**
* 封装单例的静态内部类
* @author Administrator
*
*/
private static class Singleton {

   private static ZooKeeperSession instance;

   static {
instance = new ZooKeeperSession();
} public static ZooKeeperSession getInstance() {
return instance;
} }

 

zookeeper server,创建会话的时候,是异步去进行的,所以要给一个监听器,说告诉我们什么时候才是真正完成了跟zk server的连接。
	public ZooKeeperSession() {
// 去连接zookeeper server,创建会话的时候,是异步去进行的
// 所以要给一个监听器,说告诉我们什么时候才是真正完成了跟zk server的连接
try {
this.zookeeper = new ZooKeeper("192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181", 50000, new ZooKeeperWatcher());
// 给一个状态CONNECTING,连接中
System.out.println(zookeeper.getState()); try {
// CountDownLatch
// java多线程并发同步的一个工具类
// 会传递进去一些数字,比如说1,2 ,3 都可以
// 然后await(),如果数字不是0,那么久卡住,等待 // 其他的线程可以调用coutnDown(),减1
// 如果数字减到0,那么之前所有在await的线程,都会逃出阻塞的状态
// 继续向下运行 connectedSemaphore.await();
} catch(InterruptedException e) {
e.printStackTrace();
} System.out.println("ZooKeeper session established......");
} catch (Exception e) {
e.printStackTrace();
}
}

  

 

/**
* 建立zk session的watcher
* @author Administrator
*
*/
private class ZooKeeperWatcher implements Watcher {

   public void process(WatchedEvent event) {
System.out.println("Receive watched event: " + event.getState());
if(KeeperState.SyncConnected == event.getState()) {
connectedSemaphore.countDown();
}
} }

  

**********************************************************************************************************

/**
* 获取分布式锁
* @param productId
*/
public void acquireDistributedLock(Long productId) {
String path = "/product-lock-" + productId; try { /**

                ZooDefs.Ids.OPEN_ACL_UNSAFE标识节点path的接入权限。
                ZooDefs.Ids.OPEN_ACL_UNSAFE展开如下:
                public final ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList<ACL>(
                Collections.singletonList(new ACL(Perms.ALL, ANYONE_ID_UNSAFE)));
                其中ACL类是一个bean,包含两个参数如下:
                private int perms;
                private org.apache.zookeeper.data.Id id;

                CreateMode类型分为4种

                1.PERSISTENT--持久型

                2.PERSISTENT_SEQUENTIAL--持久顺序型

                3.EPHEMERAL--临时型

                4.EPHEMERAL_SEQUENTIAL--临时顺序型

                1、2种类型客户端断开后不会消失

                3、4种类型客户端断开后超时时间内没有新的连接节点将会消息

               **/
zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("success to acquire lock for product[id=" + productId + "]");
} catch (Exception e) {
// 如果那个商品对应的锁的node,已经存在了,就是已经被别人加锁了,那么就这里就会报错
// NodeExistsException
int count = 0;
while(true) {
try {
Thread.sleep(1000);
zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} catch (Exception e2) {
count++;
System.out.println("the " + count + " times try to acquire lock for product[id=" + productId + "]......");
continue;
}
System.out.println("success to acquire lock for product[id=" + productId + "] after " + count + " times try......");
break;
}
}
}

 

/**
* 释放掉一个分布式锁
* @param productId
*/
	public void releaseDistributedLock(Long productId) {
String path = "/product-lock-" + productId;
try {
zookeeper.delete(path, -1);
System.out.println("release the lock for product[id=" + productId + "]......");
} catch (Exception e) {
e.printStackTrace();
}
}

**********************************************************************************************************

2、实例应用

          // 加代码,在将数据直接写入redis缓存之前,应该先获取一个zk的分布式锁
ZooKeeperSession zkSession = ZooKeeperSession.getInstance();
zkSession.acquireDistributedLock(productId);
// 获取到了锁
// 先从redis中获取数据
ProductInfo existedProductInfo = cacheService.getProductInfoFromReidsCache(productId); if(existedProductInfo != null) {
// 比较当前数据的时间版本比已有数据的时间版本是新还是旧
try {
Date date = sdf.parse(productInfo.getModifiedTime());
Date existedDate = sdf.parse(existedProductInfo.getModifiedTime()); if(date.before(existedDate)) {
System.out.println("current date[" + productInfo.getModifiedTime() + "] is before existed date[" + existedProductInfo.getModifiedTime() + "]");
return;
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("current date[" + productInfo.getModifiedTime() + "] is after existed date[" + existedProductInfo.getModifiedTime() + "]");
} else {
System.out.println("existed product info is null......");
} try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} cacheService.saveProductInfo2LocalCache(productInfo);
System.out.println("===================获取刚保存到本地缓存的商品信息:" + cacheService.getProductInfoFromLocalCache(productId));
cacheService.saveProductInfo2ReidsCache(productInfo); // 释放分布式锁
zkSession.releaseDistributedLock(productId);

  

使用zookeeper作为分布式锁以及设计一种通知监听模式的更多相关文章

  1. zookeeper 实现分布式锁安全用法

    zookeeper 实现分布式锁安全用法 标签: zookeeper sessionExpire connectionLoss 分布式锁 背景 ConnectionLoss 链接丢失 SessionE ...

  2. java就业指南 zookeeper分布式系统 zookeeper实现分布式锁 有用

    目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们“任何一个 分布式系统都无法同时满足一致性(Consistency).可用性 ...

  3. Redis、Zookeeper实现分布式锁——原理与实践

    Redis与分布式锁的问题已经是老生常谈了,本文尝试总结一些Redis.Zookeeper实现分布式锁的常用方案,并提供一些比较好的实践思路(基于Java).不足之处,欢迎探讨. Redis分布式锁 ...

  4. 基于Zookeeper的分布式锁(干干干货)

    原文地址: https://juejin.im/post/5df883d96fb9a0163514d97f 介绍 为什么使用锁 锁的出现是为了解决资源争用问题,在单进程环境下的资源争夺可以使用 JDK ...

  5. zookeeper实现分布式锁服务

    A distributed lock base on zookeeper. zookeeper是hadoop下面的一个子项目, 用来协调跟hadoop相关的一些分布式的框架, 如hadoop, hiv ...

  6. [ZooKeeper.net] 3 ZooKeeper的分布式锁

    基于ZooKeeper的分布式锁 ZooKeeper 里实现分布式锁的基本逻辑: 1.zookeeper中创建一个根节点(Locks),用于后续各个客户端的锁操作. 2.想要获取锁的client都在L ...

  7. 基于 Zookeeper 的分布式锁实现

    1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个“类 Unix/Linu ...

  8. zookeeper的分布式锁

    实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...

  9. 基于Zookeeper的分布式锁

    实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...

随机推荐

  1. 【EXE报错】win10运行C#程序保存报错:HTTP 无法注册URL ,进程不具有此命名空间的访问权限

    在win10系统运行C#程序出现以下报错 异常信息 [1]异常信息:HTTP 无法注册 URL http://+:13000/Core/Real/HandheldService/.进程不具有此命名空间 ...

  2. 查看PublicKeyToken和生成PublicKeyToken

    http://hi.baidu.com/honfei/item/7777500b20d8ff8a02ce1bd2

  3. Linux下 Nginx 启动 重启 关闭

    命令 nginx -s reload :修改配置后重新加载生效 nginx -s reopen :重新打开日志文件 nginx -t -c /path/to/nginx.conf 测试nginx配置文 ...

  4. vue子组件通知父组件使用方法

    vue子组件通知父组件使用方法 <template> <mt-field placeholder="验证码" v-model="getverifycod ...

  5. mysql 查看当前正在执行的语句

    查看当前正在执行的语句 show processlist:show processlist; 结束正在执行的语句进程 kill 进程id

  6. 【平台中间件】为什么用etcd而不用ZooKeeper?从应用场景到实现原理的全方位解读

    前言 博主在工作过程中经常接触到ETCD,搜索相关资料的时候发现排名最高的是一篇图片全是404的转载文章,后来看到了原文,感觉有义务让更多的人看到这样的精品文章,所以进行了转载. 原文发布在infoQ ...

  7. CISCN final 几道web题总结

    因为都有源码,所以这里直接从源码开始分析: 1.Easy web 这道题本来的意思应该是通过注入来load_file读取config.php来泄露cookie的加密密钥,从而伪造身份进行登陆再上传sh ...

  8. (转载)IOCP 浅析

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-iocp/#author   郭 仁祥, 软件工程师, IBM 简介: 传统的 Server/Cli ...

  9. antd源码分析之——栅格(Grid)

    官方文档 https://ant.design/components/grid-cn/ 目录 一.antd中的Grid 代码目录 1.整体思路 2.less文件结构图(♦♦♦重要) 3.less实现逻 ...

  10. PHP-生产随机密码

    public function dd(){ error_reporting(E_ALL^E_NOTICE^E_WARNING);$arr1 = array(0,1,2,3,4,5,6,7,8,9);$ ...