悲观锁,乐观锁和redis分布式锁

news/2025/9/26 0:53:29/文章来源:https://www.cnblogs.com/youantianqin/p/19112386

​​悲观锁(Pessimistic Lock)​​

​​为什么叫 "悲观"?​​

因为它 ​​"悲观" 地认为并发操作一定会发生冲突​​,所以在操作数据之前,​​先加锁​​,确保其他事务无法修改这条数据,直到当前事务完成。

​​实现方式​​(数据库层面):

  • SELECT ... FOR UPDATE(MySQL)

  • SELECT ... WITH (UPDLOCK)(SQL Server)

  • 其他数据库的排他锁机制

​​特点​​:

  • ​​先锁再操作​​,防止并发修改

  • ​​适用于高并发写操作​​(如抢购、库存扣减)

  • ​​可能降低并发性能​​(锁会阻塞其他事务)

​​示例​​(ThinkPHP):

 
Db::startTrans(); // 开启事务 $info = $this->where(['id' => $id])->lock(true)->find(); // 加悲观锁 // ... 处理数据 ... Db::commit(); // 提交事务(释放锁)
 
 

​​乐观锁(Optimistic Lock)​​

​​为什么叫 "乐观"?​​

因为它 ​​"乐观" 地认为并发操作不会冲突​​,所以 ​​不加锁​​,而是在更新时检查数据是否被修改过(通常用版本号或时间戳)。

​​实现方式​​:

  • ​​版本号机制​​(version字段)

  • ​​时间戳机制​​(update_time字段)

  • ​​CAS(Compare-And-Swap)​​(如 Redis)

​​特点​​:

  • ​​不加锁,先操作再检查冲突​​

  • ​​适用于读多写少的场景​​

  • ​​冲突时需要重试或回滚​​

​​示例​​(ThinkPHP):

 
// 假设数据表有 `version` 字段 $data = $this->where(['id' => $id])->find(); $newData = ['name' => 'new_name', 'version' => $data['version'] + 1]; $result = $this->where(['id' => $id, 'version' => $data['version']])->save($newData); if (!$result) { // 更新失败,说明数据被其他人修改过,可以重试或报错 }
 
 

​​对比总结​​

特性

悲观锁(Pessimistic Lock)

乐观锁(Optimistic Lock)

​​加锁方式​​

