Redis(161)如何使用Redis实现分布式锁?

分布式锁是用来在分布式系统下控制对资源的独占访问,确保多个进程或线程不会同时操作同一资源。Redis 是实现分布式锁的常用工具之一。下面是详细的实现步骤和代码示例:

1. Redis 分布式锁的基本实现

通过设置一个唯一的键来实现锁,当操作完成后删除该键即可释放锁。

1.1 获取锁

使用 SET 命令并设置过期时间。NX 参数表示只有在键不存在时才能设置成功,EX 参数用于设置键的过期时间。

bash 复制代码
SET lock_key unique_value NX EX 10

1.2 释放锁

只有持有锁的客户端才能删除锁。为了确保这一点,需要在释放锁时进行唯一值验证。

bash 复制代码
# Lua脚本原子性地检查唯一值并删除锁
if redis.call("GET", KEYS[1]) == ARGV[1] then
    return redis.call("DEL", KEYS[1])
else
    return 0
end

2. Java 实现 Redis 分布式锁

2.1 引入依赖

在 Maven 项目中引入 Jedis 依赖:

xml 复制代码
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.5.2</version>
</dependency>

2.2 获取锁的方法

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class RedisDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public RedisDistributedLock(Jedis jedis, String lockKey, String lockValue, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.lockValue = lockValue;
        this.expireTime = expireTime;
    }

    public boolean acquireLock() {
        SetParams setParams = new SetParams();
        setParams.nx().ex(expireTime);
        // 尝试获取锁
        String result = jedis.set(lockKey, lockValue, setParams);
        return "OK".equals(result);
    }

    public boolean releaseLock() {
        // 释放锁的 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, lockValue);
        return "1".equals(result.toString());
    }

    public static void main(String[] args) {
        // 连接到本地 Redis 服务
        Jedis jedis = new Jedis("localhost");

        String lockKey = "distributed_lock";
        String lockValue = "unique_value";
        int expireTime = 10; // 锁的过期时间,单位为秒

        RedisDistributedLock lock = new RedisDistributedLock(jedis, lockKey, lockValue, expireTime);

        // 获取锁
        if (lock.acquireLock()) {
            try {
                // 执行你的逻辑
                System.out.println("Lock acquired!");

                // 模拟业务处理时间
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放锁
                if (lock.releaseLock()) {
                    System.out.println("Lock released!");
                } else {
                    System.out.println("Failed to release lock!");
                }
            }
        } else {
            System.out.println("Failed to acquire lock!");
        }

        jedis.close();
    }
}

3. Redisson 提供的分布式锁

Redisson 是一个开源的 Redis 客户端,提供了更高级的分布式锁实现,与 Java 的java.util.concurrent.locks.Lock接口兼容。

3.1 引入依赖

在 Maven 项目中引入 Redisson 依赖:

xml 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.16.5</version>
</dependency>

3.2 使用 Redisson 实现分布式锁

java 复制代码
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 RedissonDistributedLock {
    public static void main(String[] args) {
        // 创建 Redisson 配置
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");

        // 创建 Redisson 客户端
        RedissonClient redissonClient = Redisson.create(config);

        // 获取锁对象
        RLock lock = redissonClient.getLock("distributed_lock");

        try {
            // 尝试获取锁,等待时间10秒,持有锁30秒
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                try {
                    // 执行你的逻辑
                    System.out.println("Lock acquired!");

                    // 模拟业务处理时间
                    Thread.sleep(5000);
                } finally {
                    // 释放锁
                    lock.unlock();
                    System.out.println("Lock released!");
                }
            } else {
                System.out.println("Failed to acquire lock!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            redissonClient.shutdown();
        }
    }
}

总结

通过配置 Redis 和编写合适的代码,可以实现可靠的分布式锁。上述示例展示了如何使用 Jedis 和 Redisson 来实现分布式锁。使用 Jedis 提供了更灵活的低级实现,而 Redisson 提供了更高级别的 API,使得分布式锁的使用更加简单和直观。选择合适的工具和方法取决于具体的应用场景和需求。

相关推荐
MegaDataFlowers8 分钟前
快速上手Spring
java·后端·spring
小江的记录本9 分钟前
【MyBatis-Plus】Spring Boot + MyBatis-Plus 进行各种数据库操作(附完整 CRUD 项目代码示例)
java·前端·数据库·spring boot·后端·sql·mybatis
大傻^15 分钟前
Spring AI Alibaba Function Calling:外部工具集成与业务函数注册
java·人工智能·后端·spring·springai·springaialibaba
码界奇点22 分钟前
基于Spring Boot的医院药品管理系统设计与实现
java·spring boot·后端·车载系统·毕业设计·源代码管理
小旭952726 分钟前
Spring MVC :从入门到精通(下)
java·后端·spring·mvc
SimonKing2 小时前
全网爆火的OpenClaw保姆级教程Linux版,它来了。
java·后端·程序员
青柠代码录2 小时前
【Linux】常用命令:sort
后端
小江的记录本3 小时前
【MyBatis-Plus】MyBatis-Plus的核心特性、条件构造器、分页插件、乐观锁插件
java·前端·spring boot·后端·sql·tomcat·mybatis
驕傲的兎孒3 小时前
基于 SpringBoot + Vue3 + AI 打造企业级售后服务支持平台 | 实战方案分享
人工智能·spring boot·后端
大傻^3 小时前
Spring AI Alibaba 可观测性实践:AI应用监控与链路追踪
java·人工智能·后端·spring·springaialibaba