场景
“分布式锁”是用来解决分布式应用中“并发冲突”的一种常用手段,实现方式一般有基于zookeeper及基于redis二种
使用基于zookeeper的分布式锁
所需组件:
- zookeeper服务
- Curator 客户端
启动zookeeper
一般是集群部署,启动zookeeper服务端。
java 代码
Curator 是一个 基于 zookeeper服务 的客户端工具
curator提供了InterProcessMutex 这样一个api。除了分布式锁之外,还提供了leader选举、分布式队列等常用的功能。 InterProcessMutex:分布式可重入排它锁 InterProcessSemaphoreMutex:分布式排它锁 InterProcessReadWriteLock:分布式读写锁
引入依赖:
代码语言:javascript复制<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.2.0</version>
</dependency>
初始化会话连接:
代码语言:javascript复制@Bean
CuratorFramework CuratorFramework() {
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
.connectString("192.168.1.111:2181")
.sessionTimeoutMs(15000)
.connectionTimeoutMs(20000)
.retryPolicy(new ExponentialBackoffRetry(1000, 10))
.build();
//打开连接
curatorFramework.start();
//是否成功建立连接,true :建立, false:没有建立
System.out.println("是否打开:" curatorFramework.isStarted());
return curatorFramework;
主要方法:
InterProcessMutex lock = new InterProcessMutex(curatorFramework, "/LOCK_LOCK_2"); lock.acquire();//抢占分布式锁资源(阻塞的) lock.release();
示例:
代码语言:javascript复制// 引入Zookeeper实现分布式锁 ,curator客户端
private synchronized String impl08() throws Exception {
System.out.println("基于临时有序节点来实现的分布式锁 的实现");
// 基于临时有序节点来实现的分布式锁.
InterProcessMutex lock = new InterProcessMutex(curatorFramework, "/LOCK_LOCK_2");
try {
lock.acquire();//抢占分布式锁资源(阻塞的)
//----------------------
String res = "";
String stockStr = stringRedisTemplate.opsForValue().get("stock");
if (StringUtils.isEmpty(stockStr)) return "库存为空";
int stock = Integer.parseInt(stockStr);
if (stock > 0) {
int newStock = stock - 1;
stringRedisTemplate.opsForValue().set("stock", newStock "");
res = String.format("扣减成功 from %s to %s n", stock, newStock);
System.out.println(res);
} else {
res = String.format("扣减失败 from %s n", stock);
System.out.println(res);
}
return res;
} finally {
// 完事后释放 锁
lock.release();
}
}