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. Node.js_1.1

    Node.js简介 Node.js是一个能够在服务器端运行JavaScript的开源代码.跨平台JavaScript运行环境 Node采用Google开发的V8引擎运行js代码,使用事件驱动.非阻塞和 ...

  2. LAMP环境搭建与配置(3)

    PHP配置 查看PHP配置文件的位置 #  /usr/local/php/bin/php   -i  |grep  -i  "loaded configuration file" ...

  3. 检测到 LoaderLock Message: 正试图在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。

    解决方法: 调试状态=>异常(Ctrl+Alt+E)=>Managed Debuggin Assistants=>LoaderLock 的选中状态去掉即可.

  4. 2级搭建类201-Oracle 12cR2 单实例 ASM(OEL7.7)公开

    项目文档引子系列是根据项目原型,制作的测试实验文档,目的是为了提升项目过程中的实际动手能力,打造精品文档AskScuti. 项目文档引子系列除特定项目目前不对外发布,仅作为博客记录,其他公开.如学员在 ...

  5. H5_0019:JS中定义json结构

            "7HKm": function(e, a, d) {             "use strict";             Object ...

  6. 疫情下的传统商企自救|4个Tips搭建销量过亿直播间

    新冠肺炎爆发以来,线下商企遭受巨大冲击.出于疫情防控需要,不少门店选择暂时停业:而消费者们更是响应号召.足不出户.这场疫情促使消费者的消费习惯和方式进一步转向线上订购转变,直播.短视频等领域逆势而起, ...

  7. POJ1273【网络流】

        Drainage Ditches   Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 91824   Accepted ...

  8. sqli-labs less-1 --> less-4

    Less-1  (报错注入) 因为第一次做这些题,不太了解,所以$sql下加上echo "$sql<br>";能更明显的看出具体的输入 1.判断是否存在注入点 当输入? ...

  9. 跨域 node git

    promise 异步回调地狱:就是多个异步请求嵌套的表现 瑕疵:后期维护难 解决:通过promise技术 什么是promise:就是一种异步编程的解决方案 有三个状态:进行中.成功了,失败了 var ...

  10. Vue快速认识

    1.Vue入门初识 1.1 Vue.js是什么? 一位华裔前Google工程师(尤雨溪)开发的前端js库 作用: 动态构建用户界面 特点: 遵循MVVM模式 编码简洁, 体积小, 运行效率高, 移动/ ...