[译]ZOOKEEPER RECIPES-Locks
锁
全局式分布式锁要求任何时刻没有两个客户端会获得同一个锁对象,这可以通过使用ZooKeeper实现。像优先级队列一样,首先需要定义一个锁节点。
在ZooKepeer的发布中src/recipes/lock(https://github.com/apache/zookeeper/tree/master/src/recipes/lock)的目录有ZooKeeper的Lock实现。
要获得锁的客户端进行如下操作:
1.调用Create方法并使用"_locknode_/guid-lock-"作为路径,并设置sequence和ephemeral标志位。guid是防止create的结果缺失,详见下面说明。
2.在锁节点上调用getChildren方法,不用设置watch(这是为了防止羊群效应)。
3.如果第一步所创建的路径拥有最小的序号,该客户端获得锁并退出协议。
4.客户端调用exists并设置watch标志在比自身小的节点上。
5.如果exists返回false,返回第二步。不然等到上一步设置的watch事件触发再回到第二步。
解锁的步骤非常简单:客户端希望释放锁只需要简单地删除第一步所创建的锁。
这里有几点值得注意:
- 由于每个节点只会被一个客户端watch,所以删除一个节点只会唤醒一个客户端。这样可以避免羊群效应。
- 没有轮询或超时的问题
- 使用该方式实现锁可以方便地看见锁的竞争、中断锁占用、调试锁等
可恢复错误和GUID
- 如果调用create时发生了一个可恢复的错误,客户端可以调用getChildren并通过guid检查节点的名字,来得知自己创建的节点。这个解决了引言中提到的问题,即create成功返回但是服务器在获得节点名字之前宕机的情况。
共享锁
可以通过修改部分协议来实现共享锁。
| 获得读锁 | 获得写锁 |
|---|---|
|
1.调用create创建"guid-/read-"节点。这是将会用到的读锁。需要确保使用sequence和ephemeral标志位。 2.在锁节点上调用getChildren,注意不要设置watch标志,避免羊群效应。 3.如果没有比第一步创建的节点小的"write-"开头的节点,则客户端获得锁并退出协议。 4.否则在次小的write节点上调用exists方法并设置watch标志。 5.如果exists方法返回false则返回第二步。 6.不然等待上面watch事件触发再返回第二步 |
1.调用create创建"guid-/write-"节点。这是后面需要的写锁。需要确保使用sequence和ephemeral标志位。 2.在锁节点上调用getChildren,注意不要设置watch标志,避免羊群效应。 3.如果没有比第一步创建的更小的节点,客户端获得锁并退出协议。 4.在次小的节点上调用exists方法并设置watch标志。 5.如果exists返回false回到第二步,不然等到watch事件触发再返回第二步。 |
###注意:
>* 该recipe可能产生羊群效应,即,当有一群客户端等待读锁时,客户端会在写锁释放时一起被唤醒。事实上,这个过程应该是正确的:所有等待的读客户端获得了锁。而羊群效应是指有一群节点被唤醒,而事实上只能允许少数可以运行。
>* 详见[上面](#可恢复错误和guid)提到的关于的guid使用。
##可恢复的共享锁
对共享锁协议做一些小幅改动就可以实现锁的可恢复:
在上面读写锁的第一步,在调用create之后,立即调用getData并使用watch标识,如果客户端收到这个watch事件,再次调用getData并使用watch标识并查看内容是否包含"unlock"字符串,unlock表示客户端必须释放当前锁。根据共享锁协议,你可以向获得锁客户端调用setData写入"unlock"字符串,申请其释放锁。
注意这个协议需要锁持有者同意释放锁。这很重要,尤其是如果锁持有者需要在释放之前做某些操作时。当然你可以在你的协议中规定,在锁持有者一定时间后如仍未删除锁节点,可以由他人强制删除。
##Curator实现
###共享锁
```
public InterProcessSemaphoreMutex(CuratorFramework client,String path)
/**
client 客户端实例
path 锁节点地址
**/
public void acquire() //获得锁
public void release() //释放锁
```
###可重入共享锁
```
public InterProcessMutex(CuratorFramework client,String path)
/**
client 客户端实例
path 锁节点地址
**/
public void acquire() //获得锁
public void release() //释放锁
public void makeRevocable(RevocationListener listener) //撤销锁
public static void attemptRevoke(CuratorFramework client,String path) //请求对应路径锁撤销
```
###可重入读写锁
```
public InterProcessReadWriteLock(CuratorFramework client,String basePath)
/**
client 客户端实例
basePath 锁基础路径
**/
public InterProcessLock readLock() //读锁
public InterProcessLock writeLock() //写锁
```
[返回引言](http://www.cnblogs.com/resentment/p/6129339.html)
[译]ZOOKEEPER RECIPES-Locks的更多相关文章
- ZooKeeper Recipes and Solutions 翻译
ZooKeeper 秘诀 与解决方案 A Guide to Creating Higher-level Constructs with ZooKeeper Out of the Box Applica ...
- ZooKeeper Recipes and Solutions
原文地址:http://zookeeper.apache.org/doc/current/recipes.html 参考:https://zookeeper.apache.org/doc/trunk/ ...
- [译]ZooKeeper recipes-引言
ZooKeeper高级应用 本系列将指导使用ZooKeeper来实现高级功能,所有功能都在客户端完成,不需要ZooKeeper的特殊支持.希望可以得到社区的支持将这些加入到一个标准的客户端类库中(Cu ...
- [译]ZOOKEEPER RECIPES-Queues
队列 分布式队列是一种常见的数据结构.为了在ZooKepeer中实现分布式队列,第一步是要使用一个znode代表队列本身.分布式客户端通过create()方法将内容放入一个名叫"queue- ...
- [译]ZOOKEEPER RECIPES-Leader Election
选主 使用ZooKeeper选主的一个简单方法是,在创建znode时使用Sequence和Ephemeral标志.主要思想是,使用一个znode,比如"/election",每个客 ...
- [译]ZOOKEEPER RECIPES-TWO PHASED COMMIT
两段式提交 两段式提交协议可以让所有分布式系统中的客户端达成协议同时提交或回滚事务. 在ZooKeeper中你可以通过协调者(coordinator)创建一个事务节点来实现两段式提交.例如" ...
- [译]ZOOKEEPER RECIPES-Barriers
Barrier 在分布式系统中常使用Barrier来阻塞进程,当满足一定条件后再恢复进行后续操作.Barrier在Zookeeper中可以通过设计一个Barrier节点来实现.Barrier 节点存在 ...
- <译>Zookeeper官方文档
apache原文地址:http://zookeeper.apache.org/doc/trunk/zookeeperOver.html ZooKeeper ZooKeeper: A Distribut ...
- [译]Zookeeper的优点与局限性
1.Zookeeper的优点与局限性 在学习了Zookeeper(后文都简称zk)的介绍和功能后,您已经很好地理解了zk. 现在,在这个zk教程中,我们将讨论zk的优点和局限性. zk有几个功能对用户 ...
随机推荐
- “.Net 社区虚拟大会”(dotnetConf) 2016 Day 3 Keynote: Scott Hanselman
美国时间 6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开,美国时间6.9 是第三天, Scott Hanselman 做Keynote.今天主题围绕的是.NET ...
- SSH实战 · 唯唯乐购项目(下)
后台模块 一:后台用户模块 引入后台管理页面 创建adminuser表: CREATE TABLE `adminuser` ( `uid` int(11) NOT NULL AUTO_INCREM ...
- 7.让网站支持http和https的访问方式
平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html#iis 怎么让网站在本地支持SSL?http://www.c ...
- Redis数据库
Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...
- 旺财速啃H5框架之Bootstrap(一)
接下来的时间里,我将和大家一起对当前非常流行的前端框架Bootstrap进行速度的学习,以案例的形式.对刚开始想学习Bootstrap的同学而找不着边的就很有帮助了.如果你想详细的学习Bootstra ...
- 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?
0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...
- Smarty的基本使用与总结
含义: Smarty是PHP的一个引擎模板,可以更好的进行逻辑与显示的分离,即我们常说的MVC,这个引擎的作用就是将C分离出来. 环境需求:PHP5.2或者更高版本 我使用的环境是:PHP5.3,wi ...
- PHP的学习--RSA加密解密
PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了. 举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了. 密码没加 ...
- 用C语言封装OC对象(耐心阅读,非常重要)
用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...
- 破解SQLServer for Linux预览版的3.5GB内存限制 (RHEL篇)
微软发布了SQLServer for Linux,但是安装竟然需要3.5GB内存,这让大部分云主机用户都没办法尝试这个新东西 这篇我将讲解如何破解这个内存限制 要看关键的可以直接跳到第6步,只需要替换 ...