在分布式系统中,多个服务可能需要访问共享资源,而为了保证资源的一致性和完整性,必须使用分布式锁。分布式锁用于控制不同机器上的应用程序访问共享资源的时序问题。本文将通过 Java 使用 Redisson 来实现一个分布式锁。
代码实现:
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.Redisson;
import java.util.concurrent.TimeUnit;
public class DistributedLockExample {
private static RedissonClient redissonClient;
// 初始化 Redisson 客户端
public static void initRedisson() {
Config config = new Config();
// 使用 Redis 服务器的 IP 和端口
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
redissonClient = Redisson.create(config);
}
// 锁定共享资源
public static void acquireLock(String lockName) {
// 创建分布式锁
RLock lock = redissonClient.getLock(lockName);
try {
// 尝试获得锁,最多等待 10 秒,锁定后 30 秒自动释放
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName() + " 获得锁 " + lockName);
// 模拟共享资源的操作
simulateSharedResourceOperation();
} else {
System.out.println(Thread.currentThread().getName() + " 获取锁失败,正在重试...");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
System.out.println(Thread.currentThread().getName() + " 释放锁 " + lockName);
}
}
}
// 模拟操作共享资源
private static void simulateSharedResourceOperation() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + " 正在操作共享资源...");
// 模拟一些耗时操作,例如数据库操作、文件操作等
Thread.sleep(5000);
}
// 关闭 Redisson 客户端
public static void shutdownRedisson() {
if (redissonClient != null) {
redissonClient.shutdown();
}
}
public static void main(String[] args) throws InterruptedException {
// 初始化 Redisson 客户端
initRedisson();
// 使用多个线程模拟不同服务
Thread thread1 = new Thread(() -> acquireLock("sharedLock"));
Thread thread2 = new Thread(() -> acquireLock("sharedLock"));
Thread thread3 = new Thread(() -> acquireLock("sharedLock"));
// 启动线程
thread1.start();
thread2.start();
thread3.start();
// 等待线程执行完成
thread1.join();
thread2.join();
thread3.join();
// 关闭 Redisson 客户端
shutdownRedisson();
}
}
代码解析:
-
RedissonClient 初始化:
- 在
initRedisson方法中,我们通过Redisson.create创建了一个RedissonClient实例,并连接到 Redis 服务器。此代码假设 Redis 服务器地址为redis://127.0.0.1:6379。
- 在
-
获取和释放分布式锁:
- 使用
redissonClient.getLock(lockName)创建一个基于 Redis 的分布式锁(RLock)。 - 在
acquireLock方法中,tryLock方法尝试获取锁。tryLock的第一个参数是最大等待时间,第二个参数是锁的超时释放时间,单位是秒。 - 获取锁后,模拟了对共享资源的操作,模拟的操作持续 5 秒。
- 无论是否获取到锁,程序都会在最后释放锁。
- 使用
-
多线程模拟:
- 在
main方法中,我们创建了三个线程来模拟不同的服务同时请求同一个共享资源的情况。每个线程都调用acquireLock方法来尝试获取分布式锁。
- 在
-
锁释放:
unlock()方法在操作完成后释放锁。需要注意的是,只有持有锁的线程才能释放该锁。
使用说明:
-
环境要求:
- 本代码依赖于 Redis 和 Redisson。你需要安装并运行 Redis 服务器,并将 Redisson 库添加到你的项目中(通过 Maven 或 Gradle)。
- Maven 依赖:
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.16.3</version> </dependency>
-
功能描述:
- 该示例展示了如何通过 Redisson 实现分布式锁,确保不同实例(线程)在访问共享资源时能够按序访问,避免出现数据竞争等问题。
- 我们在 Redis 中使用一个分布式锁,保证多个不同的服务实例在分布式环境中能正确地竞争共享资源。
-
如何使用:
- 初始化 Redisson 客户端时,可以更改 Redis 的连接配置,支持集群、主从等多种 Redis 部署方式。
- 可以调整锁的等待时间、过期时间和锁的名称来满足不同的业务需求。
- 本示例模拟了三种线程请求同一个锁,并展示了分布式锁的竞争与释放。
-
场景应用:
- 本例适用于需要多线程或多服务实例竞争同一资源的场景,例如:
- 分布式数据库操作:确保多个应用不会同时插入或修改相同的记录。
- 分布式任务调度:确保只有一个服务实例执行定时任务。
- 分布式计数器:在多个实例间协调访问和更新计数器。
- 本例适用于需要多线程或多服务实例竞争同一资源的场景,例如:
总结:
通过 Java 和 Redisson 实现的分布式锁,可以有效解决分布式系统中多实例间对共享资源的访问问题。Redisson 提供了简洁的 API,支持 Redis 环境下的分布式锁、信号量、队列等多种同步工具,能够简化开发者的分布式系统编程工作。在大规模、高并发的系统中,使用分布式锁能有效保证数据的一致性和完整性。
898

被折叠的 条评论
为什么被折叠?



