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. 有关 C# WebAPI知识

    1.[懒得安分博客总结的很全面] 2.关于基础类型作入参数的问题      参照此博客[ASP.NET WebAPI String 传值问题] 3.代码说明     using System; usi ...

  2. 第二章 Unicode简介

    /*------------------------------------------------------------- screensize.cpp -- Displays screen si ...

  3. 【csp模拟赛5】加减法--宽搜维护联通快

    题目大意: 一开始想用并查集,发现很难维护联通块的代表元素,所以用了宽搜,开数组会炸,所以开一个优先队列维护,每扫完一个联通块,统计答案,清空优先队列,!!千万记住注意数组的大小!!! 代码: #in ...

  4. javascript原型继承

    在传统的基于Class的语言如Java.C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass. 由于这类语言严格区分类和实例,继承实际上是类型的扩展.但是,JavaScript由 ...

  5. oracle表查询

    使用scott用户中存在的emp.dept表等做演示 一.单表查询 查看表结构:desc dept; 查看所有列:select * from dept: 查询指定列:select ename,sal, ...

  6. Mybatis源码学习之资源加载(六)

    类加载器简介 Java虚拟机中的类加载器(ClassLoader)负责加载来自文件系统.网络或其他来源的类文件.Java虚拟机中的类加载器默认使用的是双亲委派模式,如图所示,其中有三种默认使用的类加载 ...

  7. Netfilter 之 iptable_nat

    初始化 iptable_nat_table_init函数通过调用ipt_register_table完成NAT表注册和钩子函数注册的功能:该流程与iptable_filter的函数调用的函数一致,此处 ...

  8. ios-动态添加方法,交换方法,重定向方法

    新建一个类Person,Person.h 不写代码,Person.m 有如下两个方法: - (void)eat { NSLog(@"xxx eat===="); } [动态添加方法 ...

  9. Mac OS为UltraEdit在Terminal中添加快捷使用命令

    一,什么是UltraEdit 我觉得是个程序员,撸代码的都知道UrlEdit是什么.我们在会使用Linux,在Linux中有个很出名的编辑器gedit,使得我们在终端中输入gedit xxx.便可进入 ...

  10. 关于虚拟机可以ping通本机,本机可以ping通虚拟机,但是虚拟机就是不能上网

    1  需要确定虚拟的防火墙已经关闭 2 修改vi /etc/sysconfig/network-scripts/ifcfg-eth0配置文件  增加以下参数 BOOTPROTO=none------- ...