Redis(75)Redis分布式锁的性能如何优化?

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

优化Redis分布式锁的性能可以从多个方面入手,包括减少锁的粒度、使用Lua脚本来确保原子操作、优化网络通信、提高Redis服务器的性能,以及优化锁的实现逻辑等。以下是一些常见的性能优化方法,并结合代码进行详细解释。

1. 减少锁的粒度

锁的粒度越小,竞争的机会就越少,从而提高系统的并发性能。比如,将全局锁拆分为多个局部锁。

1// 假设我们有多个资源需要加锁,可以为每个资源设置不同的锁
2public class FineGrainedRedisLock {
3    private Jedis jedis;
4    private String lockKeyPrefix;
5    private String lockValue;
6    private int expireTime;
7
8    public FineGrainedRedisLock(Jedis jedis, String lockKeyPrefix, int expireTime) {
9        this.jedis = jedis;
10        this.lockKeyPrefix = lockKeyPrefix;
11        this.expireTime = expireTime;
12        this.lockValue = String.valueOf(Thread.currentThread().getId());
13    }
14
15    public boolean acquireLock(String resourceId) {
16        String lockKey = lockKeyPrefix + resourceId;
17        SetParams params = new SetParams().nx().px(expireTime);
18        String result = jedis.set(lockKey, lockValue, params);
19        return "OK".equals(result);
20    }
21
22    public boolean releaseLock(String resourceId) {
23        String lockKey = lockKeyPrefix + resourceId;
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(String resourceId, Runnable task) {
31        if (acquireLock(resourceId)) {
32            try {
33                task.run();
34            } finally {
35                boolean released = releaseLock(resourceId);
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        FineGrainedRedisLock lock = new FineGrainedRedisLock(jedis, "resource_lock_", 10000);
48
49        lock.executeWithLock("resource1", () -> {
50            System.out.println("Executing task for resource1.");
51            try {
52                Thread.sleep(5000);
53            } catch (InterruptedException e) {
54                Thread.currentThread().interrupt();
55            }
56            System.out.println("Task for resource1 completed.");
57        });
58
59        lock.executeWithLock("resource2", () -> {
60            System.out.println("Executing task for resource2.");
61            try {
62                Thread.sleep(5000);
63            } catch (InterruptedException e) {
64                Thread.currentThread().interrupt();
65            }
66            System.out.println("Task for resource2 completed.");
67        });
68
69        jedis.close();
70    }
71}
72

2. 使用Lua脚本确保原子操作

Lua脚本可以确保多个Redis命令的原子性,避免竞争条件。

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

3. 优化网络通信

减少网络通信延迟,可以提高分布式锁的性能。可以考虑以下几点:

  • 使用连接池:避免频繁创建和销毁Redis连接。
  • 本地缓存锁状态:减少不必要的Redis调用。
1import redis.clients.jedis.JedisPool;
2import redis.clients.jedis.JedisPoolConfig;
3import redis.clients.jedis.Jedis;
4
5public class OptimizedRedisLock {
6    private static JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
7
8    private String lockKey;
9    private String lockValue;
10    private int expireTime;
11
12    public OptimizedRedisLock(String lockKey, int expireTime) {
13        this.lockKey = lockKey;
14        this.expireTime = expireTime;
15        this.lockValue = String.valueOf(Thread.currentThread().getId());
16    }
17
18    public boolean acquireLock() {
19        try (Jedis jedis = pool.getResource()) {
20            SetParams params = new SetParams().nx().px(expireTime);
21            String result = jedis.set(lockKey, lockValue, params);
22            return "OK".equals(result);
23        }
24    }
25
26    public boolean releaseLock() {
27        try (Jedis jedis = pool.getResource()) {
28            String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
29                               "return redis.call('del', KEYS[1]) else return 0 end";
30            Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
31            return result.equals(1L);
32        }
33    }
34
35    public void executeWithLock(Runnable task) {
36        if (acquireLock()) {
37            try {
38                task.run();
39            } finally {
40                boolean released = releaseLock();
41                if (!released) {
42                    System.out.println("Failed to release lock.");
43                }
44            }
45        } else {
46            System.out.println("Failed to acquire lock, try again later.");
47        }
48    }
49
50    public static void main(String[] args) {
51        OptimizedRedisLock lock = new OptimizedRedisLock("resource_lock", 10000);
52
53        lock.executeWithLock(() -> {
54            System.out.println("Executing critical section.");
55            try {
56                Thread.sleep(5000);
57            } catch (InterruptedException e) {
58                Thread.currentThread().interrupt();
59            }
60            System.out.println("Critical section completed.");
61        });
62
63        pool.close();
64    }
65}
66

4. 提高Redis服务器性能

优化Redis服务器配置,提高其性能:

  • 增加内存:确保Redis不会频繁进行内存交换。
  • 优化Redis配置:调整maxmemory-policymaxmemory-samples等参数。
  • 使用集群模式:在高并发场景下,使用Redis Cluster进行分片,提高Redis的吞吐量。
1# redis.conf 中的几个关键配置项
2
3# 设置最大内存使用
4maxmemory 4gb
5
6# 超过最大内存后的淘汰策略,使用LRU算法
7maxmemory-policy allkeys-lru
8
9# 调整采样次数,提高LRU算法的精度
10maxmemory-samples 5
11
12# 启用持久化
13appendonly yes
14appendfsync everysec
15

5. 优化锁的实现逻辑

对于适合的业务场景,可以通过减少锁的持有时间、提高锁的重试机制等来优化锁的实现逻辑。

1import redis.clients.jedis.Jedis;
2import redis.clients.jedis.params.SetParams;
3
4public class ImprovedRedisLock {
5    private Jedis jedis;
6    private String lockKey;
7    private String lockValue;
8    private int expireTime;
9    private int retryDelay;
10    private int maxRetries;
11
12    public ImprovedRedisLock(Jedis jedis, String lockKey, int expireTime, int retryDelay, int maxRetries) {
13        this.jedis = jedis;
14        this.lockKey = lockKey;
15        this.expireTime = expireTime;
16        this.retryDelay = retryDelay;
17        this.maxRetries = maxRetries;
18        this.lockValue = String.valueOf(Thread.currentThread().getId());
19    }
20
21    public boolean acquireLock() {
22        int retries = 0;
23        while (retries < maxRetries) {
24            SetParams params
25

Redis(75)Redis分布式锁的性能如何优化?》 是转载文章,点击查看原文


相关推荐


为什么 .gitignore 不生效?其实你忘了用 git rm --cached!
唐青枫2025/10/20

简介 命令格式: git rm --cached <file> 意思: 从 Git 的 索引(index,暂存区) 中移除文件,但保留工作区中的实际文件。 也就是说: 文件仍然留在硬盘(工作区); 但不再被 Git 跟踪(tracked)。 <file>...:要移除的文件或目录路径。可以指定多个文件,或使用通配符(如 *.log)。 常用选项: --cached:仅从索引移除(必须使用)。 -r 或 --recursive:递归移除目录及其内容(如果指定目录)。


【XR硬件系列】破局“芯”瓶颈:深入浅出解析XR专用芯片的必然性
元宇宙_H2025/10/18

关键词:XR芯片、低延迟、六自由度(6DoF)、异构计算、R1芯片、Motion-to-Photon、功耗、Qualcomm XR 引言:从“玩具”到“工具”的鸿沟 还记得早期的VR头显吗?厚重的机身、粗糙的画面,以及那令人不悦的眩晕感。这些体验上的“硬伤”,曾让XR技术长期徘徊在主流市场的边缘。其核心瓶颈之一,就在于当时的设备大多沿用手机等移动平台的通用芯片(SoC)。 这些“全能但不专精”的芯片,无法满足XR这一“性能吞噬兽”的苛刻需求。今天,我们就来深入探讨,为什么XR的进化之


Redis(66)Redis如何实现分布式锁?
Victor3562025/10/17

Redis 提供了多种方法来实现分布式锁,确保多个进程或机器能够协调地访问共享资源。以下是详细的实现步骤和代码示例。 1. 基于 SET 命令的分布式锁 获取锁 获取锁的核心是使用 SET 命令,并带上 NX 和 EX 选项: NX(Not eXists): 仅当键不存在时才设置键。 EX(EXpire): 设置键的过期时间,防止死锁。 # 获取锁示例 SET mylock <lock_value> NX EX 10 Lua 脚本实现 为了更加原子化,可以使用 Lua 脚本: -- 获取锁


告别异常继承树:从 NopException 的设计看“组合”模式如何重塑错误处理
canonical_entropy2025/10/16

在软件开发中,异常处理是一个不可或缺的环节。长久以来,经典的面向对象思想教导我们,为不同类型的错误建立一个庞大的继承树是一种优雅的方案。例如,定义一个基础的 AppException,然后派生出 BusinessException、SystemException 等。这种基于**继承(Inheritance)**的设计模式直观且经典。时至今日,这种思想在许多开发者心中依然根深蒂固,被认为是“正统”的 OO 设计。 然而,当系统走向分布式、服务化,并需要应对复杂的国际化、多租户、定制化需求时,这个


libevent输出缓存区的数据
我梦之62025/10/14

在网络开发中,当需要在不干扰客户端正常接收数据的前提下,验证服务端输出缓冲区中待发送数据的存在性、完整性或格式正确性(如排查客户端收不到数据的故障、确认发送数据是否符合协议规范),或监控缓冲区数据堆积情况时,会用到这段基于 libevent 库的代码。 其核心功能是对客户端连接的输出缓冲区(evbuffer)进行 “非破坏性读取”—— 先通过bufferevent_get_output获取与客户端client2关联的输出缓冲区指针,再用evbuffer_get_length获取缓冲区中待发送数据


设计模式-策略模式
紫菜紫薯紫甘蓝2025/10/13

设计模式-策略模式 策略模式,英文全称是 Strategy Design Pattern。它是这样定义的:Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. 翻译成中文就是:定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略


npm workspace 深度解析:与 pnpm workspace 和 Lerna 的全面对比
子兮曰2025/10/11

1. 前言:Monorepo 时代的到来 随着前端项目的复杂度不断提升,单体仓库(Monorepo)架构逐渐成为主流。Monorepo 允许我们在一个代码仓库中管理多个相关的包,带来了代码共享、统一依赖管理、简化 CI/CD 等诸多优势。然而,多包管理也带来了新的挑战:如何高效地管理跨包依赖、如何避免重复安装、如何简化构建流程等。 Workspace 解决方案应运而生,它为我们提供了一种优雅的方式来管理多包项目。目前主流的解决方案包括 npm workspace、pnpm workspace 和


面试真实经历某节跳动大厂Java和算法问答以及答案总结(一)
360_go_php2025/10/10

Java面试问题与解答 常见的GC回收器 - Serial GC: 适合单线程环境,暂停时间较长。 - Parallel GC: 多线程垃圾回收,适合多核处理器,停顿时间较短。 - CMS (Concurrent Mark-Sweep): 适合响应时间要求高的应用,通过多线程并发清除垃圾。 - G1 GC: 适用于大内存系统,目标是尽量减少GC停顿时间,分区回收。​编辑 SpringMVC的请求过程 - 流程: 用户发起请求 → 前端控制器(DispatcherServlet)接收请求


JAVA算法练习题day34
QiZhang6032025/10/8

43.验证二叉搜索树 要知道二叉搜索树的中序遍历结果是升序序列 # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution(o


v你真的会记笔记吗?AI的答案可能让你意外
万少 VIP.5 如鱼得水2025/10/7

这段时间我在准备一个行业调查,调研资料几乎全来自视频会议、线上讲座和播客。 内容是很丰富,但问题也随之而来:一个小时的视频回放,想找个观点得快进倒退十几次,遇到灵感还得赶紧切出去做笔记,效率低到崩溃。 看不完,根本看不完…… 正好我朋友是一个AI发烧友,他就推荐我用了一个专注做AI笔记的工具。 坦白讲,最开始我没抱太大期待,心想不就是转写嘛。但真用了两周后,我发现它完全改变了我的学习和工作流。 这个工具叫Ai好记: 网址:aihaoji.com/zh?utm_sour… 输入口令【万少】可以

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读