zookeeper 实现分布式锁,监听前一个节点来避免羊群效应,

思路:很简单,但是实现起来要麻烦一些, 而且我也是看了很多帖子,发现很多帖子的代码,下载下来逐步调试之后发现,看起来是对的,但在并发情况下运行,就会出现问题. 有的在代码里其实并没有真正实现(监听前一个节点),

接下来分享一个: 真正的zookeeper 分布式锁: 这个也是别人的代码,自己只是搬运工,很遗憾,我自己写的分布式锁,看起来是对的,但是出现了并发问题,

    package tech.codestory.zookeeper.aalvcai.base_I0Itec_ZK_lock;

    import lombok.extern.slf4j.Slf4j;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient; import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; /**
* @author 邱润泽
**/
@Slf4j
public class ZookeeperLock {
private String server = "127.0.0.1:2181";
private ZkClient zkClient;
private static final String rootPath = "/qiurunze-lock1"; public ZookeeperLock() {
zkClient = new ZkClient(server, 5000, 20000);
buildRoot();
} // 构建根节点
public void buildRoot() {
if (!zkClient.exists(rootPath)) {
zkClient.createPersistent(rootPath);
}
}
// 获取锁
public Lock lock(String lockId, long timeout) {
// 创建临时节点
Lock lockNode = createLockNode(lockId);
lockNode = tryActiveLock(lockNode);// 尝试激活锁
if (!lockNode.isActive()) {
try {
synchronized (lockNode) {
lockNode.wait(timeout); // 线程锁住
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (!lockNode.isActive()) {
throw new RuntimeException(" lock timeout");
}
return lockNode;
} // 释放锁
public void unlock(Lock lock) {
if (lock.isActive()) {
zkClient.delete(lock.getPath());
}
} // 尝试激活锁
private Lock tryActiveLock(Lock lockNode) { // 获取根节点下面所有的子节点
List<String> list = zkClient.getChildren(rootPath)
.stream()
.sorted()
.map(p -> rootPath + "/" + p)
.collect(Collectors.toList()); // 判断当前是否为最小节点
log.info("Thread: {}, list : {}",Thread.currentThread().getName(),list); String firstNodePath = list.get(0);
log.info("Thread: {}, firstNodePath: {}",Thread.currentThread().getName(),firstNodePath);
// 最小节点是不是当前节点
if (firstNodePath.equals(lockNode.getPath())) {
lockNode.setActive(true);
} else {
String upNodePath = list.get(list.indexOf(lockNode.getPath()) - 1);
log.info("Thread: {},监听的节点是: {}",Thread.currentThread().getName(),upNodePath);
zkClient.subscribeDataChanges(upNodePath, new IZkDataListener() {
@Override
public void handleDataChange(String dataPath, Object data) throws Exception {
}
@Override
public void handleDataDeleted(String dataPath) throws Exception {
// 事件处理 与心跳 在同一个线程,如果Debug时占用太多时间,将导致本节点被删除,从而影响锁逻辑。
System.out.println("节点删除:" + dataPath);
Lock lock = tryActiveLock(lockNode);
synchronized (lockNode) {
if (lock.isActive()) {
lockNode.notify(); // 释放了
}
}
zkClient.unsubscribeDataChanges(upNodePath, this);
}
});
}
return lockNode;
} public Lock createLockNode(String lockId) {
String nodePath = zkClient.createEphemeralSequential(rootPath + "/" + lockId, "w");
return new Lock(lockId, nodePath);
}
} class Test01{
static volatile int num = 0;
static ZookeeperLock zookeeperLock = new ZookeeperLock();
public static void main(String[] args){
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
Lock zkLock = zookeeperLock.lock("lvcai", 5000 );
TimeUnit.MILLISECONDS.sleep(100);
for (int j = 0; j < 10; j++) {
num++;
}
System.out.println( "num的值是 : "+ num );
zookeeperLock.unlock(zkLock);
} catch (Exception e) {
e.printStackTrace();
}
},"线程"+i).start();
}
}
} class Lock {
private String lockId;
private String path;
private boolean active;
public Lock(String lockId, String path) {
this.lockId = lockId;
this.path = path;
} public Lock() {
} public String getLockId() {
return lockId;
} public void setLockId(String lockId) {
this.lockId = lockId;
} public String getPath() {
return path;
} public void setPath(String path) {
this.path = path;
} public boolean isActive() {
return active;
} public void setActive(boolean active) {
this.active = active;
}
}

