- zookeeper的配置和安装请移步zookeeper的安装
- 分布式锁的可选择性一般常用的为redis的分布式锁和zookeeper的分布式锁,redis是以一个key值作为唯一,zookeeper是以创建的临时节点下的子节点来创建一个唯一,redis分布式锁请移步基于redisson的分布式锁
- 下面是具体的代码实现
- 依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.gitee.reger</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.0.9</version>
</dependency>
server.port=8081
#服务治理当前项目的名称
spring.dubbo.application.name=servermodule
#暴露服务的包路径
spring.dubbo.base-package=com.sunyw.xyz.service
#zookeeper的注册地址
spring.dubbo.registry.address=127.0.0.1
#zookeeper的端口
spring.dubbo.registry.port=2181
#性能调优,balabala.....
spring.dubbo.protocol.name=dubbo
#重试次数,默认为2,这里设置为0
spring.dubbo.provider.retries=0
#超时时间
spring.dubbo.consumer.timeout=40000
spring.dubbo.registry.timeout=40000
spring.dubbo.provider.timeout=40000
#配置实际地址,只是多地址配置示范规则为 ip1:port1, ip2:port2.....
zookeeper.address=127.0.0.1:2181,127.0.0.1:2181,127.0.0.1:2181
- 配置类主要配置了curator,curator是一个zookeeper的操作框架,官网地址curator
package com.sunyw.xyz.service.version.config;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.CuratorEventType;
import org.apache.curator.framework.api.CuratorListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.WatchedEvent;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ZkServerConfig {
@Value("${zookeeper.address}")
private String zkAddress;
@Bean
public CuratorFramework initCurator() {
ExponentialBackoffRetry retry = new ExponentialBackoffRetry(1000, 3);
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(zkAddress, retry);
curatorFramework.getCuratorListenable().addListener(new ZkListener() {
});
curatorFramework.start();
return curatorFramework;
}
/**
* 监听
*/
public class ZkListener implements CuratorListener {
@Override
public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {
CuratorEventType eventType = event.getType();
if (eventType == CuratorEventType.WATCHED) {
WatchedEvent eventWatchedEvent = event.getWatchedEvent();
String eventPath = eventWatchedEvent.getPath();
if (null != eventPath) {
client.checkExists().watched().forPath(eventPath);
}
}
}
}
}
- 业务代码,模拟减库存,没有使用到数据库,大概可以看一下
package com.sunyw.xyz.service.version.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
@Slf4j
public class ZkLockController {
@Autowired
private CuratorFramework curatorFramework;
/**
* 临时节点名称
*/
private static final String LOCK_NAME = "/lock";
/**
* 库存
*/
private int kz = 5;
/**
* zookeeper分布式锁使用demo
* @param id
* @return
*/
@GetMapping("/add/{id}")
public String add(@PathVariable String id) {
String name = Thread.currentThread().getName();
log.info("线程{}->开始进入add方法", name);
InterProcessSemaphoreMutex mutex = new InterProcessSemaphoreMutex(curatorFramework, LOCK_NAME);
log.info("线程{}->开始获取🔒", name);
boolean acquire;
try {
acquire = mutex.acquire(6000, TimeUnit.SECONDS);
if (acquire) {
log.info("线程{}->获取🔒成功开始进行购买,剩余数量{}", name, kz);
if (kz == 0) {
log.info("销售一空了~~~~~~~~~~~~~~~~~~~~~~~~");
return "销售一空";
}
kz--;
Thread.sleep(1000);
log.info("线程{}->购买完毕", name);
}
} catch (Exception e) {
log.error("业务执行错误信息-->", e);
} finally {
log.info("线程{}->开始释放🔒", name);
try {
mutex.release();
log.info("线程{}->释放🔒成功", name);
} catch (Exception e) {
log.error("释放🔒错误信息-->", e);
}
}
return "SUCCESS";
}
}
- 执行结果