zookeeper分布式锁,解决了羊群效应, 真正的zookeeper 分布式锁
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 分布式锁的更多相关文章
- zookeeper分布式锁避免羊群效应(Herd Effect)
本文(转自:http://jm-blog.aliapp.com/?p=2554)主要讲述在使用ZooKeeper进行分布式锁的实现过程中,如何有效的避免“羊群效应( herd effect)”的出现. ...
- 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...
- Zookeeper——基本使用以及应用场景(手写实现分布式锁和rpc框架)
文章目录 Zookeeper的基本使用 Zookeeper单机部署 Zookeeper集群搭建 JavaAPI的使用 Zookeeper的应用场景 分布式锁的实现 独享锁 可重入锁 实现RPC框架 基 ...
- ZooKeeper 分布式锁 Curator 源码 03:可重入锁并发加锁
前言 在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的? 并发加锁 先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又创建了新的临时节点. ...
- 分布式交易系统的并发处理, 以及用Redis和Zookeeper实现分布式锁
交易系统 交易系统的数据结构 支付系统API通常需要一个“订单号”作为入参, 而实际调用API接口时使用到的往往不是真正意义的业务订单号, 而是交易订单号. 支付系统的API会使用“商户号+订单号” ...
- 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存
原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...
- 利用redis实现分布式事务锁,解决高并发环境下库存扣减
利用redis实现分布式事务锁,解决高并发环境下库存扣减 问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...
- springmvc单Redis实例实现分布式锁(解决锁超时问题)
一.前言 关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题 ...
- redis分布式锁解决超卖问题
redis事务 redis事务介绍: 1. redis事务可以一次执行多个命令,本质是一组命令的集合. 2.一个事务中的所有命令都会序列化,按顺序串行化的执行而不会被其他命令插入 作用:一个队列 ...
随机推荐
- hdu1435 稳定婚姻问题
题意: Stable Match Special Judge Problem Description Network 公司的BOSS 说现在他们公司建立的信号发射站和接收站经常出现信号发送接收不稳定的 ...
- UVA11549计算器谜题
题意: 有一个计算机只能保留数字的前n位,你有一个数字k(k<=9),反复平方后在计算机上显示的最大数字是多少. 思路: 显然这个题目是有循环节的,为什么有循环节?首先 ...
- 0803-PyTorch的Debug指南
0803-PyTorch的Debug指南 目录 一.ipdb 介绍 二.ipdb 的使用 三.在 PyTorch 中 Debug 四. 通过PyTorch实现项目中容易遇到的问题 五.第八章总结 py ...
- Andrew Ng机器学习算法入门(十):过拟合问题解决方法
在使用机器学习对训练数据进行学习和分类的时候,会出现欠拟合和过拟合的问题.那么什么是欠拟合和过拟合问题呢?
- 详解 WebRTC 传输安全机制:一文读懂 DTLS 协议
作者|进学 审校|泰一 DTLS (Datagram Transport Layer Security) 基于 UDP 场景下数据包可能丢失或重新排序的现实情况下,为 UDP 定制和改进的 TLS 协 ...
- 谷歌浏览器安装Vue.js devtools
第一步:访问谷歌商店 在之前的博客中已经谈到了这一点的实现方式 https://www.cnblogs.com/10134dz/p/13552777.html 第二步:下载Vue.js devtool ...
- SpringJUnit4ClassRunner requires JUnit 4.12 or higher
报错:需要Junit 4.12 或者更高的版本 原因:查看pom.xml文件引入的Junit版本为4.11 解决办法:修改Junit版本为4.12即可
- tp5.1中返回当天、昨天、当月等的开始和结束时间戳
/** * 返回今日开始和结束的时间戳 * * @return array */function today(){ list($y, $m, $d) = explode('-', date('Y-m- ...
- 还不懂 redis 持久化?看看这个
Redis 是一个内存数据库,为了保证数据不丢失,必须把数据保存到磁盘,这就叫做持久化. Redis 有两种持久化方法: RDB 方式以及 AOF 方式 RDB 持久化 前言 RDB持久化把内存中的数 ...
- Python自动扫描出微信不是好友名单
前言 最近找几个老友准备聊天发现几个已经被删除好友名单,做为潜水党多年的我已经不知道成为多少人的黑名单,但是好友列表却依然有不是好友的名单,面对庞大的好友数量想要清除谈何容易.虽然可以发消息给所有人, ...