Redis的分布式锁如何使用和代码示例

 更新时间:2025年11月15日 12:00:15   作者:辞暮尔尔-烟火年年  
Redis分布式锁是一种有效的工具,用于在分布式环境中实现互斥访问,Redis提供了一种简单且高效的方式来实现分布式锁,下面给大家介绍是如何使用Redis实现分布式锁的,感兴趣的朋友跟随小编一起看看吧

在分布式系统中,分布式锁是一种关键的工具,用于确保多个进程在不同机器上能够安全地访问共享资源。Redis 提供了一种简单且高效的方式来实现分布式锁。以下是如何使用 Redis 实现分布式锁的详细介绍和代码示例。

1. 分布式锁的基本原理

Redis 分布式锁的基本原理是使用 Redis 的 SET 命令来尝试设置一个键,如果该键不存在,则表示获取锁成功。为了防止死锁,需要为锁设置过期时间。

2. 使用 Jedis 实现 Redis 分布式锁

以下是使用 Jedis 客户端在 Java 中实现 Redis 分布式锁的完整示例。

依赖添加

在你的 Maven 项目中添加 Jedis 依赖:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>

分布式锁实现类

下面是一个简单的 Redis 分布式锁实现类:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
public class RedisDistributedLock {
    private final Jedis jedis;
    private final String lockKey;
    private final long expireTime;
    public RedisDistributedLock(Jedis jedis, String lockKey, long expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
    }
    public boolean acquireLock(String lockValue) {
        SetParams params = new SetParams().nx().px(expireTime);
        String result = jedis.set(lockKey, lockValue, params);
        return "OK".equals(result);
    }
    public boolean releaseLock(String lockValue) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                        "return redis.call('del', KEYS[1]) " +
                        "else return 0 end";
        Object result = jedis.eval(script, 1, lockKey, lockValue);
        return "1".equals(result.toString());
    }
    public static void main(String[] args) {
        try (Jedis jedis = new Jedis("localhost", 6379)) {
            String lockKey = "myLock";
            String lockValue = "myUniqueValue";
            long expireTime = 30000; // 30 seconds
            RedisDistributedLock lock = new RedisDistributedLock(jedis, lockKey, expireTime);
            // Acquire lock
            if (lock.acquireLock(lockValue)) {
                System.out.println("Lock acquired!");
                // Do your critical section work here
                // Release lock
                if (lock.releaseLock(lockValue)) {
                    System.out.println("Lock released!");
                } else {
                    System.out.println("Failed to release lock!");
                }
            } else {
                System.out.println("Failed to acquire lock!");
            }
        }
    }
}

3. 详细解释

  • acquireLock 方法:该方法尝试获取锁。使用 SET 命令和 NX(仅当键不存在时设置)和 PX(设置过期时间)参数来确保设置锁时的原子性。返回 true 表示获取锁成功,返回 false 表示获取锁失败。
  • releaseLock 方法:该方法释放锁。使用 Lua 脚本来确保释放锁的原子性,确保只有持有锁的客户端才能释放锁。Lua 脚本检查当前锁的值是否与传入的值匹配,如果匹配则删除锁。

4. 注意事项

  • 锁的过期时间:确保锁的过期时间足够长,可以覆盖所有可能的操作时间,但也不能太长,以防止死锁。
  • 唯一标识:确保每个客户端设置的 lockValue 唯一,这样可以确保只有持有锁的客户端才能释放锁。
  • 容错处理:在实际应用中,还需要考虑网络分区、Redis 故障等情况,可以使用 Redlock 算法来增强可靠性。

5. 使用 Redlock 算法

Redlock 是 Redis 提供的一种分布式锁算法,旨在提高分布式环境下锁的可靠性。其基本思想是在多个独立的 Redis 实例上尝试获取锁,以提高容错性。

