Redis(74)Redis分布式锁与ZooKeeper分布式锁有何区别?

作者:Victor356日期:2025/10/21

Redis和ZooKeeper都是用来实现分布式锁的常用工具,但它们在实现机制、性能、可用性和一致性方面有显著区别。以下是详细的比较和结合代码的解释。

1. 实现机制

Redis分布式锁:

  • 实现机制:基于简单的字符串操作,通过SET NX PX命令来实现锁,使用Lua脚本确保原子性。Redis是一个内存数据库,操作速度非常快。
  • 一致性:Redis提供的是最终一致性,不能完全保证严格的强一致性。
  • 可用性:Redis是AP系统(高可用性和分区容错性),可能在网络分区时提供较高的可用性,但在一致性方面有所妥协。

ZooKeeper分布式锁:

  • 实现机制:基于ZNode(ZooKeeper节点)来实现锁,通过创建临时顺序节点来竞争锁。ZooKeeper依赖于ZAB协议(ZooKeeper Atomic Broadcast),确保严格的一致性。
  • 一致性:ZooKeeper提供的是强一致性,保证严格的顺序一致性。
  • 可用性:ZooKeeper是CP系统(强一致性和分区容错性),在网络分区时可能会牺牲部分可用性来保证一致性。

2. 性能

  • Redis:由于是内存数据库,操作非常快,适合高性能、高并发的场景。
  • ZooKeeper:性能较Redis稍逊,但在一致性和可靠性方面更强,适合需要严格一致性的场景。

3. 可用性和一致性

  • Redis:在网络分区时可能会牺牲一致性来保证可用性,属于AP系统。
  • ZooKeeper:在网络分区时可能会不可用来保证一致性,属于CP系统。

4. 示例代码

Redis分布式锁代码示例

1import redis.clients.jedis.Jedis;
2import redis.clients.jedis.params.SetParams;
3
4public class RedisDistributedLock {
5    private Jedis jedis;
6    private String lockKey;
7    private String lockValue;
8    private int expireTime;
9
10    public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
11        this.jedis = jedis;
12        this.lockKey = lockKey;
13        this.expireTime = expireTime;
14        this.lockValue = String.valueOf(Thread.currentThread().getId());
15    }
16
17    public boolean acquireLock() {
18        SetParams params = new SetParams().nx().px(expireTime);
19        String result = jedis.set(lockKey, lockValue, params);
20        return "OK".equals(result);
21    }
22
23    public boolean releaseLock() {
24        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
25                           "return redis.call('del', KEYS[1]) else return 0 end";
26        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
27        return result.equals(1L);
28    }
29
30    public void executeWithLock(Runnable task) {
31        if (acquireLock()) {
32            try {
33                task.run();
34            } finally {
35                boolean released = releaseLock();
36                if (!released) {
37                    System.out.println("Failed to release lock.");
38                }
39            }
40        } else {
41            System.out.println("Failed to acquire lock, try again later.");
42        }
43    }
44
45    public static void main(String[] args) {
46        Jedis jedis = new Jedis("localhost", 6379);
47        RedisDistributedLock lock = new RedisDistributedLock(jedis, "resource_lock", 10000);
48
49        lock.executeWithLock(() -> {
50            System.out.println("Executing critical section.");
51            // Simulate long running task
52            try {
53                Thread.sleep(8000);
54            } catch (InterruptedException e) {
55                Thread.currentThread().interrupt();
56            }
57            System.out.println("Critical section completed.");
58        });
59
60        jedis.close();
61    }
62}
63

ZooKeeper分布式锁代码示例

