zookeeper适用场景:分布式锁实现
问题导读:
1.zookeeper如何实现分布式锁?
2.什么是羊群效应?
3.zookeeper如何释放锁?

在zookeeper应用场景有关于分布式集群配置文件同步问题的描述,设想一下如果有100台机器同时对同一台机器上某个文件进行修改,如何才能保证文本不会被写乱,这就是最简单的分布式锁,本文介绍利用zk实现分布式锁。下面是写锁的实现步骤
分布式写锁
create一个PERSISTENT类型的znode,/Locks/write_lock
- 客户端创建SEQUENCE|EPHEMERAL类型的znode,名字是lockid开头,创建的znode是/Locks/write_lock/lockid0000000001
- 调用getChildren()不要设置Watcher获取/Locks/write_lock下的znode列表
- 判断自己步骤2创建znode是不是znode列表中最小的一个,如果是就代表获得了锁,如果不是往下走
- 调用exists()判断步骤2自己创建的节点编号小1的znode节点(也就是获取的znode节点列表中最小的znode),并且设置Watcher,如果exists()返回false,执行步骤3
- 如果exists()返回true,那么等待zk通知,从而在回掉函数里返回执行步骤3
释放锁就是删除znode节点或者断开连接就行
*注意:上面步骤2中getChildren()不设置Watcher的原因是,防止羊群效应,如果getChildren()设置了Watcher,那么集群一抖动都会收到通知。在整个分布式锁的竞争过程中,大量重复运行,并且绝大多数的运行结果都是判断出自己并非是序号最小的节点,从而继续等待下一次通知—,这个显然看起来不怎么科学。客户端无端的接受到过多的和自己不相关的事件通知,这如果在集群规模大的时候,会对Server造成很大的性能影响,并且如果一旦同一时间有多个节点的客户端断开连接,这个时候,服务器就会像其余客户端发送大量的事件通知——这就是所谓的羊群效应。
下面是代码实现
import sys
class GJZookeeper(object):
ZK_HOST = "localhost:2181"
ROOT = "/Locks"
WORKERS_PATH = join(ROOT,"write_lock")
MASTERS_NUM = 1
TIMEOUT = 10000
def __init__(self, verbose = True):
self.VERBOSE = verbose
self.masters = []
self.is_master = False
self.path = None
self.zk = ZKClient(self.ZK_HOST, timeout = self.TIMEOUT)
self.say("login ok!")
# init
self.__init_zk()
# register
self.register()
def __init_zk(self):
"""
create the zookeeper node if not exist
|--Locks
|--write_lock
"""
nodes = (self.ROOT, self.WORKERS_PATH)
for node in nodes:
if not self.zk.exists(node):
try:
self.zk.create(node, "")
except:
pass
def register(self):
"""
register a node for this worker
|--Locks
|--write_lock
|--lockid000000000x ==> hostname
"""
import socket
hostname = socket.gethostname()
self.path = self.zk.create(self.WORKERS_PATH + "/lockid", hostname, flags=zookeeper.EPHEMERAL | zookeeper.SEQUENCE)
self.lockid = basename(self.path)
self.say("register ok! I'm %s" % self.path)
# check who is the master
self.get_lock()
def get_lock(self):
"""
get children znode try to get lock
"""
@watchmethod
def watcher(event):
self.say("child changed, try to get lock again.")
self.get_lock()
children = self.zk.get_children(self.WORKERS_PATH)
children.sort()
min_lock_id = children[0]
self.say("%s's children: %s" % (self.WORKERS_PATH, children))
if cmp(self.lockid,min_lock_id) == 0:
self.get_lock_success()
return True
elif cmp(self.lockid,min_lock_id) > 0:
index = children.index(self.lockid)
new_lockid_watch = join(self.WORKERS_PATH,children[index-1])
self.say("Add watch on %s"%new_lockid_watch)
res = self.zk.exists(new_lockid_watch,watcher)
if not res :
"""代表没有存在之前小的锁,但是这并不意味着能拿到锁了,因为还可能有比当前还小的锁,还没轮到,要重新执行一遍"""
# self.get_lock_success()
return False
else :
"""现在的锁有人在使用,等他释放了再抢"""
self.say("I can not get the lock this time,wait for the next time")
return False
def get_lock_success(self):
self.say("I get the lock !!!")
self.write_file()
self.zk.delete(join(self.WORKERS_PATH,self.lockid))
self.say("I release the lock !!!")
sys.exit(1)
def write_file(self):
fd = open("lock.log",'a')
fd.write("%s\n"%self.lockid)
fd.close()
def say(self, msg):
"""
print messages to screen
"""
if self.VERBOSE:
if self.path:
log.info("[ %s(%s) ] %s" % (self.path, "master" if self.is_master else "slave", msg))
else:
log.info(msg)
def start_get_lock():
gj_zookeeper = GJZookeeper()
def main():
th1 = threading.Thread(target = start_get_lock, name = "thread_1", args = ())
th1.start()
th1.join()
if __name__ == "__main__":
main()
time.sleep(1000)
文章转自:http://www.aboutyun.com/forum.php?mod=viewthread&tid=9267&ctid=16
zookeeper适用场景:分布式锁实现的更多相关文章
- 整理分布式锁:业务场景&分布式锁家族&实现原理
1.引入业务场景 业务场景一出现: 因为小T刚接手项目,正在吭哧吭哧对熟悉着代码.部署架构.在看代码过程中发现,下单这块代码可能会出现问题,这可是分布式部署的,如果多个用户同时购买同一个商品,就可能导 ...
- 如何用Zookeeper来实现分布式锁?
什么是Zookeeper临时顺序节点? 例如 : / 动物 植物 猫 仓鼠 荷花 松树 Zookeeper的数据存储结构就像一棵树,这棵树由节点组成,这种节点叫做Zonde.# Znode分为四种类型 ...
- 基于zookeeper实现的分布式锁
基于zookeeper实现的分布式锁 2011-01-27 • 技术 • 7 条评论 • jiacheo •14,941 阅读 A distributed lock base on zookeeper ...
- java使用zookeeper实现的分布式锁示例
java使用zookeeper实现的分布式锁示例 作者: 字体:[增加 减小] 类型:转载 时间:2014-05-07我要评论 这篇文章主要介绍了java使用zookeeper实现的分布式锁示例,需要 ...
- ZooKeeper 笔记(6) 分布式锁
目前分布式锁,比较成熟.主流的方案有基于redis及基于zookeeper的二种方案. 大体来讲,基于redis的分布式锁核心指令为SETNX,即如果目标key存在,写入缓存失败返回0,反之如果目标k ...
- 基于zookeeper实现高性能分布式锁
实现原理:利用zookeeper的持久性节点和Watcher机制 具体步骤: 1.创建持久性节点 zkLock 2.在此父节点下创建子节点列表,name按顺序定义 3.Java程序获取该节点下的所有顺 ...
- 基于Zookeeper实现多进程分布式锁
一.zookeeper简介及基本操作 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化.当对目录节点监控状态打开时,一旦目录节点的状态发生变化,Watc ...
- 利用ZooKeeper简单实现分布式锁
1.分布式锁的由来: 在程序开发过程中不得不考虑的就是并发问题.在java中对于同一个jvm而言,jdk已经提供了lock和同步等.但是在分布式情况下,往往存在多个进程对一些资源产生竞争关系,而这些进 ...
- 基于zookeeper简单实现分布式锁
https://blog.csdn.net/desilting/article/details/41280869 这里利用zookeeper的EPHEMERAL_SEQUENTIAL类型节点及watc ...
- zookeeper实现的分布式锁
在分布式系统中,多个jvm对共享资源进行操作时候,要加上锁,这就是分布式锁 利用zookeeper的临时节点的特性,可以实现分布式锁 public class ZookeeperDistrbuteLo ...
随机推荐
- C#开发中Windows域认证登录2016(扩展吉日嘎拉GPM系统V4.2)
2013年搞公司的OA时,为了统一用户登录,将Windows AD的用户和OA的账号对接,OA用户名的规则就是使用Windows AD的用户名,格式举例:Troy.Cui,原理就是先进行域服务器的认证 ...
- chrome修改UserAgent,调试
chrome浏览器模拟 UserAgent,调试手机环境. https://chrome.google.com/webstore/detail/user-agent-switcher-for-c/dj ...
- jQuery中常用的元素查找方法
$("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myElement所以得到的是唯一的元素 $("div&q ...
- 重新想象 Windows 8.1 Store Apps (73) - 新增控件: DatePicker, TimePicker
[源码下载] 重新想象 Windows 8.1 Store Apps (73) - 新增控件: DatePicker, TimePicker 作者:webabcd 介绍重新想象 Windows 8.1 ...
- Csharp: read excel file using Open XML SDK 2.5
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- mbps
Mbps=Mbit/s即兆比特每秒.Million bits per second的缩写 传输速率是指设备的的数据交换能力,也叫“带宽”,单位是Mbps(兆位/秒),目前主流的集线器带宽主要有10Mb ...
- 线段树---Atlantis
题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110064#problem/A Description There are se ...
- Hibernate中的一级缓存、二级缓存和懒加载(转)
1.为什么使用缓存 hibernate使用缓存减少对数据库的访问次数,从而提升hibernate的执行效率.hibernate中有两种类型的缓存:一级缓存和二级缓存. 2.一级缓存 Hibenate中 ...
- winform(数据导出、TreeView的使用)
一.数据导出:目标: 将数据库的数据导出成Excel工作表或是Word文档 基本步骤: 1.首先将数据库中的数据封装成实体类 2.写好查询数据的方法,在主窗体中调用查看所有的数据 3.利用saveFi ...
- Ansible用于网络设备管理 part 2 对Jinja2 YAML 和 module的理解
虽然很不想用“应该”这个词,但是还是写上了,的确我自己目前就是这么理解的. 那么这个理解就是,Ansible的一个key point 就是总的一个playbook是去依赖很多元素的,就像一开始那个图里 ...