欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > redisson分布式锁关的疑问和解答记录

redisson分布式锁关的疑问和解答记录

2025/2/5 22:44:41 来源:https://blog.csdn.net/yang2330648064/article/details/145091968  浏览:    关键词:redisson分布式锁关的疑问和解答记录

redisson主从切换锁丢失问题

  • 使用redisson实现分布式锁,可能出现主从切换锁丢失的问题:zookeeper实现分布式锁可解决该问题

问题背景:Redis 主从切换导致分布式锁丢失问题

  • 在 Redis 作为分布式锁的实现中,通常依赖于 SETNX 命令和过期时间(EX)来保证锁的获取与自动释放。但是,当 Redis 部署在主从模式下,可能会出现以下问题:
  1. 主从同步延迟:当 Redis 主节点挂掉时,如果锁信息尚未同步到从节点,新的从节点提升为主节点后,锁的信息可能丢失。
  2. 锁丢失:主从切换后,原本已经持有的锁会被新主节点认为不存在,从而导致锁丢失,出现并发安全问题。

这种情况下,依赖 Redis 的分布式锁无法满足严格一致性的要求,因此需要一种更可靠的分布式锁实现方案。


解决:Zookeeper 能解决 Redis 锁丢失问题

  • Zookeeper 是一种分布式协调服务,利用其强一致性临时节点的特性,可以避免 Redis 在主从切换中出现的锁丢失问题。其核心机制如下:
  1. 临时节点机制

    • 客户端在 Zookeeper 上创建临时节点,如果客户端断开连接(比如因为挂掉或网络中断),Zookeeper 会自动删除临时节点。
    • 锁的持有与客户端的存活绑定,这样可以避免锁长期持有或丢失的问题。
  2. 强一致性保证

    • Zookeeper 通过 ZAB(ZooKeeper Atomic Broadcast)协议保证分布式数据的一致性,确保所有节点看到的数据是完全一致的。
    • 即使在 Zookeeper 的主节点切换过程中,也能保证锁的信息不会丢失。
  3. 顺序节点保证公平性

    • Zookeeper 提供顺序节点,可以实现分布式锁的公平性,即锁按照客户端的请求顺序被依次获取。

因此,Zookeeper 天生适合实现分布式锁,尤其是在需要高可靠性和严格一致性的场景下。


Zookeeper 分布式锁的代码实现

Maven 依赖

<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.5.0</version> <!-- 使用最新版本 -->
</dependency>

代码实现

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;public class ZookeeperDistributedLockExample {// Zookeeper 连接地址private static final String ZOOKEEPER_ADDRESS = "127.0.0.1:2181";// 锁路径private static final String LOCK_PATH = "/locks/my_lock";public static void main(String[] args) {// 创建 Zookeeper 客户端CuratorFramework client = CuratorFrameworkFactory.builder().connectString(ZOOKEEPER_ADDRESS).retryPolicy(new ExponentialBackoffRetry(1000, 3)) // 重试策略.build();client.start(); // 启动客户端// 创建分布式锁InterProcessMutex lock = new InterProcessMutex(client, LOCK_PATH);// 使用分布式锁try {// 获取锁if (lock.acquire(10, java.util.concurrent.TimeUnit.SECONDS)) {try {System.out.println("获取锁成功,开始执行任务...");// 模拟任务执行Thread.sleep(5000);} finally {// 释放锁lock.release();System.out.println("任务完成,释放锁!");}} else {System.out.println("获取锁失败!");}} catch (Exception e) {e.printStackTrace();} finally {// 关闭客户端client.close();}}
}

运行结果

运行上述代码后,你会看到以下输出(假设成功获取锁):

获取锁成功,开始执行任务...
任务完成,释放锁!

如果锁被其他客户端持有,则会提示获取锁失败。


Zookeeper 分布式锁的优缺点

优点

  1. 强一致性:利用 Zookeeper 的强一致性和临时节点机制,保证锁不会丢失。

  2. 高可靠性:即使在主从切换或节点故障时,锁的信息仍然完整,确保分布式系统的正确性。

  3. 公平性:基于顺序节点,可以实现锁的公平性,确保先请求的客户端优先获取锁。

  4. 自动释放:如果客户端崩溃或断开连接,Zookeeper 会自动删除临时节点,释放锁。

缺点

  1. 性能开销:Zookeeper 的一致性协议(ZAB)在强一致性保证下性能相对较低,尤其是在高并发场景下。

  2. 复杂性:部署和维护 Zookeeper 集群比 Redis 更复杂。

  3. 吞吐量限制:Zookeeper 适合处理协调类任务(如分布式锁、选主等),但不适合作为高吞吐量的存储系统。


Redis 和 Zookeeper 分布式锁的比较

特性RedisZookeeper
一致性保证弱一致性(主从切换可能导致锁丢失)强一致性
性能高性能,适合高并发场景性能较低,适合协调类任务
锁的释放机制基于过期时间(可能过早释放)临时节点自动释放
实现复杂性简单(如 Redisson 封装)较复杂(需要配置和维护 Zookeeper 集群)
公平性不支持公平锁(需要额外逻辑实现)天生支持公平性

总结

  • Redis 分布式锁适合高性能、高并发场景,但存在主从切换锁丢失的问题,在要求一致性较低的场景(如简单任务调度)可以使用。
  • Zookeeper 分布式锁在一致性和可靠性方面表现更好,尤其适用于对锁严格要求的场景(如分布式事务、选主机制等)。

  • 如果系统对锁的一致性和可靠性要求高(如不能容忍锁丢失),优先选择 Zookeeper。

