Redis 分布式锁教程
简介
在分布式系统中,多个进程可能会尝试同时访问共享资源,这会导致数据不一致或者竞争条件。分布式锁是一种用于控制对共享资源访问的机制。Redis 是一个流行的内存数据存储系统,可以用来实现分布式锁。
本文将介绍如何使用 Redis 实现分布式锁,并提供一个简单的 Java 代码示例。
环境准备
在开始之前,请确保你的开发环境已经安装了以下组件:
- Java Development Kit (JDK) 8 或更高版本
- Maven 或其他构建工具
- Redis 服务器
引入依赖
首先,在你的 pom.xml
文件中引入 Jedis(一个 Redis 的 Java 客户端)的依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.1.3</version>
</dependency>
示例代码
下面是一个简单的 Java 代码示例,展示如何使用 Redis 实现分布式锁。
RedisLock.java
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
public class RedisLock {
private Jedis jedis;
private String lockKey;
private int lockExpireTime;
public RedisLock(Jedis jedis, String lockKey, int lockExpireTime) {
this.jedis = jedis;
this.lockKey = lockKey;
this.lockExpireTime = lockExpireTime;
}
public boolean acquireLock(String uniqueId) {
// 使用 SETNX 命令设置锁
String result = jedis.set(lockKey, uniqueId, new SetParams().nx().px(lockExpireTime));
return "OK".equals(result);
}
public boolean releaseLock(String uniqueId) {
// 使用 Lua 脚本确保释放锁的原子性
String luaScript =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) " +
"else " +
"return 0 " +
"end";
Object result = jedis.eval(luaScript, 1, lockKey, uniqueId);
return result != null && (Long) result > 0;
}
}
Main.java
import redis.clients.jedis.Jedis;
import java.util.UUID;
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(new RedisLocalTest()).start();
}
}
static class RedisLocalTest implements Runnable {
String lockKey = "myLock";
int lockExpireTime = 10000; // 锁过期时间为 10 秒
public void run() {
Jedis jedis = new Jedis("localhost", 6379);
//jedis.auth("123456"); // redis 配置密码需要设置
RedisLock redisLock = new RedisLock(jedis, lockKey, lockExpireTime);
String uniqueId = UUID.randomUUID().toString();
String threadName = Thread.currentThread().getName();
if (redisLock.acquireLock(uniqueId)) {
System.out.println(threadName + " 获取到锁!");
// 在这里执行你的业务逻辑
try {
Thread.sleep(5000); // 模拟业务处理时间
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (redisLock.releaseLock(uniqueId)) {
System.out.println(threadName + " 锁已释放!");
} else {
System.out.println(threadName + " 释放锁失败!");
}
}
} else {
System.err.println(threadName + " 未能获取到锁!");
}
jedis.close();
}
}
}
运行示例
- 启动 Redis 服务器。
- 编译并运行
Main
类。
你应该会看到类似如下的输出:
Thread-0 获取到锁!
Thread-2 未能获取到锁!
Thread-1 未能获取到锁!
Thread-0 锁已释放!
结论
本文介绍了如何使用 Redis 实现分布式锁,并提供了一个简单的 Java 示例代码。通过这种方式,你可以确保在分布式系统中多个进程对共享资源的访问是有序且安全的。希望这篇文章对你有所帮助!
如果你有任何问题或改进建议,欢迎讨论!