zookeeper分布式锁,解决了羊群效应, 真正的zookeeper 分布式锁的更多相关文章

  1. zookeeper分布式锁避免羊群效应(Herd Effect)

    本文(转自:http://jm-blog.aliapp.com/?p=2554)主要讲述在使用ZooKeeper进行分布式锁的实现过程中,如何有效的避免“羊群效应( herd effect)”的出现. ...

  2. 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁

    首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...

  3. Zookeeper——基本使用以及应用场景(手写实现分布式锁和rpc框架)

    文章目录 Zookeeper的基本使用 Zookeeper单机部署 Zookeeper集群搭建 JavaAPI的使用 Zookeeper的应用场景 分布式锁的实现 独享锁 可重入锁 实现RPC框架 基 ...

  4. ZooKeeper 分布式锁 Curator 源码 03:可重入锁并发加锁

    前言 在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的? 并发加锁 先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又创建了新的临时节点. ...

  5. 分布式交易系统的并发处理, 以及用Redis和Zookeeper实现分布式锁

    交易系统 交易系统的数据结构 支付系统API通常需要一个“订单号”作为入参, 而实际调用API接口时使用到的往往不是真正意义的业务订单号, 而是交易订单号.  支付系统的API会使用“商户号+订单号” ...

  6. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  7. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  8. springmvc单Redis实例实现分布式锁(解决锁超时问题)

    一.前言 关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题 ...

  9. redis分布式锁解决超卖问题

    redis事务 redis事务介绍:    1. redis事务可以一次执行多个命令,本质是一组命令的集合. 2.一个事务中的所有命令都会序列化,按顺序串行化的执行而不会被其他命令插入 作用:一个队列 ...

随机推荐

  1. 编译Android 4.4源代码并烧录到Nexus4

    环境准备: 基本环境:ubuntu-12.04-desktop-64bit(裸机或者Windows下虚拟机安装均可,14.04也可以) 其他要求:空闲磁盘空间100G以上,代码部分接近10G,内存越大 ...

  2. Linux内核升级、GRUB2引导故障处理与密码破解

    目录 内核升级 GRUB2内核启动设置 GRUB2引导菜单加密 GRUB2引导故障及修复 救援模式管理 Rhel7破解root密码 内核升级 查看当前内核版本: uname  -r 查看可升级内核:  ...

  3. poj2175费用流消圈算法

    题意:      有n个建筑,每个建筑有ai个人,有m个避难所,每个避难所的容量是bi,ai到bi的费用是|x1-x2|+|y1-y2|+1,然后给你一个n*m的矩阵,表示当前方案,问当前避难方案是否 ...

  4. [CTF]Rabbit加密

    [CTF]Rabbit加密 ---------------------  作者:adversity`  来源:CSDN  原文:https://blog.csdn.net/qq_40836553/ar ...

  5. 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素2

    [python]Leetcode每日一题-寻找旋转排序数组中的最小元素2 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...

  6. php 获取某文件夹(比如共享文件夹)下图片并下载并压缩成zip

    1.前端部分:直接请求 2.后端php //zip下载public function downZip(){ $pro_code = "test"; //zip名称 //获取列表 $ ...

  7. Mybatis学习之自定义持久层框架(三) 自定义持久层框架:读取并解析配置文件

    前言 前两篇文章分别讲解了JDBC和Mybatis的基本知识,以及自定义持久层框架的设计思路,从这篇文章开始,我们正式来实现一个持久层框架. 新建一个项目 首先我们新建一个maven项目,将其命名为I ...

  8. 理解微信小程序的双线程模型

    有过微信小程序开发经验的朋友应该都知道"双线程模型"这个概念,本文简单梳理一下双线程模型的一些科普知识,学识浅薄,若有错误欢迎指正. 我以前就职于「小程序·云开发」团队,在对外的一 ...

  9. Android面试必问!View 事件分发机制,看这一篇就够了!

    在 Android 开发当中,View 的事件分发机制是一块很重要的知识.不仅在开发当中经常需要用到,面试的时候也经常被问到. 如果你在面试的时候,能把这块讲清楚,对于校招生或者实习生来说,算是一块不 ...

  10. golang:并发编程总结

    并行和并发 并发编程是指在一台处理器上"同时"处理多个任务. 宏观并发:在一段时间内,有多个程序在同时运行. 微观并发:在同一时刻只能有一条指令执行,但多个程序指令被快速的轮换执行 ...