以下是使用 Redlock 算法的实现示例:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.params.SetParams;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class RedisRedlock {
    private final List<JedisPool> jedisPools;
    private final long expireTime;
    private final long retryDelay;
    private final int retryCount;
    public RedisRedlock(List<JedisPool> jedisPools, long expireTime, long retryDelay, int retryCount) {
        this.jedisPools = jedisPools;
        this.expireTime = expireTime;
        this.retryDelay = retryDelay;
        this.retryCount = retryCount;
    }
    public String acquireLock(String lockKey) {
        String lockValue = UUID.randomUUID().toString();
        int n = jedisPools.size();
        int quorum = n / 2 + 1;
        for (int i = 0; i < retryCount; i++) {
            int count = 0;
            long startTime = System.currentTimeMillis();
            for (JedisPool pool : jedisPools) {
                try (Jedis jedis = pool.getResource()) {
                    SetParams params = new SetParams().nx().px(expireTime);
                    String result = jedis.set(lockKey, lockValue, params);
                    if ("OK".equals(result)) {
                        count++;
                    }
                }
            }
            long elapsedTime = System.currentTimeMillis() - startTime;
            if (count >= quorum && elapsedTime <= expireTime) {
                return lockValue;
            } else {
                for (JedisPool pool : jedisPools) {
                    try (Jedis jedis = pool.getResource()) {
                        if (lockValue.equals(jedis.get(lockKey))) {
                            jedis.del(lockKey);
                        }
                    }
                }
            }
            try {
                Thread.sleep(retryDelay);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        return null;
    }
    public boolean releaseLock(String lockKey, String lockValue) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                        "return redis.call('del', KEYS[1]) " +
                        "else return 0 end";
        boolean success = false;
        for (JedisPool pool : jedisPools) {
            try (Jedis jedis = pool.getResource()) {
                Object result = jedis.eval(script, Arrays.asList(lockKey), Arrays.asList(lockValue));
                if ("1".equals(result.toString())) {
                    success = true;
                }
            }
        }
        return success;
    }
    public static void main(String[] args) {
        List<JedisPool> jedisPools = Arrays.asList(
                new JedisPool("localhost", 6379),
                new JedisPool("localhost", 6380),
                new JedisPool("localhost", 6381)
        );
        long expireTime = 30000; // 30 seconds
        long retryDelay = 200; // 200 milliseconds
        int retryCount = 3;
        RedisRedlock redlock = new RedisRedlock(jedisPools, expireTime, retryDelay, retryCount);
        String lockKey = "myLock";
        String lockValue = redlock.acquireLock(lockKey);
        if (lockValue != null) {
            System.out.println("Lock acquired!");
            // Do your critical section work here
            if (redlock.releaseLock(lockKey, lockValue)) {
                System.out.println("Lock released!");
            } else {
                System.out.println("Failed to release lock!");
            }
        } else {
            System.out.println("Failed to acquire lock!");
        }
    }
}

总结

Redis 分布式锁是一种有效的工具,用于在分布式环境中实现互斥访问。通过使用 Jedis 客户端,可以方便地实现基本的分布式锁功能。而 Redlock 算法则提供了一种更可靠的分布式锁实现,适用于对容错性要求较高的场景。合理配置和使用分布式锁,可以显著提高分布式系统的稳定性和一致性。

到此这篇关于Redis的分布式锁如何使用和代码示例的文章就介绍到这了,更多相关redis分布式锁使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • redis在Windows中下载及安装、设置教程

    redis在Windows中下载及安装、设置教程

    这篇文章主要介绍了Windows中redis的下载及安装、设置教程,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • Redis哨兵模式的实现

    Redis哨兵模式的实现

    Redis的哨兵模式是一种用于自动监控Redis实例状态并在主服务器出现故障时自动切换到从服务器的机制,本文主要介绍了Redis哨兵模式的实现,感兴趣的可以了解一下
    2024-02-02
  • 在redisCluster中模糊获取key方式

    在redisCluster中模糊获取key方式

    这篇文章主要介绍了在redisCluster中模糊获取key方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Redis7.2.x主从复制的实现示例

    Redis7.2.x主从复制的实现示例

    本文主要介绍了Redis7.2.x主从复制的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Redis哨兵机制的使用详解

    Redis哨兵机制的使用详解

    文章讲解了Redis哨兵机制的基本原理、主库和从库自动切换的过程、如何减少误判、哨兵集群的组成和通信机制,以及哨兵在故障发生时如何选举Leader进行主从切换
    2025-01-01
  • Redis秒杀实现方案讲解

    Redis秒杀实现方案讲解

    这篇文章主要介绍了Redis秒杀实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • Redis分片集群的实现方法

    Redis分片集群的实现方法

    Redis Cluster是Redis官方提供的分布式解决方案,它不是像哨兵那样只负责高可用切换,而是同时解决了数据分片和高可用两个问题,感兴趣的可以了解一下
    2025-08-08
  • Redis中的通用命令解读

    Redis中的通用命令解读

    这篇文章主要介绍了Redis中的通用命令,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-07-07
  • Redis如何从海量key中查询出某一固定前缀的key

    Redis如何从海量key中查询出某一固定前缀的key

    当Redis存储一亿key时,使用keys指令可能因返回全部key导致服务器卡顿,而scan指令通过游标分批获取,避免阻塞,适合生产环境,需注意重复结果可用hashSet去重,count参数可调整返回数量但非强制
    2025-07-07
  • Redis实现分布式锁的示例代码

    Redis实现分布式锁的示例代码

    分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现,本文就来介绍一下Redis实现分布式锁的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08

最新评论