基于Zookeeper+Curator实现分布式锁

1、Zookeeper简介

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

Zookeeper安装及简单使用请参考博文:Zookeeper安装及简单使用

2、Curator简介

Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt(Zookeeper)以一句“Guava is to Java that Curator to Zookeeper”给Curator予高度评价。

3、使用Curator框架实现分布式锁

Curator maven坐标:

1
2
3
4
5
6
<!-- 封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式Barrier -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.0.0</version>
</dependency>

我们使用Springboot项目来实现。

maven依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath />
</parent>

<dependencies>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

新建CuratorConfig 配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class CuratorConfig {

@Value("${zookeeper.connectstr}")
private String connectStr;

@Bean
public CuratorFramework curatorFramework() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient(connectStr, retryPolicy);
client.start();
return client;
}

}

新建配置文件application.properties:

1
2
server.port=8181
zookeeper.connectstr=127.0.0.1:2181

新建web测试接口:

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
@RestController
public class ProductController {

private Integer stock = 5;

@Autowired
private CuratorFramework client;

@PostMapping("deduct/stock/{productId}")
public Integer deductStock(@PathVariable("productId") String productId) throws Exception {

// zk分布式锁
InterProcessMutex lock = new InterProcessMutex(client, "/lock/"+productId);
if (lock.acquire(5, TimeUnit.SECONDS)) {
try {
System.out.println("减库存");
if (stock <= 0) {
throw new Exception("扣减失败");
}
stock--;
} finally {
lock.release();
}
}
return stock;
}
}

创建启动类:

1
2
3
4
5
6
7
@SpringBootApplication
public class DistributelockApplication {

public static void main(String[] args) {
SpringApplication.run(DistributelockApplication.class, args);
}
}

启动DistributelockApplication ,使用jmeter开启多线程访问 http://127.0.0.1:8181/deduct/stock/10000。 大家可自行去尝试!

4、总结

实现分布式锁使用Redis也可以实现。

zookeeper在分布式的系统中的使用场景还是蛮多的,如分布式配置中心(Springboot2.x+Zookeeper实现分布式配置中心),有兴趣的可以继续去研究。

Curator框架还有其他现成的功能,有兴趣的可以去官网看看:http://curator.apache.org/index.html


基于Zookeeper+Curator实现分布式锁
https://river106.cn/posts/981e502e.html
作者
river106
发布于
2020年12月25日
许可协议