Zookeeper分布式锁实战
使用curator操作Zookeeper进行实战;
curator是什么:Apache Curator包含一套高级API框架和工具类,它 是Apache ZooKeeper 的Java 客户端库。
准备
- pom文件引入curtor依赖和zookeeper依赖
<!--curator-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.6.0</version>
</dependency>
<!--zookeeper-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.9.2</version>
</dependency>
- yml配置
#zookeeper
curator:
connectString: localhost:2181
retryCount: 5
elapsedTimeMs: 5000
sessionTimeOutMs: 60000
connectionTimeOutMs: 5000
- 配置类
/**
* @Author
* @Date 2024/5/19 19:45
*/
@Data
@Component
@ConfigurationProperties(prefix = "curator")
public class WrapperZK {
/** 重试次数*/
private int retryCount;
/** 重试间隔时间*/
private int elapsedTimeMs;
/** 连接地址*/
private String connectString;
/** session超时时间*/
private int sessionTimeOutMs;
/** 连接超时时间*/
private int connectionTimeOutMs;
}
@Configuration
public class ZookeeperConfig {
@Autowired
private WrapperZK wrapperZK;
@Bean
public CuratorFramework curatorFramework(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(wrapperZK.getElapsedTimeMs(),wrapperZK.getRetryCount());
CuratorFramework client = CuratorFrameworkFactory.newClient(wrapperZK.getConnectString(), wrapperZK.getSessionTimeOutMs(), wrapperZK.getConnectionTimeOutMs(), retryPolicy);
client.start();
return client;
}
}
- 使用
@Autowired
private CuratorFramework curatorFramework;
static InterProcessLock zkLock;
/** 使用zookeeper分布式锁 */
@Transactional
public void updateByZookeeperLock(Long id,int count){
if(zkLock == null){
zkLock = new InterProcessMutex(curatorFramework, "/locks");
}
try {
boolean acquire = zkLock.acquire(10000, TimeUnit.MILLISECONDS);
/** 加锁*/
if(acquire){
Product product = mapper.selectById(id);
int newCont = product.getProductCount() - count;
product.setProductCount(newCont);
if(mapper.updateProduct(product) >0 ){
System.out.println("扣减成功!");
}else {
throw new RuntimeException("扣减失败");
}
}else {
System.out.println("拿不到分布式锁!");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
/** 释放锁*/
zkLock.release();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService service;
@GetMapping("buy/{id}/{count}")
public void buy(@PathVariable long id,@PathVariable int count){
service.updateByZookeeperLock(id,count);
}
}
- 测试
压测前:
压测:
压测后:
成功!