基于 ZooKeeper 实现分布式锁 由于下面使用了 Curator 客户端,因此需要引入相应的依赖 1 2 3 4 5 6 7 8 9 10 11 <dependency > <groupId > org.apache.curator</groupId > <artifactId > curator-framework</artifactId > <version > 5.5.0</version > </dependency > <dependency > <groupId > org.apache.curator</groupId > <artifactId > curator-recipes</artifactId > <version > 5.5.0</version > </dependency >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.framework.recipes.locks.InterProcessLock;import org.apache.curator.retry.ExponentialBackoffRetry;public class CuratorDistributedLockExample { private static final String ZOOKEEPER_CONNECTION_STRING = "localhost:2181" ; private static final String LOCK_PATH = "/zk-lock" ; public static void main (String[] args) throws Exception { CuratorFramework client = CuratorFrameworkFactory.newClient(ZOOKEEPER_CONNECTION_STRING, new ExponentialBackoffRetry(1000 , 3 )); client.start(); InterProcessLock lock = new InterProcessMutex(client, LOCK_PATH); try { lock.acquire(); System.out.println("Lock acquired, do some work here..." ); Thread.sleep(5000 ); } finally { try { lock.release(); System.out.println("Lock released." ); } catch (Exception exception) { exception.printStackTrace(); } } client.close(); } }
在这个示例中,首先创建了 Curator 客户端,然后使用 InterProcessMutex
类创建了一个分布式锁实例。在 try
块中调用 acquire()
方法获取锁,在获取锁后执行需要加锁的业务逻辑,最后在 finally
块中释放锁。Curator 会自动处理加锁、解锁和失败重试等复杂逻辑,简化了分布式锁的使用。
Dubbo 使用 Curator 连接 ZooKeeper 失败 异常日志:
1 Caused by: org.apache.zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented for /dubbo/xxx.xxx.service.UserService/providers/dubbo ....
异常分析:ZooKeeper 的版本与 Curator 的版本不兼容所导致,Curator 官网说明如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 第一种情况: Curator 2.x.x compatible with both ZooKeeper 3.4.x and ZooKeeper 3.5.x Curator 3.x.x compatible only with ZooKeeper 3.5.x and includes support for new features such as dynamic reconfiguration, etc. 第二种情况: ZooKeeper 3.5.x Curator 4.0 has a hard dependency on ZooKeeper 3.5.x If you are using ZooKeeper 3.5.x there's nothing additional to do - just use Curator 4.0 ZooKeeper 3.4.x Curator 4.0 supports ZooKeeper 3.4.x ensembles in a soft-compatibility mode. To use this mode you must exclude ZooKeeper when adding Curator to your dependency management tool.
解决方法:针对第二种情况,假设各组件的版本分别为 Dubbo (2.7.0)、ZooKeeper (3.4.13)、Curator-Framework (4.0.1),则需要排除 Curator-Framework (4.0.1) 默认依赖的高版本 ZooKeeper (3.5.x),然后指定低版本的 ZooKeeper (3.4.x),Maven 的 POM 写法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <dependencies> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.13</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.1</version> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.0.1</version> </dependency> </dependencies>