Zookeeper实现分布式锁的原理
Zookeeper基于临时有序节点+watch机制实现分布式锁原理; 所有线程启动后,所有线程都会在zookeeper中创建临时有序节点(抢占锁),只有最小临时有序节点的那个线程能够抢占到锁, 其他未抢占到锁的线程处于等待状态和监听比自己小的节点; 当抢占到锁的线程释放锁后,比自己大的节点会监听到该节点发生变化,并且去尝试抢占锁;
源码
Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
application.yml
server:
port: 8085
spring:
curator:
retryCount: 5 #重试次数
elapsedTimeMs: 5000 #重试间隔时间
connectString: 127.0.0.1:2181 #zookeeper地址
sessionTimeoutMs: 60000 #session超时时间
connectionTimeoutMs: 15000 #连接超时时间
CuratorConfig 配置类
@Value("${spring.curator.retryCount}")
private int retryCount;
@Value("${spring.curator.elapsedTimeMs}")
private int elapsedTimeMs;
@Value("${spring.curator.connectString}")
private String connectString;
@Value("${spring.curator.sessionTimeoutMs}")
private int sessionTimeoutMs;
@Value("${spring.curator.connectionTimeoutMs}")
private int connectionTimeoutMs;
@Bean
public CuratorFramework curatorFramework() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(elapsedTimeMs, retryCount);
CuratorFramework client = CuratorFrameworkFactory.newClient(
connectString,
sessionTimeoutMs,
connectionTimeoutMs,
retryPolicy);
client.start();
return client;
}
Controller 控制器类
@RestController
@Slf4j
public class CuratorLockController {
@Autowired
private CuratorFramework client;
/**
* 锁测试共享变量
*/
private Integer lockCount = 10;
@GetMapping("/lock")
public void lock() throws Exception {
// Zk分布式锁
InterProcessMutex lock = new InterProcessMutex(client, "/lock/lockCount");
if (lock.acquire(5, TimeUnit.SECONDS)) {
try {
if (lockCount <= 0) {
throw new Exception("lockCount不能小于0");
}
// 业务逻辑
lockCount--;
log.info("lockCount值:"+lockCount);
} finally {
lock.release();
}
}
}
Application 启动类
@SpringBootApplication
public class ZkLockApplication {
public static void main(String[] args) {
SpringApplication.run(ZkLockApplication.class,args);
}
}
测试
打开 JMeter,设置10个线程,点击运行:
序号依次递减,如下图:
参考:
http://curator.apache.org/index.htmls
https://mvnrepository.com/artifact/org.apache.curatorZookeeper
http://curator.apache.org/apidocs/org/apache/curator/framework/CuratorFrameworkFactory.html