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,使得分布式锁的使用更加简单和直观。选择合适的工具和方法取决于具体的应用场景和需求。

相关推荐
计算机程序设计小李同学36 分钟前
动漫之家系统设计与实现
java·spring boot·后端·web安全
布列瑟农的星空1 小时前
SSE与流式传输(Streamable HTTP)
前端·后端
开心就好20251 小时前
使用 HBuilder 上架 iOS 应用时常见的问题与应对方式
后端
开心猴爷1 小时前
Swift IPA 混淆在工程实践中的方式,分析仅依赖源码层混淆的局限性
后端
用户4099322502122 小时前
Vue3 v-if与v-show:销毁还是隐藏,如何抉择?
前端·vue.js·后端
黄俊懿2 小时前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——全局事务的回滚
java·后端·spring·spring cloud·微服务·架构·架构师
Java编程爱好者2 小时前
SpringBoot启动太慢?几个优化技巧
后端
喷火龙8号2 小时前
修复 Hertz + OpenTelemetry 链路追踪中的数据竞争问题
后端
JIngJaneIL2 小时前
基于springboot + vue健康管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·后端
程序员小胖2 小时前
每天一道面试题之架构篇|Java 热部署插件化架构设计
后端