1import org.apache.zookeeper.*;
2import org.apache.zookeeper.data.Stat;
3
4import java.io.IOException;
5
6public class ZookeeperDistributedLock implements Watcher {
7    private ZooKeeper zooKeeper;
8    private String lockName;
9    private String lockPath;
10    private String currentLockNode;
11
12    public ZookeeperDistributedLock(String hostPort, String lockName) throws IOException {
13        this.zooKeeper = new ZooKeeper(hostPort, 3000, this);
14        this.lockName = lockName;
15        this.lockPath = "/locks/" + lockName;
16        try {
17            Stat stat = zooKeeper.exists("/locks", false);
18            if (stat == null) {
19                zooKeeper.create("/locks", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
20            }
21        } catch (KeeperException | InterruptedException e) {
22            e.printStackTrace();
23        }
24    }
25
26    public boolean acquireLock() {
27        try {
28            currentLockNode = zooKeeper.create(lockPath + "/lock_", new byte[0],
29                    ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
30            while (true) {
31                Stat predecessorStat = null;
32                String predecessorPath = null;
33                for (String node : zooKeeper.getChildren(lockPath, false)) {
34                    String fullPath = lockPath + "/" + node;
35                    if (currentLockNode.compareTo(fullPath) > 0) {
36                        if (predecessorStat == null || fullPath.compareTo(predecessorPath) > 0) {
37                            predecessorStat = zooKeeper.exists(fullPath, true);
38                            predecessorPath = fullPath;
39                        }
40                    }
41                }
42                if (predecessorStat == null) {
43                    return true;
44                }
45                synchronized (this) {
46                    wait();
47                }
48            }
49        } catch (KeeperException | InterruptedException e) {
50            e.printStackTrace();
51            return false;
52        }
53    }
54
55    public boolean releaseLock() {
56        try {
57            zooKeeper.delete(currentLockNode, -1);
58            return true;
59        } catch (KeeperException | InterruptedException e) {
60            e.printStackTrace();
61            return false;
62        }
63    }
64
65    public void executeWithLock(Runnable task) {
66        if (acquireLock()) {
67            try {
68                task.run();
69            } finally {
70                boolean released = releaseLock();
71                if (!released) {
72                    System.out.println("Failed to release lock.");
73                }
74            }
75        } else {
76            System.out.println("Failed to acquire lock, try again later.");
77        }
78    }
79
80    @Override
81    public void process(WatchedEvent event) {
82        if (event.getType() == Event.EventType.NodeDeleted) {
83            synchronized (this) {
84                notifyAll();
85            }
86        }
87    }
88
89    public static void main(String[] args) throws IOException {
90        ZookeeperDistributedLock lock = new ZookeeperDistributedLock("localhost:2181", "resource_lock");
91
92        lock.executeWithLock(() -> {
93            System.out.println("Executing critical section.");
94            // Simulate long running task
95            try {
96                Thread.sleep(8000);
97            } catch (InterruptedException e) {
98                Thread.currentThread().interrupt();
99            }
100            System.out.println("Critical section completed.");
101        });
102    }
103}
104

代码详解

Redis分布式锁代码详解

  1. 锁的获取与释放
    • acquireLock()方法使用NXPX参数设置锁的唯一性和过期时间,确保锁的原子性和自动过期。
    • releaseLock()方法使用Lua脚本确保释放锁的原子性,避免误删其他线程持有的锁。
  2. 执行带锁的任务
    • executeWithLock(Runnable task)方法封装了锁的获取、任务执行和锁的释放逻辑,确保任务在锁的保护下执行。

ZooKeeper分布式锁代码详解

  1. 锁的获取与释放
    • acquireLock()方法通过创建临时顺序节点来竞争锁,并监听前一个节点的删除事件来确保锁的公平性。
    • releaseLock()方法删除当前的临时顺序节点,释放锁。
  2. 执行带锁的任务
    • executeWithLock(Runnable task)方法封装了锁的获取、任务执行和锁的释放逻辑,确保任务在锁的保护下执行。
  3. 事件处理
    • process(WatchedEvent event)方法处理节点删除事件,确保在前一个节点释放锁后,当前节点能及时获取锁。

总结来说,Redis和ZooKeeper都有各自的优势和适用场景。Redis适合高性能、高并发的场景,ZooKeeper适合需要严格一致性的场景。选择哪一种锁机制,主要取决于具体的应用需求和系统架构。


Redis(74)Redis分布式锁与ZooKeeper分布式锁有何区别?》 是转载文章,点击查看原文


相关推荐


Qt的QT_QPA_EGLFS_INTEGRATION环境变量浅解
华丽的周遭2025/10/20

在Qt嵌入式开发中,环境变量QT_QPA_EGLFS_INTEGRATION用于控制 ​​EGLFS(Embedded GL Framework for Systems)平台插件​​ 与底层显示子系统的集成方式。 它主要适用于基于OpenGL ES的无头(Headless)或嵌入式设备场景(如无X11/Wayland的嵌入式Linux系统),尤其在ZynqMP这类SoC方案中,常用于配置Qt应用的图形渲染与显示输出。 ​​一、核心作用​​ EGLFS是Qt提供的轻量级平台插件,直接通过EG


【粉丝福利社】从算筹到卫星导航:这本书藏着人类文明的进化密码
愚公搬代码2025/10/18

💎【行业认证·权威头衔】 ✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家 ✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主 ✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者 🏆【荣誉殿堂】 🎖 连续三年蝉联"华为云十佳博主"(2022-2024) 🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023) 🎖 十余个技术社区年度杰出贡献奖得主 📚【知识宝库】 覆盖


Git提交后追加修改操作指南
字节逆旅2025/10/17

在开发时经常会遇到在git commit后,又把文件修改了一下的情况,此时要如何操作才能避免提交多个commit呢? 前面你已经走了这两步: git add . git commit -m "fix:修改了一个bug" 此时你提交的代码还在本地暂存区,然后你又发现没改完,又有新修改文件产生。 接下来,你的操作步骤应该是这样的: 基本步骤 将修改的文件添加到暂存区(Staging Area) 这里还是和你平时提交前一样,使用 git add 命令。 # 添加某个特定文件 git add <


前端必备:JS数组与对象完全指南,看完秒变数据处理高手!
良山有风来2025/10/16

一、为什么你的代码总是处理不好数据? 你是不是经常遇到这样的场景: 从后端拿到一堆数据,却不知道如何快速筛选出需要的内容 想要对数据进行排序、过滤、转换,却写出一堆复杂的for循环 面对嵌套的对象结构,感觉像是在走迷宫,总是找不到想要的数据 别担心,这都不是你的问题!很多前端开发者都在数据处理上栽过跟头。今天这篇文章,就带你彻底掌握JavaScript中最核心的两种数据结构:数组和对象。 读完本文,你将获得: 数组和对象的完整操作方法大全 实际开发中最常用的数据处理技巧 避免常见坑点的最佳


云原生-k8s
dalianwawatou2025/10/14

k8s的优缺点 优点:部署应用方便,具有高可用、负载均衡功能,能自动扩容、对Pod进行监控 缺点:需要很多机器,成本投入大 安装 服务器准备 首先安装三台虚拟机,一台主节点,两台从节点,规划如下 操作系统:Rocky_linux9.6 配置: 4核cpu +/8Gib 内存/20G磁盘 网卡模式:NAT 角色IP主机名主节点master192.168.52.131k8s1从节点node1192.168.52.132k8s2从节点node2192.168.52.133k8s3


HTTPS 真的牢不可破吗?—— 中间人攻击与安全机制解析
程序员三明治2025/10/13

👨‍💻程序员三明治:个人主页 🔥 个人专栏: 《设计模式精解》 《重学数据结构》 🤞先做到 再看见! 在实际应用中,我们可能会遇到这样的情况:当客户端通过浏览器向服务端发起 HTTPS 请求时,请求被“假基站”劫持并转发至“中间人服务器”。于是,客户端实际上是与中间人完成了 TLS 握手,而中间人再与真正的服务端建立 TLS 连接。具体流程如下: 具体过程如下: 客户端发起 HTTPS 连接请求,被假基站重定向至中间人服务器。中间人随后向真实服务端发起 H


苦练Python第62天:零基础玩转CSV文件读写,csv模块实战​
倔强青铜三 VIP.1 初学乍练2025/10/11

前言 大家好,我是倔强青铜三。欢迎关注我,微信公众号:倔强青铜三。点赞、收藏、关注,一键三连! 欢迎来到苦练Python第62天! 今天我们来学习Python标准库中的csv模块。 一、CSV 是什么?能做什么? CSV(Comma-Separated Values,逗号分隔值)是一种纯文本表格格式。 每行是一条记录(record),行内每个字段(field)用分隔符(通常是逗号)隔开。 结构简单、体积小、兼容性强,几乎所有电子表格、数据库、数据分析工具都支持。 常见场景 Excel /


某大厂跳动面试:计算机网络相关问题解析与总结
360_go_php2025/10/10

​ 在参加像字节跳动这样的互联网公司面试时,计算机网络的知识是一个常见的考察点。以下是一些常见的计算机网络面试问题和详细解答,在面试中打下坚实的基础。 1. HTTPS通信过程 HTTPS (HyperText Transfer Protocol Secure) 是一种安全的 HTTP 协议,通过 TLS/SSL 加密实现数据的保密性和完整性。HTTPS 的通信过程包括以下几个步骤:​编辑 客户端发起连接:客户端向服务器发送请求,使用 HTTPS 协议。 服务器响应:服务器返回其 SSL/T


CentOS安装Jenkins
何中应2025/10/8

说明:之前介绍过用 Docker 的方式部署 Jenkins,本文介绍通过安装包的方式部署最新版的 Jenkins 在云服务器上安装Jenkins 第一步:准备工作 安装 Jenkins 的前提,是需要服务器有 JDK、Maven 和 Git 环境,如下: 这几个环境,参看上面的文章进行安装,最新版的 Jenkins 需要 JDK17 或 JDK21,Maven 最好装 3+ 第二步:安装启动 找一个合适的目录,下载 Jenkins 安装包 wget https://mirro


Vue 组件与插件的区别详解
excel2025/10/7

在 Vue 的开发体系中,“组件 (Component)” 与 “插件 (Plugin)” 是两个经常被提及的概念。它们都能提升开发效率与系统可维护性,但用途与设计目标截然不同。本文将通过定义、作用、实现方式与使用场景等方面,对两者进行系统梳理与对比。 一、组件是什么? 1. 定义回顾 组件是一种将图形或非图形的逻辑抽象为独立单元的开发模式。在 Vue 中,每一个 .vue 文件都可以被视为一个组件。 简单来说,组件就是一个具有独立逻辑与界面的可复用模块。 2. 组件的优势 降低系统耦合度

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0