本文目录导读:

我来为您提供Java分布式锁的完整案例,包含多种实现方案:
基于Redis的分布式锁
1 基础版本 - 使用SETNX + 过期时间
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class RedisLock {
private Jedis jedis;
private String lockKey;
private String lockValue;
private long expireTime = 30; // 默认过期时间(秒)
public RedisLock(Jedis jedis, String lockKey) {
this.jedis = jedis;
this.lockKey = lockKey;
}
/**
* 获取分布式锁
*/
public boolean lock(long waitTimeout, long expireTime) {
this.lockValue = UUID.randomUUID().toString();
this.expireTime = expireTime;
long startTime = System.currentTimeMillis();
try {
// 使用SET命令实现原子性加锁
while (true) {
SetParams params = new SetParams();
params.nx().px(expireTime * 1000);
String result = jedis.set(lockKey, lockValue, params);
if ("OK".equals(result)) {
System.out.println("获取锁成功: " + lockValue);
return true;
}
// 判断是否超时
if ((System.currentTimeMillis() - startTime) > waitTimeout) {
System.out.println("获取锁超时");
return false;
}
Thread.sleep(100); // 等待100ms后重试
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 释放分布式锁(使用Lua脚本保证原子性)
*/
public void unlock() {
String script = "if redis.call('get',KEYS[1]) == ARGV[1] then " +
"return redis.call('del',KEYS[1]) " +
"else return 0 end";
Long result = (Long) jedis.eval(script,
java.util.Collections.singletonList(lockKey),
java.util.Collections.singletonList(lockValue));
if (result > 0) {
System.out.println("释放锁成功: " + lockValue);
} else {
System.out.println("释放锁失败,锁已过期或被其他线程持有");
}
}
// 使用示例
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost", 6379);
RedisLock lock = new RedisLock(jedis, "product:1001");
try {
// 尝试获取锁,等待5秒,锁过期时间30秒
if (lock.lock(5000, 30)) {
// 执行业务逻辑
System.out.println("执行业务逻辑...");
Thread.sleep(2000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
2 使用Redisson框架(推荐)
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import java.util.concurrent.TimeUnit;
public class RedissonLockDemo {
private RedissonClient redissonClient;
public void init() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://localhost:6379")
.setPassword("123456")
.setConnectionPoolSize(10)
.setConnectionMinimumIdleSize(5);
redissonClient = Redisson.create(config);
}
/**
* 使用Redisson分布式锁(自动续期机制)
*/
public void demoLock() {
RLock lock = redissonClient.getLock("order:lock");
try {
// 尝试加锁,等待2秒,持锁30秒
if (lock.tryLock(2, 30, TimeUnit.SECONDS)) {
System.out.println("获取锁成功");
// 执行业务逻辑
businessProcess();
} else {
System.out.println("获取锁失败");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
System.out.println("释放锁");
}
}
}
// 看门狗机制 - 自动续期
public void demoWithWatchDog() {
RLock lock = redissonClient.getLock("order:lock");
try {
// 不指定过期时间,使用看门狗自动续期(默认30秒,每10秒续期一次)
lock.lock();
System.out.println("获取锁成功,自动续期模式");
// 长时间业务操作,不需要担心锁过期
businessProcess();
} finally {
lock.unlock();
}
}
private void businessProcess() {
// 模拟业务逻辑
try {
Thread.sleep(5000);
System.out.println("业务处理完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
基于ZooKeeper的分布式锁
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class ZookeeperLock implements Watcher {
private ZooKeeper zk;
private String root = "/locks";
private String lockName;
private String selfPath;
private String waitPath;
private CountDownLatch connectedLatch = new CountDownLatch(1);
private CountDownLatch waitLatch;
public ZookeeperLock(String connectString, String lockName) {
this.lockName = lockName;
try {
zk = new ZooKeeper(connectString, 3000, this);
connectedLatch.await();
// 创建根节点
if (zk.exists(root, false) == null) {
zk.create(root, new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 尝试获取锁(临时顺序节点实现)
*/
public boolean lock() {
try {
// 创建临时顺序节点
selfPath = zk.create(root + "/" + lockName,
new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("创建节点: " + selfPath);
// 获取所有子节点
List<String> children = zk.getChildren(root, false);
Collections.sort(children);
// 判断当前节点是否是最小节点
String selfNode = selfPath.substring(selfPath.lastIndexOf("/") + 1);
int index = children.indexOf(selfNode);
if (index == 0) {
// 最小节点,获取锁成功
System.out.println("获取锁成功");
return true;
} else {
// 监听前一个节点
waitPath = root + "/" + children.get(index - 1);
waitLatch = new CountDownLatch(1);
zk.exists(waitPath, true);
System.out.println("等待前一个节点释放: " + waitPath);
// 等待前一个节点删除
waitLatch.await();
return true;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 释放锁
*/
public void unlock() {
try {
if (zk != null && selfPath != null) {
zk.delete(selfPath, -1);
System.out.println("释放锁: " + selfPath);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (zk != null) {
zk.close();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected) {
connectedLatch.countDown();
}
// 检查节点删除事件
if (event.getType() == Event.EventType.NodeDeleted) {
if (event.getPath().equals(waitPath)) {
waitLatch.countDown();
}
}
}
// 使用示例
public static void main(String[] args) {
ZookeeperLock lock = new ZookeeperLock("localhost:2181", "order");
try {
if (lock.lock()) {
System.out.println("执行业务逻辑...");
Thread.sleep(3000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
使用Spring Integration分布式锁
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@Service
public class SpringIntegrationLockDemo {
@Autowired
private RedisLockRegistry redisLockRegistry;
public void businessMethod(String orderId) {
// 创建锁
Lock lock = redisLockRegistry.obtain("lock:" + orderId);
boolean isLocked = false;
try {
// 尝试获取锁,等待5秒
isLocked = lock.tryLock(5, TimeUnit.SECONDS);
if (isLocked) {
System.out.println("获取锁成功,执行订单: " + orderId);
// 业务逻辑
processOrder(orderId);
} else {
System.out.println("获取锁失败");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
if (isLocked) {
lock.unlock();
System.out.println("释放锁");
}
}
}
private void processOrder(String orderId) {
// 业务处理逻辑
System.out.println("处理订单业务...");
}
}
分布式锁实战应用示例
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* 分布式锁实战 - 电商订单防重
*/
public class OrderLockService {
private static final Logger logger = LoggerFactory.getLogger(OrderLockService.class);
private RedissonClient redissonClient;
public OrderLockService() {
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
redissonClient = Redisson.create(config);
}
/**
* 创建订单(使用分布式锁防止重复提交)
*/
public Result createOrder(OrderRequest request) {
// 使用用户ID+商品ID作为锁的key
String lockKey = "order:create:" + request.getUserId() + ":" + request.getProductId();
RLock lock = redissonClient.getLock(lockKey);
try {
// 尝试获取锁,等待3秒
if (!lock.tryLock(3, TimeUnit.SECONDS)) {
return Result.fail("操作太频繁,请稍后再试");
}
logger.info("获取锁成功, userId={}, productId={}",
request.getUserId(), request.getProductId());
// 检查是否已存在订单
if (checkOrderExist(request)) {
return Result.fail("订单已存在,请勿重复提交");
}
// 创建订单
Order order = createNewOrder(request);
// 扣减库存
reduceStock(request.getProductId(), request.getQuantity());
return Result.success(order);
} catch (Exception e) {
logger.error("创建订单失败", e);
return Result.fail("系统异常,请稍后再试");
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
logger.info("释放锁成功");
}
}
}
/**
* 模拟多线程并发下单测试
*/
public void testConcurrentOrder() {
int threadCount = 10;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
final int userId = i;
new Thread(() -> {
try {
latch.await();
OrderRequest request = new OrderRequest();
request.setUserId(userId);
request.setProductId(1001L);
request.setQuantity(1);
Result result = createOrder(request);
System.out.println("用户" + userId + "下单结果: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
latch.countDown();
}
}
private boolean checkOrderExist(OrderRequest request) {
// 查询数据库检查订单是否存在
return false;
}
private Order createNewOrder(OrderRequest request) {
// 创建订单逻辑
return new Order();
}
private void reduceStock(Long productId, Integer quantity) {
// 扣减库存逻辑
}
// 辅助类
static class OrderRequest {
private Integer userId;
private Long productId;
private Integer quantity;
// getters and setters...
public Integer getUserId() { return userId; }
public void setUserId(Integer userId) { this.userId = userId; }
public Long getProductId() { return productId; }
public void setProductId(Long productId) { this.productId = productId; }
public Integer getQuantity() { return quantity; }
public void setQuantity(Integer quantity) { this.quantity = quantity; }
}
static class Order {
private Long id;
private Integer userId;
// ...
}
static class Result {
private boolean success;
private String message;
private Object data;
public static Result success(Object data) {
Result result = new Result();
result.success = true;
result.data = data;
return result;
}
public static Result fail(String message) {
Result result = new Result();
result.success = false;
result.message = message;
return result;
}
@Override
public String toString() {
return "Result{success=" + success + ", message='" + message + "'}";
}
}
}
分布式锁配置类
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;
@Configuration
public class DistributedLockConfig {
/**
* Redisson客户端配置
*/
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://192.168.1.100:6379")
.setPassword("123456")
.setDatabase(0)
.setConnectionPoolSize(50)
.setConnectionMinimumIdleSize(10)
.setTimeout(3000)
.setRetryAttempts(3)
.setRetryInterval(1500);
return Redisson.create(config);
}
/**
* Spring Integration 锁注册表
*/
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory connectionFactory) {
return new RedisLockRegistry(connectionFactory, "spring-integration-lock", 30000);
}
}
Maven依赖配置
<dependencies>
<!-- Redis Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<!-- Redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.8</version>
</dependency>
<!-- ZooKeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.3</version>
</dependency>
<!-- Spring Integration Redis -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
<version>5.5.15</version>
</dependency>
<!-- Spring Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
关键设计要点
Redis分布式锁注意事项
- 原子性:使用SET NX EX命令确保原子操作
- 唯一标识:每个锁必须有唯一标识,防止误删其他线程的锁
- 过期时间:设置合理的过期时间,防止死锁
- 看门狗机制:Redisson的看门狗可以自动续期
ZooKeeper分布式锁
- 临时顺序节点:避免羊群效应
- 监听机制:只监听前一个节点
- 会话超时:处理心跳超时场景
最佳实践建议
// 锁的粒度设计
// - 细粒度:订单ID、用户ID
// - 粗粒度:库存、账户
// 超时时间设计
lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
// waitTime: 等待获取锁的时间
// leaseTime: 锁的持有时间
// 错误处理
catch (InterruptedException e) {
Thread.currentThread().interrupt();
// 恢复中断状态
}
这些案例涵盖了主流的分布式锁实现方案,您可以根据实际需求选择合适的方案,生产环境推荐使用Redisson,因为它提供了完善的自动续期机制和高可用支持。