public IDistributedReadWriteLock CreateReadWriteLock(string name) { var path = ZKPaths.MakePath(BASE_LOCK_PATH, name); var rwlock = new ZookeeperReadWriteLock(_zkClient, path, _options.DefaultLockTimeout); return(rwlock); }
//public ZookeeperLockProvider(ZooKeeper zkClient) //{ // _zkClient = zkClient; //} //public ZookeeperLockProvider(string connectString, int sessionTimeout) //{ // _zkClient = new ZooKeeper(connectString, sessionTimeout, null); //} public IDistributedLock CreateMutexLock(string name) { var path = ZKPaths.MakePath(BASE_LOCK_PATH, name); var mlock = new ZookeeperMutexLock(_zkClient, path, _options.DefaultLockTimeout); return(mlock); }
public LockInternals(ZooKeeper zkClient, ILockInternalsDriver driver, string path, string lockName, int maxLeases) { _driver = driver; _lockName = lockName; _maxLeases = maxLeases; _zkClient = zkClient; _basePath = ZKPaths.ValidatePath(path); _path = ZKPaths.MakePath(path, lockName); _signal = new SemaphoreSlim(0); _watcher = new ReleaseLockWatcher(_signal); }
/// <summary> /// zk信号量 /// </summary> /// <param name="zkClient"></param> /// <param name="path"></param> /// <param name="maxLeases"></param> public ZookeeperSemaphore(ZooKeeper zkClient, string path, int maxLeases, int lockTimeout) { ZKPaths.ValidatePath(path); _zkClient = zkClient; _maxLeases = maxLeases; _lockTimeout = lockTimeout; _lock = new ZookeeperMutexLock(zkClient, ZKPaths.MakePath(path, LOCK_PARENT), lockTimeout); _leasesPath = ZKPaths.MakePath(path, LEASE_PARENT); _acquiredLeases = new List <string>(maxLeases); _signal = new SemaphoreSlim(0); _watcher = new ReleaseLockWatcher(_signal); }
public virtual PredicateResults GetTheLock(ZooKeeper client, List <string> sortedChildren, string sequenceNodePath, int maxLeases) { var sequenceNodeName = ZKPaths.GetNodeFromPath(sequenceNodePath); var ourIndex = sortedChildren.IndexOf(sequenceNodeName); if (ourIndex < 0) { throw new KeeperException.NoNodeException(sequenceNodePath); } var locked = ourIndex < maxLeases; var nodeToWatch = locked ? null : sortedChildren[ourIndex - maxLeases]; return(new PredicateResults(nodeToWatch, locked)); }
private PredicateResults ReadLockPredicate(List <string> children, string sequenceNodePath) { // 已获取写锁可以直接获取读锁 if (_writeLock.IsAcquiredLock()) { return(new PredicateResults(null, true)); } int watchWriteIndex = int.MaxValue; int ourIndex = -1; var sequenceNodeName = ZKPaths.GetNodeFromPath(sequenceNodePath); for (int index = 0; index < children.Count; index++) { var node = children[index]; // 写锁节点 if (node.Contains(ZookeeperReadWriteLock.WRITE_LOCK_NAME)) { watchWriteIndex = index; } // 当前读锁节点 else if (node == sequenceNodeName) { ourIndex = index; break; } } if (ourIndex < 0) { throw new KeeperException.NoNodeException(sequenceNodePath); } var locked = (ourIndex < watchWriteIndex); var pathToWatch = locked ? null : children[watchWriteIndex]; return(new PredicateResults(pathToWatch, locked)); }
public static async Task <string> RecursionCreateAsync(this ZooKeeper zkClient, string path, byte[] data, List <ACL> acl, CreateMode createMode) { ZKPaths.ValidatePath(path); var paths = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); string outPath = null; var currPath = string.Empty; for (int i = 0; i < paths.Length; i++) { currPath += "/" + paths[i]; try { var stat = await zkClient.existsAsync(currPath); if (stat == null) // 节点不存在 { if (i == paths.Length - 1) // 终节点 { outPath = await zkClient.createAsync(currPath, data, acl, createMode); } else { await zkClient.createAsync(currPath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } } catch (KeeperException.NodeExistsException) { continue; } } return(outPath); }
/// <summary> /// 获取一个Lease /// </summary> /// <param name="startMs">开始毫秒数</param> /// <param name="waitMs">等待毫秒数</param> /// <returns>Lease节点名称</returns> private async Task <string> InternalAcquireOneLeaseAsync(long startMs, long waitMs) { // 获取剩余等待时间 var remainingTime = GetRemainingWaitMs(startMs, waitMs); if (remainingTime <= 0) { new TimeoutException("等待超时"); } // 获取分布式锁 await _lock.AcquireAsync(remainingTime); string leasePath; var success = false; try { // 创建Lease临时有序节点 leasePath = await _zkClient.createAsync(ZKPaths.MakePath(_leasesPath, LEASE_BASE_NAME), null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); // 节点名称 var leaseNodeName = ZKPaths.GetNodeFromPath(leasePath); try { while (true) { var childrenResult = await _zkClient.getChildrenAsync(_leasesPath, _watcher); // 找不到刚创建的Lease节点 if (!childrenResult.Children.Contains(leaseNodeName)) { throw new KeeperException.NoNodeException("Sequential path not found - possible session loss"); } // 成功获取一个Lease if (childrenResult.Children.Count <= _maxLeases) { break; } // 剩余等待时间 remainingTime = GetRemainingWaitMs(startMs, waitMs); if (remainingTime <= 0) { throw new TimeoutException("等待超时"); } // 等待被唤醒 var result = await _signal.WaitAsync(remainingTime); if (!result) { throw new TimeoutException("等待超时"); } } success = true; } finally { if (!success) { await DeleteLease(leasePath); } } } finally { await _lock.ReleaseAsync(); } return(leasePath); }
private async Task <bool> InternalLockLoopAsync(long startMillis, int millisToWait, string ourPath) { var haveTheLock = false; var doDelete = false; try { while (_zkClient.getState() == ZooKeeper.States.CONNECTED) { // 获取排序的子节点 var children = await GetSortedChildren(); //var sequenceNodeName = ourPath.Substring(_basePath.Length + 1); // 判断能否持有锁 var predicateResults = _driver.GetTheLock(_zkClient, children, ourPath, _maxLeases); // 已获取到锁 if (predicateResults.Locked) { return(true); } // 上一个节点路径 var previousSequencePath = ZKPaths.MakePath(_basePath, predicateResults.NodeToWatch); try { // 剩余等待时间 millisToWait -= (int)(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - startMillis); startMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); if (millisToWait <= 0) { // 超时,删除创建的节点 doDelete = true; break; } // 设置释放锁监听 await _zkClient.getDataAsync(previousSequencePath, _watcher); // 阻塞 等待锁释放或超时 if (!await _signal.WaitAsync(millisToWait)) { doDelete = true; break; } } catch (KeeperException.NoNodeException ex) { // 上一个节点已被删除(即释放锁)。再次尝试获取 } } } catch (Exception ex) { doDelete = true; throw ex; } finally { if (doDelete) { await DeleteOurPathAsync(ourPath); } } return(haveTheLock); }
public ZookeeperMutexLock(ZooKeeper zkClient, string path, string lockName, int maxLeases, ILockInternalsDriver driver, int lockTimeout) { _basePath = ZKPaths.ValidatePath(path); _lockTimeout = lockTimeout; _internals = new LockInternals(zkClient, driver, path, lockName, maxLeases); }