news 2026/10/23 6:40:18

分布式锁的代码实现:从原理到实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分布式锁的代码实现:从原理到实战

1. 引言

在分布式系统中,多个服务实例可能同时操作共享资源,如果缺乏互斥机制,就会出现超卖、重复扣款、数据覆盖等问题。分布式锁正是为了解决这类跨进程、跨节点的并发竞争问题而设计的通用方案。本文围绕分布式锁的核心原理,给出基于 Redis 的完整代码实现,并讨论常见注意事项。

2. 核心原理

分布式锁的本质是让多个进程在共享存储上竞争一个「唯一标记」,谁拿到标记,谁就获得执行权。以 Redis 为例,最朴素的做法是利用SETNX命令:只有当 key 不存在时才能写入成功,写入成功的节点即获得锁。为了避免死锁,锁必须设置过期时间;为了避免误删他人锁,释放前要校验持有者标识。

3. 代码实现

下面给出一个基于 Redis 的分布式锁实现,使用 Java 语言和 Jedis 客户端,代码可直接复制运行。

import redis.clients.jedis.Jedis; import java.util.UUID; public class RedisLock { private Jedis jedis; private String lockKey; private String requestId; private int expireTime = 30000; // 锁自动过期时间,单位毫秒 public RedisLock(Jedis jedis, String lockKey) { this.jedis = jedis; this.lockKey = lockKey; this.requestId = UUID.randomUUID().toString(); } // 加锁:SETNX + 过期时间,保证原子性 public boolean tryLock() { String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime); return "OK".equals(result); } // 解锁:先校验持有者,再删除,防止误删他人锁 public void unlock() { String script = "if redis.call('get', KEYS[1]) == ARGV[1] " + "then return redis.call('del', KEYS[1]) " + "else return 0 end"; jedis.eval(script, 1, lockKey, requestId); } }

使用示例:

Jedis jedis = new Jedis("localhost", 6379); RedisLock lock = new RedisLock(jedis, "order:12345"); if (lock.tryLock()) { try { // 执行临界区业务逻辑 System.out.println("获取锁成功,执行业务"); } finally { lock.unlock(); } } else { System.out.println("获取锁失败,稍后重试"); }

4. 注意事项

第一,加锁和解锁必须保证原子性,避免「先 SETNX 再单独 EXPIRE」这种非原子写法。第二,释放锁前必须校验持有者标识,否则可能误删其他线程的锁。第三,业务执行时间不能超过锁的过期时间,否则锁提前失效会导致并发问题,必要时可引入看门狗续期机制。第四,在 Redis 主从架构下,主节点宕机可能导致锁丢失,对强一致性要求高的场景可考虑 Redlock 算法。

5. 总结

分布式锁是解决分布式并发竞争的基础组件。本文给出的 Redis 实现覆盖了加锁、解锁和防误删三个关键环节,代码简洁且可直接落地。实际生产环境中,建议优先使用 Redisson 等成熟客户端,它们内置了看门狗续期和 Redlock 支持,能进一步降低实现复杂度。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 6:39:40

Thread 类的基本用法

一.线程创建第一方式:创建子类继承Thread 重写run方法package Thread_star;public class Dome1 extends Thread {Overridepublic void run() {while (true){System.out.println("hello thread");try {Thread.sleep(1_000);} catch (InterruptedException …

作者头像 李华
网站建设 2026/10/23 6:38:34

全文 - 第01章 - 简介 - InfiniBand Specification release 1.4

「译注:本章适合浏览,不需要精读」 本文档是 InfiniBand 架构规范的第一卷。它是描述该架构的一系列文档中的第一份。 1.1 致谢 以下人员在 InfiniBand 架构规范本卷的编写过程中做出了重要贡献: 指导委员会成员 联合主席: 成员&a…

作者头像 李华
网站建设 2026/10/23 6:38:15

【译】今天我将审核 GitHub 拉取请求

今天我将向大家演示,在开发团队协作或者管理开源项目时,如何处理最常见的工作之一:拉取请求(Pull Request)。本次演示我们会使用 Visual Studio 内置的 GitHub 工具,不过这套操作思路在 Azure DevOps 中也大…

作者头像 李华
网站建设 2026/10/23 6:34:32

Spring Boot购物网站源码实战:下单事务、库存扣减与防超卖

简介:这套购物网站项目源码与数据库面向JavaWeb初学者、课程设计及毕业设计参考者,提供一套功能较完整的类淘宝电商实现,适合用作电商项目入门拆解样本,可帮助读者理解从商品浏览、搜索、购物车到下单、用户管理等业务流程如何落地…

作者头像 李华
网站建设 2026/10/23 6:34:27

圆瓶贴附路径离散:弦高、首段方向与分段数校核

壹星(YIXING)技术笔记|东莞市壹星自动化设备有限公司把圆瓶贴附路径画成若干直线段时,第一条弦并不与起点切线重合。段数太少会同时产生径向轮廓误差和首段方向误差,但这属于离散表示误差,不能直接解释真实…

作者头像 李华