redis实现分布式锁的方案:redlock

  • Redlock 是 Redis 提供的一种实现分布式锁的算法,旨在解决单实例 Redis 或主从模式下可能出现的锁丢失、不一致等问题。它是一种基于 多实例 Redis 部署的分布式锁方案,可以增强分布式锁的可靠性和安全性。

Redlock 的设计理念

Redlock 通过以下机制保证锁的安全性和可靠性:

  1. 多实例 Redis 部署:在多个独立的 Redis 实例上同时获取锁,确保即使部分 Redis 实例宕机或不可用,也能保证锁的可靠性。

  2. 时间窗口:锁的有效期是有时间限制的,通过合理设置过期时间,避免死锁或锁长期持有问题。

  3. 分布式一致性:使用 N/2 + 1 的法则确保锁的一致性,即在大多数实例上成功获取锁后,才认为锁获取成功。


Redlock 的核心实现步骤

1. 获取当前时间:在客户端记录当前的时间戳(毫秒)。

2. 顺序尝试获取锁:客户端依次向所有 Redis 实例发送 SET resource_name value NX PX expiration_time 命令。

  • 参数解释:
    • NX:确保只有在锁不存在时才能成功创建。
    • PX expiration_time:设置锁的过期时间,防止死锁。
  • 如果客户端在某个 Redis 实例成功获取到锁,则记录锁成功的实例数量。

3. 校验锁获取成功:如果客户端在 至少 N/2 + 1 个 Redis 实例上成功获取到锁,则认为锁获取成功。否则,释放所有已成功获取锁的实例,返回获取失败。

4. 设置锁的有效时间:客户端需要确保锁的有效时间 大于请求所有 Redis 实例所需的网络延迟时间总和,以避免锁过早失效。
5. 释放锁:客户端执行完任务后,向所有 Redis 实例发送命令,删除对应的锁。确保无论锁是否完全成功,都释放所有可能持有锁的 Redis 实例。


Redlock 的实现关键点

  1. 避免单点故障:Redlock 必须运行在多个独立的 Redis 实例上,避免因单个实例宕机导致锁丢失。

  2. 防止锁超时:确保锁的过期时间大于客户端任务的预期执行时间,并且客户端需要检测超时情况。

  3. 保证锁的唯一性:每次锁请求的 value 都应该是唯一值(例如 UUID),这样可以确保锁的持有者正确释放锁。

  4. 时间窗口限制:锁的总持有时间必须小于网络延迟时间和任务执行时间的总和,否则可能出现锁被错误释放的风险。


Redlock 的代码实现

Maven 依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.23.5</version> <!-- 使用最新版本 -->
</dependency>

Redlock 示例代码

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 RedlockExample {public static void main(String[] args) {// 配置多个 Redis 实例Config config = new Config();config.useReplicatedServers().addNodeAddress("redis://127.0.0.1:6379", // 第一个 Redis 实例"redis://127.0.0.2:6379", // 第二个 Redis 实例"redis://127.0.0.3:6379") // 第三个 Redis 实例.setPassword(null); // 如果有密码,填写在这里// 创建 Redisson 客户端RedissonClient redissonClient = Redisson.create(config);// 获取分布式锁RLock lock = redissonClient.getLock("myRedlock");try {// 尝试加锁,最多等待 10 秒,锁的自动过期时间为 30 秒if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {try {System.out.println("获取锁成功,执行任务...");// 模拟任务执行Thread.sleep(5000);} finally {// 释放锁lock.unlock();System.out.println("任务完成,释放锁!");}} else {System.out.println("获取锁失败!");}} catch (InterruptedException e) {e.printStackTrace();} finally {// 关闭 Redisson 客户端redissonClient.shutdown();}}
}

Redlock 的优缺点

优点

  1. 高可靠性:通过在多个 Redis 实例上获取锁,避免单实例宕机导致的锁丢失问题。

  2. 简单易用:借助 Redisson 等工具,Redlock 的实现非常简单,可以快速部署。

  3. 高性能:Redis 本身性能高,Redlock 适用于大多数高并发分布式场景。

  4. 灵活性:可自定义锁的超时时间和获取重试策略。

缺点

  1. 一致性风险:Redlock 的一致性依赖于 Redis 实例的时间同步和网络延迟,存在锁不完全一致的可能性。

  2. 分布式开销:获取锁时需要访问多个 Redis 实例,网络延迟和可靠性可能会影响性能。

  3. 时间窗口依赖:如果锁的过期时间设置不合理,可能出现锁在任务未完成时被其他客户端获取的风险。


Redlock 适用场景

  1. 分布式任务调度:如定时任务、分布式任务调度系统等。

  2. 分布式资源竞争:如控制对共享资源(如文件、数据库记录等)的并发访问。

  3. 高并发业务逻辑:如防止电商系统中库存超卖、重复订单处理等。


Redlock 与 Zookeeper 的比较

特性Redlock(Redis 实现)Zookeeper 实现
一致性强一致性(存在一定时间窗口的不一致风险)强一致性,无时间窗口风险
性能高性能,适合高并发场景性能较低,适合协调类任务
部署复杂度Redis 部署相对简单Zookeeper 部署相对复杂
锁自动释放基于过期时间基于会话失效
应用场景高性能场景,适度容忍一致性问题严格一致性要求的场景

总结

Redlock 是一种简单高效的分布式锁实现方案,适用于大多数分布式系统场景。它通过在多个 Redis 实例上获取锁,提高了锁的可靠性,避免了单实例锁的缺陷。

  • 如果对性能要求较高,可以优先选择 Redlock;
  • 如果对一致性和可靠性有更高要求(如分布式事务场景),可以考虑基于 Zookeeper 的分布式锁。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com