zookeeper实现的一个锁
要求: 分布在不同机器上的进程,同时扫描某个ftp目录,得到文件目录,下载文件,但是要保证每个文件都只被一个进程获取
思路:
1. 文件以RW方式打开,比较暴力 ,另FTP支持RW方式打开吗。。。没了解过
2. 实现一个分布式锁,
2.1 redis:
redis单机的事务能否实现? 应该可以,保证一个list,然后不断poll即可。
redis集群的一致性能否实现? 从表面上看,最终一致性不能保证。。。。。 ------------- 待测试验证
2.2 zookeeper
zookeeper状态信息: http://coolxing.iteye.com/blog/1871328
zookeeper使用帮助:http://zookeeper.apache.org/doc/trunk/recipes.html
zookeeper介绍及典型场景: http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
apache- zookeeper-lock : https://svn.apache.org/repos/asf/zookeeper/trunk/src/recipes/lock/src/java/org/apache/zookeeper/recipes/lock/WriteLock.java
实现时候的zookeeper内文件结构:
[zk: localhost:2181(CONNECTED) 79] ls /na/lock/ftp/2014/12/01/test6/0.log
[x-309002431815222022-0000000001, x-164887243784979208-0000000000, x-381060026091242234-0000000002]
/na/lock/ftp/2014/12/01/test6/0.log 是 目标文件
x-309002431815222022-0000000001, x-164887243784979208-0000000000, x-381060026091242234-0000000002 是3个客户端创建的子文件
子文件结构 x- [sessionid] - [zk内部sequence] 309002431815222022 是sessionid 0000000001 是 seq
3个客户端提交的create请求将在zk内部通过类似cas(或者就是cas)来竞争达到排序的目的,然后大家看谁的seq最靠前谁就获得锁。
apache提供的lock需要改进的地方:
1. path自适应,parent不存在的时候能够自动创建parent
2. 两个进程中的线程同时create一个文件的时候会有keeperexception,需要catch下,判定有exception的没有获取到锁
3. znodename做sortmap的时候,拿prefix在内做了compare,容易出问题,需要改成直接拿sequence比较。
int answer = this.prefix.compareTo(that.prefix); // -- line79
=》
// int answer = this.prefix.compareTo(that.prefix); 注释掉
4. create子节点的时候,line186,用了临时的SEQUENTIAL文件类别,原意是控制单个文件的并发写入,这个文件是可以重入的,在锁占用进程关闭zkclient之后,另外的进程是可以进入的。但是在本案例中,文件下载下来就不能再处理了,所以要改成PERSISTENT_SEQUENTIAL
code如下 :
id = zookeeper.create(dir + "/" + prefix, data, getAcl(), CreateMode.EPHEMERAL_SEQUENTIAL);
=>
id = zookeeper.create(dir + "/" + prefix, data, getAcl(), CreateMode.PERSISTENT_SEQUENTIAL);