Test

Enumerable.Range(1, 5).ToList().ForEach(i =>
{
Task.Run(() =>
{ var lockHelper = new ZooKeeperLockHelper("localhost:5181");
lockHelper.OnAcquireLock += (id) =>
{
var random = new Random().Next(10);
Log.Debug("NodeId {@id} executing.....Sleep {@ms} ms", id, random * 1000); Thread.Sleep(random * 1000);
Log.Debug("NodeId {@id} executing success", id); return Task.CompletedTask;
}; lockHelper.AcquireLock(); }); });
using org.apache.zookeeper;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; namespace RedisDemo
{
public class ZooKeeperLockHelper : Watcher, IDisposable
{ #region event public event Func<long, Task> OnAcquireLock;
#endregion private bool _disposed; private ZooKeeper _zooKeeper;
private Event.KeeperState _currentState;
private AutoResetEvent _notifyEvent = new AutoResetEvent(false); private string _connectionString; private bool _hasAcquireLock;
private string _lockPath;
private long _currentNodeId; private static readonly string DEFAULT_PATH = "/zk";
private static readonly string NODE_NAME = "node-"; public ZooKeeperLockHelper(string connectionString)
{
_connectionString = connectionString;
this.Initialize(_connectionString, TimeSpan.FromSeconds(60));
} public void AcquireLock(string path = "")
{
if (this._hasAcquireLock)
{
FireAcquireLock(this._currentNodeId).Wait();
return;
} if (!WaitConnected(TimeSpan.FromSeconds(10)))
{
throw new Exception($"{_connectionString} Cannot Connect ZooKeeper");
} _lockPath = path;
if (string.IsNullOrEmpty(_lockPath))
{
_lockPath = DEFAULT_PATH;
} var nodePath = _lockPath + "/" + NODE_NAME; var spath = this._zooKeeper.createAsync(
nodePath, Encoding.UTF8.GetBytes("data"),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL).Result;
this._currentNodeId = ParseNodeId(spath); var reuslt = this._zooKeeper.getChildrenAsync(_lockPath, true).GetAwaiter().GetResult();
Log.Debug("#-> Begin Acquire Lock CurrentId {@id}", _currentNodeId); if (this.IsMinNodeId(reuslt, this._currentNodeId))
{
lock (this)
{
if (!this._hasAcquireLock)
{
Log.Debug("NodeId {@id} Direct Acquire Lock", _currentNodeId);
this._hasAcquireLock = true;
this.FireAcquireLock(this._currentNodeId).Wait();
} }
} } protected bool IsMinNodeId(ChildrenResult childrenResult, long nodeId)
{
if (nodeId == 0 || childrenResult == null || childrenResult.Children.Count == 0)
return false; var nodeIds = new List<long>(); foreach (var item in childrenResult.Children)
{
nodeIds.Add(ParseNodeId(item));
} if (nodeIds.Count > 0 && nodeIds.Min() == nodeId)
{
return true; }
return false;
} protected long ParseNodeId(string path)
{
var m = Regex.Match(path, "(\\d+)");
if (m.Success)
{
return long.Parse(m.Groups[0].Value);
}
return 0L;
} protected void Initialize(String connectionString, TimeSpan sessionTimeout)
{
this._zooKeeper = new ZooKeeper(connectionString, (int)sessionTimeout.TotalMilliseconds, this);
} public Task FireAcquireLock(long id)
{
this.OnAcquireLock(id).Wait();
this.CloseConnection();
Log.Debug("NodeId {@id} Close ZooKeeper Success", id);
return Task.CompletedTask;
} public bool WaitConnected(TimeSpan timeout)
{
var continueWait = false;
while (this._currentState != Event.KeeperState.SyncConnected)
{
continueWait = _notifyEvent.WaitOne(timeout);
if (!continueWait)
{
return false;
}
}
return true;
} protected void CloseConnection()
{
if (_disposed)
{
return;
}
_disposed = true; if (_zooKeeper != null)
{
try
{
this._zooKeeper.closeAsync().ConfigureAwait(false).GetAwaiter().GetResult();
}
catch { } }
} #region Watcher Impl public override Task process(WatchedEvent @event)
{
if (@event.getState() == Event.KeeperState.SyncConnected)
{
if (String.IsNullOrEmpty(@event.getPath()))
{
this._currentState = @event.getState();
this._notifyEvent.Set();
} var path = @event.getPath();
if (!string.IsNullOrEmpty(path))
{
if (path.Equals(this._lockPath))
{
Log.Debug("NodeId {@id} Start Watcher Callback", this._currentNodeId); if (this._hasAcquireLock)
{
Log.Debug("NodeId {@id} Has Acquire Lock return", this._currentNodeId);
return Task.CompletedTask;
} Task.Run(() =>
{
var childrenResult = _zooKeeper.getChildrenAsync(this._lockPath, this).Result; if (IsMinNodeId(childrenResult, this._currentNodeId))
{
lock (this)
{
if (!this._hasAcquireLock)
{
Log.Debug("NodeId {@id} Acquire Lock", this._currentNodeId);
this._hasAcquireLock = true;
this.FireAcquireLock(this._currentNodeId).Wait();
}
}
}
}); //_zooKeeper.getChildrenAsync(_lockPath, this); }
}
} return Task.CompletedTask;
} public void Dispose()
{
this.CloseConnection();
} #endregion
}
}

ZooKeeper Distributed lock的更多相关文章

  1. distributed lock manager (DLM)(分布式管理锁)

    A distributed lock manager (DLM) provides distributed software applications with a means to synchron ...

  2. Redis Distributed lock

    using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using ...

  3. 基于ZooKeeper的分布式锁和队列

    在分布式系统中,往往需要一些分布式同步原语来做一些协同工作,上一篇文章介绍了Zookeeper的基本原理,本文介绍下基于Zookeeper的Lock和Queue的实现,主要代码都来自Zookeeper ...

  4. zookeeper实现分布式锁服务

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

  5. How to do distributed locking

    How to do distributed locking 怎样做可靠的分布式锁,Redlock 真的可行么? 本文是对 Martin Kleppmann 的文章 How to do distribu ...

  6. 基于Apache Curator框架的ZooKeeper使用详解

    一 简介 Apache Curator是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API 简化了ZooKeeper的操作.通过查看官方文档,可以发现Curator主要解决了三类问题 ...

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

    基于zookeeper实现的分布式锁 2011-01-27 • 技术 • 7 条评论 • jiacheo •14,941 阅读 A distributed lock base on zookeeper ...

  8. zookeeper生产最广泛使用java客户端curator介绍及其它客户端比较

    关于zookeeper的原理解析,可以参见zookeeper核心原理详解,本文所述大多数实践基于对zookeeper原理的首先理解. Curator是Netflix公司开源的一个Zookeeper客户 ...

  9. 01 . 消息队列之(Kafka+ZooKeeper)

    消息队列简介 什么是消息队列? 首先,我们来看看什么是消息队列,维基百科里的解释翻译过来如下: 队列提供了一种异步通信协议,这意味着消息的发送者和接受者不需要同时与消息保持联系,发送者发送的消息会存储 ...

随机推荐

  1. css揭秘 一

    当某些值相互依赖是,应该把它们的相互关系用代码表达出来 font-size: 20px; line-height: 1.5; // 行高是字体的1.5倍 当改变某个参数时候,做到只改尽量少的地方,最好 ...

  2. 0014 基于DRF框架开发(02 基类视图 GenericAPIView)

    前端于对数据操作的请求基本上就分为四类:增删改查,即增加.删除.修改.查询. 而DRF把前端请求分为两个大类:带ID参数请求和不带ID参数请求. 不带ID参数请求包括:增加.分布多条查询 带ID参数请 ...

  3. CF1237F Balanced Domino Placements

    题意 给定一个 \(h\) 行 \(w\) 列的方格图,上面已经放置了一些 \(1\times 2\) 的多米诺骨牌. 我们称一个放置多米诺骨牌的方案是好的,当且仅当任何两个多米诺骨牌不占用相同的行与 ...

  4. spark-sklearn TypeError: 'JavaPackage' object is not callable

    from sklearn import svm, datasets from spark_sklearn import GridSearchCV from pyspark import SparkCo ...

  5. linux C++ 读取mysql结果保存

    c++读取mysql数据库结果保存 #include <fstream> #include <iomanip> #include <iostream> #inclu ...

  6. JS绑定事件处理函数及处理流程

    一.事件绑定的几种方式: 1.1 ele.on+“事件名“:如div.onclick = function(event){ }; 1.1.1这种方式兼容性非常好,但一个元素的同一个事件上只能绑定一个处 ...

  7. Eclispe WEB项目 转到 IDEA 后无法部署问题

    IDEA是个强大的IDE  这个就不用多说了 Eclispe 的Web项目  转到IDEA之后,开始部署会出现大量的问题 项目从SVN下载下来的时候,大概就是这个样 第一步是先设置  项目结构  也就 ...

  8. java课堂测试

       package 作业2; //信1805-1 杨一帆 20183608 public class ScoreInformation1 { private String stunumber; pr ...

  9. luogu P2158 [SDOI2008]仪仗队 (欧拉函数)

    欧拉函数裸题 可惜我太久没做题忘了欧拉函数是什么了... 注意判断一下n = 1的情况就好了 #include <cstdio> using namespace std; ; typede ...

  10. [ZJOI2007] 矩阵游戏 - 二分图匹配

    题意:问一个\(0-1\)方阵是不是非奇异的 其实我真的很想求行列式 #include <bits/stdc++.h> using namespace std; #define N 505 ...