当前位置: 首页 > article >正文

分布式锁剖析

一、分布式锁

1. 为什么需要分布式锁?

在单体应用中,通过synchronized或ReentrantLock等进程内锁即可解决多线程资源竞争问题。但在分布式系统中,多个服务实例运行在不同进程中,传统进程内锁失效,此时需要一种跨进程的互斥机制 ——分布式锁,确保在分布式环境下对共享资源的互斥访问。

2. 分布式锁的核心功能

  • 互斥性:同一时刻只能有一个客户端获取锁
  • 可重入性:同一个客户端可多次获取同一把锁(需记录持有锁的客户端信息)
  • 容错性:锁服务需具备高可用性,避免单点故障
  • 锁超时:防止死锁,需设置合理的锁过期时间
  • 公平性(可选):保证锁获取顺序(适用于有严格顺序要求的场景)

3. 典型应用场景

  • 分布式缓存更新:避免多个节点同时更新缓存导致数据不一致
  • 分布式定时任务:确保同一任务只被一个节点执行
  • 分布式事务:作为分布式事务的协调机制之一
  • 库存扣减:保证高并发下库存的准确扣减

二、核心实现原理

1. 分布式锁的实现模型

所有分布式锁的实现本质上都基于分布式系统中的一致性协议,核心是解决以下问题:

  • 如何标识锁(唯一的资源标识符)
  • 如何实现互斥(原子性操作保证)
  • 如何处理锁超时(防止资源泄露)
  • 如何实现锁的释放(安全释放机制)

2. 关键技术点

原子性操作

需要依赖底层中间件提供的原子操作接口,例如:

  • Redis 的SETNX(Set If Not Exists)
  • ZooKeeper 的节点创建操作
  • 数据库的INSERT …

锁的持有标识

为避免误释放其他客户端的锁,获取锁时需生成唯一的客户端标识(如 UUID),释放锁时需验证标识一致性,而非直接删除锁。

锁续约机制

为防止业务执行时间超过锁过期时间,需实现锁的自动续约(如 Redisson 的看门狗机制),在锁过期前自动延长有效期。

等待队列

对于非公平锁,客户端获取锁失败后直接返回;对于公平锁,需实现等待队列(如 ZooKeeper 的有序节点队列)。

三、主流实现方案

方案一:基于 Redis 的分布式锁

1. 基础实现:SETNX + 过期时间

// 伪代码:基于Jedis实现
public boolean tryLock(String lockKey, String clientId, long expireTime) {// SETNX命令保证原子性,NX表示仅当key不存在时设置// EX设置过期时间,防止死锁String result = jedis.set(lockKey, clientId, "NX", "EX", expireTime);return "OK".equals(result);
}public boolean releaseLock(String lockKey, String clientId) {// 检查锁是否属于当前客户端,避免误释放String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";return jedis.eval(script, 1, lockKey, clientId).equals(1L);
}

2. 缺陷与优化

  • 竞争条件:锁过期与业务执行完成之间可能被其他客户端获取锁,需通过校验客户端标识 + Lua 脚本原子释放解决
  • 集群模式问题:主从模式下存在锁丢失风险(主节点未同步到从节点时宕机),需通过 RedLock 算法(多节点获取锁)提升可靠性
  • 推荐工具:Redisson 框架(实现了可重入锁、公平锁、锁续约等完整功能)

3. Redisson 分布式锁示例

// 引入依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.17.6</version>
</dependency>Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);RLock lock = redisson.getLock("resourceLock");
try {// 可重入锁,默认过期时间30秒(看门狗机制自动续约)lock.lock();// 执行业务逻辑
} finally {lock.unlock();
}

方案二:基于 ZooKeeper 的分布式锁

1. 实现原理

利用 ZooKeeper 的临时有序节点特性:

  • 客户端在/locks节点下创建临时顺序节点(如/locks/lock-)
  • 获取/locks下所有子节点,判断自己是否是最小序号的节点
  • 若是则获取锁,否则监听前一个节点的删除事件(Watcher 机制)
  • 释放锁时删除自己的节点,触发后续节点的监听事件