先加锁再操作(FOR UPDATE

不加锁,更新时检查冲突

​​适用场景​​

高并发写操作(如抢购)

读多写少(如文章编辑)

​​性能影响​​

可能降低并发性能(锁阻塞)

无锁,冲突时才处理

​​实现方式​​

数据库锁机制

版本号、时间戳、CAS

​​冲突处理​​

其他事务会被阻塞

需要重试或回滚

​​如何选择?​​

  • ​​悲观锁​​:数据竞争激烈,必须保证数据一致性(如支付、库存扣减)。

  • ​​乐观锁​​:冲突概率低,希望提高并发性能(如文章编辑、评论更新)。

 

redis分布式锁:

这段代码的作用是 ​​使用 Redis 的 SETNX(SET if Not eXists)实现分布式锁​​,防止并发重复提交(如重复提现)。具体解析如下:


​​代码解析​​

 
if (!setLockNx($withdrawLockKey, 30)) { //提现锁,处理完手动解锁 json_exit_Base64(401, lang("处理中,请勿重复点击")); }
 
 
  1. ​​setLockNx($withdrawLockKey, 30)​​

    • 调用一个自定义函数(可能是封装了 Redis 的 SETNX命令)。

    • ​​$withdrawLockKey​​:锁的唯一标识(如用户ID + 业务类型,例如 withdraw:user123)。

    • ​​30​​:锁的自动过期时间(单位:秒),防止锁未释放导致死锁。

  2. ​​!setLockNx(...)​​

    • 如果获取锁失败(返回 false),说明锁已存在(即当前有其他请求正在处理相同业务)。

    • 直接返回错误提示,阻止重复操作。

  3. ​​json_exit_Base64(401, ...)​​

    • 返回 HTTP 401 状态码和 Base64 编码的 JSON 错误消息(可能是项目约定的通信格式)。

    • 提示用户:"处理中,请勿重复点击"。

  4. ​​注释说明​​

    • //提现锁,处理完手动解锁:提示开发者需要在业务逻辑完成后 ​​手动释放锁​​(如调用 delLock($withdrawLockKey)),否则锁会在 30 秒后自动过期。


​​实现原理(Redis 分布式锁)​​

  1. ​​加锁​​

    通过 Redis 的 SETNX命令实现原子性锁:

     
    SETNX $withdrawLockKey 1 # 如果 key 不存在则设置成功(返回1),否则失败(返回0) EXPIRE $withdrawLockKey 30 # 设置过期时间,避免程序崩溃导致死锁
     
     

    (注:高版本 Redis 支持 SET $withdrawLockKey 1 NX EX 30一步完成)

  2. ​​解锁​​

    业务处理完成后需手动删除 key:

     
    DEL $withdrawLockKey
     
     

​​适用场景​​

  • ​​提现/支付防重​​:防止用户多次点击导致重复扣款。

  • ​​秒杀/库存扣减​​:避免超卖问题。

  • ​​任何需要分布式环境下的互斥操作​​(如定时任务防并发执行)。


​​注意事项​​

  1. ​​锁的粒度​​

    • 锁的 key 需要足够具体(例如包含用户ID),避免不同用户互相阻塞。

  2. ​​锁的过期时间​​

    • 过期时间(如30秒)需大于业务处理时间,但不宜过长(否则阻塞其他请求)。

  3. ​​原子性问题​​

    • 确保 SETNX + EXPIRE是原子操作(如用 Redis 2.6.12+ 的 SET命令带 NX和 EX参数)。

  4. ​​手动解锁​​

    • 如果业务逻辑异常退出,需在 finally块中释放锁,或依赖自动过期。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/917740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

US$66.5 Yanhua ACDP FEM/BDC Bench Integrated Interface Board

Yanhua ACDP FEM/BDC Bench Integrated Interface BoardFeature:Simple operation. Avoid wrong plug and connection.Plug to use it directly. Safe and reliable connection!Package List:1pc x Yanhua ACDP FEM/BD…

辽宁建设厅投诉网站开通小程序流程

设备数据通过Azure Functions 推送到 Power BI 数据大屏进行展示(1.准备工作) 原创 Sean Yu 云计算实战 2019-12-06 本案例适用于开发者入门理解Azure Functions/ IoT Hub / Service Bus / Power BI等几款产品。 主要实战的内容为: 将设备遥…

sql练习笔记

记得练习(sql) SELECT Selectid fromtable whereadditional ORDER BY id2025-09-25 1.可回收且低脂的产品(1757) 无特点 2.寻找用户推荐人(584) 判空使用 IS NULL 3.大的国家 (595) 查询多个属性:name, populat…

算法练习

记得练习(algorthim) 2025-09-25 统计理想数组的数目(2338) 思路: 组合数学 - 隔板法

自己建网站网站视觉

Redis 中所有的键的类型都是字符串类型,⼀个字符串的最⼤值不能超过 512 MB。 由于 Redis 内部存储字符串完全是按照⼆进制流的形式保存的,所以 Redis 是不处理字符集编码问题的,客⼾端传⼊的命令中使⽤的是什么字符集编码,就存储…

微山网站建设自己做的网站怎么样把里面的内容下载下来

1.服务器 简单理解:服务器也是一台计算机,只是比平时用到的计算机在性能上更强大,开发中通常都需要将开发好的项目部署到服务器进行访问,例如:我们可以访问百度、淘宝、京东等,都是因为有服务器的存在&…

US$33.25 YANHUA ACDP N20/N13 Integrated Interface Board

YANHUA ACDP N20/N13 Integrated Interface BoardDME Intergrated Interface BoardFeatures: Simple operation. Plus to use it directly. Safe and reliable connetion!Package List:1pc x YANHUA ACDP N20/N13 Inte…

【System Beats!】第三章 程序的机器级表示

3.1 历史观点 处理器的发展历史Intel处理器俗称x86,它利用进步的技术满足更高性能和支持更高级操作系统的需求。 每个后继处理器的设计都是后向兼容的,较早版本上编译的代码可以在较新的处理器上运行。 这些年来,许…

苍穹外卖-day06(HttpClient) - a

苍穹外卖-day06(HttpClient) 课程内容HttpClient1. HttpClient 1.1 介绍 HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 H…

企业网站站内优化宁津有培训做网站的

函数的嵌套函数也是可以嵌套的。也就是可以在一个函数内部定义和运行另一个函数。举个例子:>>> def funa():print(funa()正在被调用)def funb():print(funb()正在被调用)funb()>>> funa()funa()正在被调用funb()正在被调用在上述举例中&#xff0…

元人文AI的领域化部署:从哲学构想到实践应用的完整路径

元人文AI的领域化部署:从哲学构想到实践应用的完整路径 一、引言:元人文AI的领域化转向 随着人工智能技术的持续演进,特别是大模型能力的快速提升,AI系统已经从单纯的工具转变为具有一定价值判断能力的智能体。在这…

10G网站空间回龙观手机网站建设服务

包含(后代)选择器 包含选择器,即加入空格,用于选择指定标签元素下的后辈元素。如右侧代码编辑器中的代码: .first span{color:red;} 这行代码会使第一段文字内容中的“胆小如鼠”字体颜色变为红色。 请注意这个选择器与子选择器的区别,子…

Python 虚拟环境管理-学习笔记分享

Python 虚拟环境管理-学习笔记分享python 虚拟环境管理参考文献 虚拟环境:你肯定用过,但不一定了解.hucci 从pip到uv:一口气梳理现代Python项目管理全流程! 【uv】Python迄今最好的项目管理+环境管理工具(吧?) …

做题记录3

CF2149E. Hidden Knowledge of the Ancients 思路 滑动窗口 + 双指针。 先不考虑长度的限制,求"恰好有 \(k\) 个不同的数"的区间。可以维护两个窗口,一个是以当前的位置为右端点,且第一个最多有 \(k\) 个…

网站建设咨询有客诚信wordpress手机全部显示

在Shiro中我们可以通过org.apache.shiro.session.mgt.eis.SessionDAO对象的getActiveSessions()方法方便的获取到当前所有有效的Session对象。通过这些Session对象,我们可以实现一些比较有趣的功能,比如查看当前系统的在线人数,查看这些在线用…

寻求网站建设技术怀柔网站建设优化seo

根据Github Trendings的统计,今日(2024-03-13统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目2Python项目2非开发语言项目2HTML项目1CSS项目1Dart项目1TypeScript项目1Go项目1JavaScript项目1《Hello 算法》:动画图解、一键运行的…

oucaiclub_cheapter1

Part1 代码练习 螺旋分类实验过程 初始准备生成样本线性模型分类神经网络分类反思总结 问题与解决 首次尝试中,在进行神经网络分类时,损失和准确率的结果与线性模型基本一样,没有明显改善。检查错误后,发现在设置优…

2025年9月训练记录

2025年9月训练记录2025/9/26 abc416_f 题意:树上选\(k\)条不相交的链,使得其贡献和最大. 可以考虑树形\(dp\). 考虑状态的设计如下:设\(dp_{u,i,0/1/2}\)表示当前选了以\(u\)为根的子树,且当前子树的根节点的状态为…

20250925 之所思 - 人生如梦

20250925 之所思9月23日,秋分,我最喜欢的节气;在南方,“桦加沙”很快就要在广东沿海登陆...收到了这两年来对自己最重要的邮件,被任命为中国区部门的软件discipline经理。非常感慨,十多年的奋斗不止,终于在这一…

在CodeBolcks下wxSmith的C++编程教程——在屏幕上绘图和保存绘图

0.前言欢迎来到 wxSmith 教程页面!wxSmith 与 Code::Blocks、wxWidgets 和 C++ 编译器相结合,为您提供一种所见即所得的方式来创建具有图形用户界面 (GUI) 的应用程序。该组合形成了一个用于快速应用程序开发 (RA…