我自己写了一个redis分布式锁的模块,已经推到pypi里面了。 但是带来了一个问题是,如果客户端自己因为内存泄露被系统内核给oom干掉了。
在分布式的架构下,一堆的节点去获取锁是徒劳的,只能等我们先前redis的TTL自动消逝….当然我自己也扩展了一个追加时间戳的方式,来判断他的进程在不在,但是可能会遇到的问题是,他因为hbase的堵塞,会消耗不少的时间…我不能及时的,实时的推送我的任务时间戳….
我想大家就算是在正常的情况下,也是会遇到任务堵塞的情况,又因为你的程序不健全,没有做好timeout超时的释放机制,单纯的用expire做ttl的控制不是那么的合理。 如果应用在我们项目下,会遇到任务正在干着,但是因为某个原因堵塞了,但是自动解锁的时间马上就要到了… 这算是个悲催的场景了….
文章的原文是引用在我的博客….
其实我们可以监听客户端的链接的状态…. 我们这里可以采用zookeeper来解决这类的问题,zookeeper会自动长连接的,如果客户端中断了连接,不管是你主动还是被动,我都会在我的注册列表里卖弄,干掉你,并且解锁
自己也懒得写了,直接搜了个开源的模块 https://github.com/tinyogre/zklock 在pypi里面,也有不少类似的模块.
#创建锁 z = zklock.Lock('nima') try: #查询是否已经锁定了 if z.acquire(): print "zklocktest: Lock acquired" time.sleep(20) # 解锁 z.release() except: z.release() with zklock.ScopedLock("scoped_lock_test", block=False) as z: if z.acquired: print "Locked!" time.sleep(20) else: print "Could not obtain lock!" print "zklocktest: Exiting"
zk节点(znode)可以分为如下四类:
PERSISTENT:持续的,相比于EPHEMERAL,不会随着client session的close/expire而消失
PERSISTENT_SEQUENTIAL:顺序的,会自动在节点名后面添加一个自增计数,格式为%010d
EPHEMERAL:临时节点,生命周期依赖于client session,对应session close/expire后其znode也会消失,临时节点不能有子节点
(我们这里采用的就是 临时节点,因为他有个session的概念….当客户端出现异常后,其他的客户端可以watch监听到的)
EPHEMERAL_SEQUENTIAL
该方法可能触发如下异常:
NodeExistsError:当要创建的节点已经存在时
NoNodeError:当makepath为False且祖先节点不存在时
NoChildrenForEphemeralsError:父节点为临时节点,在一个临时节点下面创建子节点会报该异常
ZookeeperError:节点值太大,zk默认节点值限制为1M
ZookeeperError:服务器返回一个非0状态码