2. 核心优势

  • 高可用性:ZooKeeper 的集群选举机制保证锁服务的可用性
  • 公平性:有序节点天然支持公平锁
  • 自动释放:临时节点在客户端宕机后自动删除,避免死锁

3. Curator 框架实现示例

// 引入依赖
// <dependency>
//     <groupId>org.apache.curator</groupId>
//     <artifactId>curator-recipes</artifactId>
//     <version>5.3.0</version>
// </dependency>CuratorFramework client = CuratorFrameworkFactory.builder().connectString("zk1:2181,zk2:2181,zk3:2181").retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
client.start();InterProcessMutex lock = new InterProcessMutex(client, "/distributed_lock");
try {// 可重入锁,支持超时获取boolean acquired = lock.acquire(10, TimeUnit.SECONDS);if (acquired) {// 执行业务逻辑}
} catch (Exception e) {// 处理异常
} finally {try {lock.release();} catch (Exception e) {// 释放锁异常处理}
}

方案三:基于数据库的分布式锁

1. 实现方式一:表锁(悲观锁)

创建锁表distributed_lock:

CREATE TABLE distributed_lock (lock_key VARCHAR(64) PRIMARY KEY,client_id VARCHAR(64),expire_time BIGINT
);

获取锁:

INSERT INTO distributed_lock (lock_key, client_id, expire_time) 
VALUES ('resource_1', 'client_A', 1678901234) 

释放锁:

DELETE FROM distributed_lock 
WHERE lock_key='resource_1' AND client_id='client_A';

2. 实现方式二:乐观锁(版本号控制)

通过UPDATE … WHERE version = ?实现:

UPDATE resource_table 
SET status='locked', version=version+1 
WHERE resource_id=1 AND version=123;

3. 适用场景

  • 简单场景或遗留系统兼容
  • 不适合高并发场景(数据库成为瓶颈)

4. 缺陷

  • 性能问题:依赖数据库 IO,吞吐量有限
  • 锁超时处理:需额外的定时任务清理过期锁
  • 分布式事务问题:需结合数据库事务保证一致性

四、分布式锁最佳实践

1. 锁粒度控制

遵循最小锁粒度原则,避免长时间持有锁
例如:库存扣减时以商品ID为锁 Key,而非整个库存系统

2. 异常处理

  • 获取锁时设置超时时间,避免线程永久阻塞
  • 释放锁时必须校验客户端标识,防止误释放
  • 业务代码需捕获异常并确保锁释放(使用finally块)

3. 监控与报警

  • 监控锁的获取成功率、等待时间等指标
  • 对锁超时、锁竞争激烈的场景设置报警

4. 混合方案

对于金融等高可靠性场景,可结合 Redis 和 ZooKeeper 实现双锁机制,提升容错能力。

五、总结与发展趋势

分布式锁是分布式系统中解决资源竞争的核心组件,不同方案各有优劣:

  • Redis 方案凭借高性能和简单易用成为首选
  • ZooKeeper 方案在需要严格顺序和高可用性时更优
  • 数据库方案适用于轻量场景或兼容性需求

随着云原生技术的发展,基于 Kubernetes 的分布式锁(如利用 ETCD)和 Service Mesh 中的分布式锁实现正在成为新的研究方向。开发者需根据具体业务场景(并发量、可靠性要求、技术栈)选择合适的方案,并结合框架(如 Redisson、Curator)简化开发成本。


相关文章:

分布式锁剖析

一、分布式锁 1. 为什么需要分布式锁&#xff1f; 在单体应用中&#xff0c;通过synchronized或ReentrantLock等进程内锁即可解决多线程资源竞争问题。但在分布式系统中&#xff0c;多个服务实例运行在不同进程中&#xff0c;传统进程内锁失效&#xff0c;此时需要一种跨进程…...

C语言中函数指针和指针函数的定义及用法

在C/C中&#xff0c;函数指针和指针函数是两个容易混淆但完全不同的概念。以下是它们的详细对比和学习指南&#xff0c;结合代码示例帮助你彻底掌握。 1. 函数指针&#xff08;Function Pointer&#xff09; 本质&#xff1a;一个指向函数的指针变量&#xff0c;用于动态调用…...

Spring Boot DevTools 热部署

在Spring Boot项目中加入 spring-boot-devtools 热部署依赖启动器后&#xff0c;通常不需要手动重启项目即可让更改生效。spring-boot-devtools 的核心特性之一就是自动重启或热加载。 Spring Boot DevTools 热部署关键知识点 &#x1f525; 目的&#xff1a;spring-boot-devt…...

unix/linux source 命令,其基本属性、语法、操作、api

现在像解剖精密仪器一样,来细致地审视 source (或 .) 命令的各个方面:它的属性、语法、操作方式,以及可以称之为“API”的交互接口。这种细致的分析有助于我们精确地理解和使用它。 让我们深入细节: 一、基本属性 (Core Attributes) 命令类型 (Command Type): Shell 内置…...

FPGA仿真中阻塞赋值(=)和非阻塞赋值(<=)区别

FPGA仿真中阻塞赋值和非阻塞赋值的区别 单独仿真小模块对但将小模块加入整个工程仿真不对就有可能是没有注意到仿真中阻塞赋值和非阻塞赋值的区别 目录 前言 一、简介 二、设计实例 三、仿真实例 1、仿真用非阻塞赋值 2、仿真用阻塞赋值 总结 前言 网上很多人介绍verilo…...

LabVIEW轴角编码器自动检测

LabVIEW 开发轴角编码器自动检测系统&#xff0c;针对指控系统中高故障率的轴角编码器性能检测需求&#xff0c;通过模块化硬件架构与软件设计&#xff0c;实现编码器运转状态模拟、扭矩 / 转速实时监测、19 位并行编码采集译码、数据自动分析及报告生成等功能&#xff0c;解决…...

MySQL数据库从0到1

目录 数据库概述 基本命令 查询命令 函数 表的操作 增删改数据和表结构 约束 事务 索引 视图 触发器 存储过程和函数 三范式 数据库概述 SQL语句的分类&#xff1a; DQL&#xff1a;查询语句&#xff0c;凡是select语句都是DQL。 DML&#xff1a;insert,delete,up…...

WiFi万能钥匙鲲鹏服务器部署 TiDB 集群实战指南

作者&#xff1a; TiDBer_yangxi 原文来源&#xff1a; https://tidb.net/blog/15a234d0 一、环境准备 1. 硬件要求 服务器架构 &#xff1a;鲲鹏服务器&#xff08;ARM架构&#xff09;&#xff0c;TiDB 官方明确支持 ARM 架构服务器部署 推荐配置 &#xff08;生产环…...

正则表达式的前世今生

当你熟练地用正则表达式查找替换代码时&#xff0c;这个工具的历史可以追溯到1943年。那时候还没有计算机&#xff0c;更别说编程语言了。 从神经网络到文本匹配 故事要从两个神经生理学家说起。1943年&#xff0c;Warren McCulloch和Walter Pitts发表了一篇论文《A logical ca…...

Vue 核心技术与实战智慧商城项目Day08-10

温馨提示&#xff1a;这个黑马的视频在b占可以找到&#xff0c;里面有完整的教学过程 然后这个项目有完整的代码&#xff0c;我已经上传了&#xff0c;如果审核成功大家就可以看了&#xff0c;但是需要审核多久我也不是很确定 1.项目演示 2. 项目收获 3. 创建项目 4. 调整初始化…...

TCP/IP协议精华总结pdf分享

hi &#xff0c;大家好&#xff0c;应小伙伴们的要求&#xff0c;上次分享了个人的一些学习和职场经验&#xff0c;其中网络协议PDF文档是我之前学习协议的时候总结一些精华知识&#xff0c;网络属于基本功&#xff0c;是互联网必备知识&#xff0c;我深信掌握好核心20%知识&am…...

组件化:软件工程化的基础

在现代软件系统中&#xff0c;**组件化&#xff08;Componentization&#xff09;**不仅是一种设计技术&#xff0c;更是推动软件工程走向工业化、体系化的关键基础。随着业务复杂度、团队规模与生命周期成本的持续上升&#xff0c;软件开发从“写代码”演变为“构建系统”。而…...

⚡️ Linux grep 命令参数详解

⚡️ Linux grep 用法及参数详解 &#x1f4d8; 1. grep 简介 grep 是 Linux/Unix 系统中用于文本搜索的命令&#xff0c;其全称为 Global Regular Expression Print&#xff0c;意为全局正则表达式打印器。 它根据给定的 模式&#xff08;pattern&#xff09; 对文件或标准…...

2025年第三届CCF·夜莺开源创新论坛通知

点击蓝字 关注我们 CCF Opensource Development Committee 01 大会简介 由中国计算机学会主办、CCF开源发展委员会及夜莺开源社区承办的第三届CCF夜莺开源创新论坛拟于2025年7月4日在北京召开。本次论坛以“AI 加速可观测”为主题&#xff0c;汇聚了开源夜莺核心开发团队&#…...

GMDCMonitor企业版功能分享0602

企业版包含了拓扑中心、签退中心、知识库、通知渠道配置、平台自定义&#xff0c;这5个功能 1&#xff09;拓扑中心 拓扑中心绘制的时候需要注意2点&#xff1a; 1&#xff09;要先选择 “矩形区域” 或 “圆形区域” 来添加各个背景区域&#xff0c;同时录入区域尺寸&#x…...

automa

网页版插件 https://extension.automa.site/(可能插件下架了&#xff09; https://github.com/AutomaApp/automa/releases/tag/v1.29.9&#xff08;可以直接在git上下载&#xff09; automa官网地址&#xff1a; https://www.automa.site/ 官方的文档 https://docs.automa.si…...

Warm-Flow发布1.7.3 端午节(设计器流和流程图大升级)

Warm-Flow发布1.7.3 端午节&#xff08;设计器流和流程图大升级&#xff09; 更新内容项目介绍功能思维导图演示地址官网Warm-Flow视频 更新内容 [feat] 新版流程图通过前端渲染[perf] 美化流程设计器ui[feat] 办理人权限处理器&#xff0c;新增办理人转换接口&#xff0c;比如…...

【存储基础】SAN存储基础知识

文章目录 1. 什么是SAN存储&#xff1f;2. SAN存储组网架构3. SAN存储的主要协议SCSI光纤通道&#xff08;FC&#xff09;协议iSCSIFCoENVMe-oFIB 4. SAN存储的关键技术Thin Provision&#xff1a;LUN空间按需分配Tier&#xff1a;分级存储Cache&#xff1a;缓存机制QoS&#x…...

2025年ESWA SCI1区TOP,改进成吉思汗鲨鱼算法MGKSO+肝癌疾病预测,深度解析+性能实测

1.摘要 本文针对肝癌&#xff08;HCC&#xff09;早期诊断难题&#xff0c;提出了一种基于改进成吉思汗鲨鱼优化算法&#xff08;MGKSO&#xff09;的计算机辅助诊断系统。由于HCC在早期症状不明显且涉及高维复杂数据&#xff0c;传统机器学习方法易受噪声和冗余特征干扰。为提…...

精益数据分析(93/126):增长率的真相——从数据基准到科学增长策略

精益数据分析&#xff08;93/126&#xff09;&#xff1a;增长率的真相——从数据基准到科学增长策略 在创业领域&#xff0c;增长率常被视为企业成功的核心指标&#xff0c;但多少才算“足够好”&#xff1f;如何避免陷入“盲目增长陷阱”&#xff1f;今天&#xff0c;我们将…...

MAC上怎么进入隐藏目录

在Mac上&#xff0c;由于系统保护的原因&#xff0c;一些系统目录如/usr默认是隐藏的&#xff0c;但可以通过以下方法进入&#xff1a; 方法一&#xff1a;使用Finder的“前往文件夹”功能 打开Finder。使用快捷键Command Shift G&#xff0c;或者在菜单栏中选择“前往”-“…...

Spark-TTS: AI语音合成的“变声大师“

嘿&#xff0c;各位AI爱好者&#xff01;还记得那些机器人般毫无感情的合成语音吗&#xff1f;或者那些只能完全模仿但无法创造的语音克隆&#xff1f;今天我要介绍的Spark-TTS模型&#xff0c;可能会让这些问题成为历史。想象一下&#xff0c;你可以让AI不仅说出任何文字&…...

【Python 进阶3】常见的 call 和 forward 区别

在 Python 和深度学习框架&#xff08;如 PyTorch&#xff09;中&#xff0c;__call__ 和 forward 是两个不同的概念&#xff0c;它们的用途和实现方式有明显区别&#xff1a; 1. __call__ 方法&#xff08;Python 内置特殊方法&#xff09; 在 Python 中&#xff0c;__call_…...

WEB3——简易NFT铸造平台之nft.storage

该平台目前已经不太支持免费试用&#xff0c;现在推荐Pinata平台&#xff0c;免费用1GB Pinata | Cryptos file storage 下面web3.storage也可以用&#xff0c;但是需要你有可以交易的外币卡 w3up console &#x1f9e0; 1. nft.storage 是什么&#xff1f; https://nft.stor…...

一元函数积分

1. 不同名函数积分 2.三角函数有理式...

6年“豹变”,vivo S30系列引领手机进入场景“体验定义”时代

出品 | 何玺 排版 | 叶媛 5月29日晚&#xff0c;备受用户期待的vivo S30系列如约而至。 相比前几代S系列产品&#xff0c;S30系列变化显著&#xff0c;堪称“豹变”。首先&#xff0c;其产品打造思路发生了质变&#xff0c;产品体验更好&#xff0c;综合竞争力更为强。其次&a…...

Pytorch的梯度控制

在之前的实验中遇到一些问题&#xff0c;因为之前计算资源有限&#xff0c;我就想着微调其中一部分参数做&#xff0c;于是我误打误撞使用了with torch.no_grad&#xff0c;可是发现梯度传递不了&#xff0c;于是写下此文来记录梯度控制的两个方法与区别。 在PyTorch中&#x…...

linux驱动开发(1)-内核模块

内核模块 模块最大的好处是可以动态扩展应用程序的功能而无须重新编译链接生成新的应用程序镜像&#xff0c;在微软的Windows系统上动态链接库DLL&#xff08;Dynamic Link Library&#xff09;&#xff0c;Linux系统上的共享库so&#xff08;shared object&#xff09;文件的…...

AI产品风向标:从「工具属性」到「认知引擎」的架构跃迁​

近年来&#xff0c;人工智能正在改变法律行业的游戏规则。从最初的“工具属性”——帮律师干些重复的杂活儿&#xff0c;到如今逐渐变身为“认知引擎”——能够理解法律逻辑、分析案例&#xff0c;法律AI产品正在迎来一场华丽的转身。这篇文章将带你一探究竟&#xff0c;看看这…...

前端八股之CSS

CSS 盒子模型深度解析与实战 一、盒子模型核心概念 Box-sizing CSS 中的 box-sizing 属性定义了引擎应该如何计算一个元素的总宽度和总高度 语法&#xff1a; box-sizing: content-box|border-box|inherit:content-box 默认值&#xff0c;元素的 width/height 不包含paddi…...