72 分布式锁
72 分布式锁
什么是分布式锁
分布式锁 = 分布式 + 锁。那么分布式是指的什么呢?锁又是锁的谁呢?在业务开发中我们经常会听到分布式分布式的概念,分布式也很简单,通俗的来说就是你具有多个服务器,每个服务器上运行的程序是一样的,用户的每一次请求,都会平衡的分配到随机的一个服务器中进行处理。那么这样的话就会导致一个问题,那就是并发冲突和数据不一致等问题。下面结合一个简单的小例子来介绍一下分布式环境下不使用分布式锁会造成什么问题。
假设你运营着一个在线电商平台,某个商品(商品ID为
product123
)的库存为10件。当用户在下单时,系统会检查库存,确定库存是否充足,然后减少库存并生成订单。为了应对大量并发请求,你的系统使用了多台服务器来处理订单请求。用户1(请求在服务器A上处理)和 用户2(请求在服务器B上处理)同时发出购买请求。当前库存:10件
服务器A接收到用户1的请求,并查询数据库中的库存,此时库存为10件。
服务器B也接收到用户2的请求,并同时查询数据库中的库存,此时库存也是10件。
此时,两个服务器节点都“看到”库存为10件。
服务器A为用户1生成了订单,并将库存减少1。库存应减少为9件。
与此同时,服务器B为用户2生成了订单,并将库存也减少1,认为库存现在也是9件。
- 服务器A将新的库存9件更新回数据库。
- 服务器B将新的库存9件(根据它的视角)更新回数据库。
最终结果:虽然两个用户下单并减少库存,但两台服务器并没有意识到对方的操作,因此它们都认为库存应该从10减少到9,而不是从10减少到8。
实际发生的问题是,两个用户都成功购买了商品,但库存实际上只减少了1件,而不是2件。这就是库存超卖的现象。
库存最终显示为9件,而实际上它应该显示为8件,意味着库存被错误地记录,系统允许用户购买超过实际库存量的商品。
分布式锁保证了在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
分布式锁应该具备的品质
课本上的概念直接列出,让人看了好似懂了又好似没懂。分布式锁简单的来说就是为了在不同服务器上的相同方法只能有一个在某一时刻运行就是了,我们需要锁住一些资源,让其达到这种效果,无论是什么,都会涉及到六个字:高可用高性能,这个也不例外。这个分布式锁需要保证高可用的获取锁和释放锁,也需要保证高性能的获取锁和释放锁。同时为了避免一些意外情况导致某线程一直占用锁,我们需要保证分布式锁具有过期时间,从而避免死锁。
- 1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
- 2、高可用的获取锁与释放锁;
- 3、高性能的获取锁与释放锁;
- 4、具备可重入特性;
- 5、具备锁失效机制,防止死锁;
- 6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。
实现方式
目前我们接触到的很多大型网站都是基于分布式环境下开发的,但是有一个理论被称为CAP理论,这个理论告诉我们,**任何一个分布式系统都无法同时保证系统的一致性、可用性和分区容错性。**所以很多分布式系统都是选择牺牲一定的强一致性来得到高可用和高性能这一目标,它们选择系统只要保证最终一致性即可。
在很多的分布式场景中,为了达到最终一致性需要很多的技术支持,比如:分布式事务和分布式锁等等。这里我们先详细的介绍一下分布式锁的实现方式,分布式锁的实现一般分为三个大类:
- 基于数据库实现分布式锁;
- 基于缓存实现分布式锁;
- 基于ZooKeeper实现分布式锁;
接下来我们一一介绍。
在介绍之前,我们先仔细思考一下锁的概念,什么是锁呢?锁只是一个概念,它不涉及到一个具体的事物。任何只要能保证唯一性的都可以作为锁,我们仔细想想什么能保证唯一性呢?没错,就是数据库中的ID和Redis中的setnx,只要插入了两个一样的就会失败,这就是等价于获取锁失败了。
基于数据库实现分布式锁
通过上面的介绍,那么这个就很简单了,就是创建一个表,这个表就是为了分布式系统用来获取锁的,比如就创建了这个:
CREATE TABLE `distributed_lock` (`lock_key` VARCHAR(64) NOT NULL PRIMARY KEY,`lock_value` VARCHAR(64) NOT NULL,`expires_at` TIMESTAMP NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
如果这个线程想获取到这个锁,就在这个表中插入一条数据,其中lock_key为该线程需要对这个数据进行操作的ID,比如订单ID等等
在每个分布式节点中,当需要对某个共享资源进行操作时,我们会尝试向 distributed_lock
表中插入一条记录。如果插入成功,则表示获取了锁,可以安全地执行操作。如果插入失败,则说明锁已被其他节点占用。
INSERT INTO `distributed_lock` (`lock_key`, `lock_value`, `expires_at`)
VALUES ('product_123', 'UUID-xxxx', DATE_ADD(NOW(), INTERVAL 10 SECOND))
ON DUPLICATE KEY UPDATE`lock_value` = IF(`expires_at` < NOW(), 'UUID-xxxx', `lock_value`),`expires_at` = IF(`expires_at` < NOW(), DATE_ADD(NOW(), INTERVAL 10 SECOND), `expires_at`);
到了评价这个方法的优劣的时候了,首先这个是基于MySQL的,那就是外存中的,不用说效率低,效率低带来的结果就是并发性不高,就不适合高并发的情况,但是该方法方便,但是一般不用。
基于 MySQL 的分布式锁适合那些并发量不大、锁的粒度较粗的场景,如任务调度、定时任务等。对于高并发、低延迟要求较高的场景,建议使用更高效的分布式锁实现,如 Redis 或 ZooKeeper。
ON DUPLICATE KEY UPDATE
:这个语句的作用是在插入新记录时,如果lock_key
已经存在(比如因为主键或唯一约束冲突),则不会重新插入,而是执行更新操作。换句话说,如果已经有人持有了锁,这里会判断锁是否已经过期,如果过期了就让当前请求获取锁。
基于Redis实现分布式锁
基于setnx实现分布式锁
set if not exist = setnx;
- 加锁:执行setnx,若成功再执行expire添加过期时间
- 解锁:执行delete命令
SETNX lock_key unique_value
EXPIRE lock_key 10
这里会存在一些问题,首先就是这事两个操作,不是原子性的,如果客户端在执行 SETNX
后崩溃,EXPIRE
命令无法执行,导致这个锁永远不会自动释放,造成死锁问题。
我们可以通过这个来解决:set nx ex
SET lock_key unique_value NX EX 10
这个是原子性的。
同时这里还有一个过期时间的问题,就是我获取到锁的这个线程,无法在过期时间内完成这个任务,导致别的线程获得了锁,从而又导致了分布式锁的问题。
我们可以通过自动续期(检查当前线程是否完成了任务,如果没有完成就自动的延长过期时间),我们也可以采用更成熟的比如redisson,该提供了更成熟的分布式锁的设计。
基于Redis的Lua脚本能力
使用 SETNX
创建锁时,如果锁被客户端成功获取并持有,当客户端任务执行完毕后需要手动释放锁。然而,如果客户端在释放锁之前崩溃或者出现了错误,可能会导致锁未被正确释放,或者其他客户端错误地释放了本不属于它的锁。
使用 DEL
命令来释放锁时,必须确保只有持有锁的客户端才可以释放它。为此,可以将 unique_value
设置为唯一值(如 UUID),并通过 Lua 脚本确保只有在持有锁的客户端才能删除锁。
if redis.call("GET", "lock_key") == "unique_value" thenreturn redis.call("DEL", "lock_key")
elsereturn 0
end
基于Redisson实现分布式锁
参考资料
- Redis分布式锁-这一篇全了解(Redission实现分布式锁完美方案)
- 7年一线互联网经验,超爱图解底层原理,全栈一枚
重点关注这个方式实现,在以后会经常使用这个Redisson来实现分布式锁。
基于Zookeeper实现分布式锁
优点:不必多说,可以保证高可用,毕竟是专业的,Curator框架已原生支持系列分布式锁命令,使用简单
缺点:也不必多说,成本高,需要单独维护一套ZK集群。
相关文章:

72 分布式锁
72 分布式锁 什么是分布式锁 分布式锁 分布式 锁。那么分布式是指的什么呢?锁又是锁的谁呢?在业务开发中我们经常会听到分布式分布式的概念,分布式也很简单,通俗的来说就是你具有多个服务器,每个服务器上运行的程序…...

使用Windbg分析dump文件排查C++软件异常的一般步骤与要点分享
目录 1、概述 2、打开dump文件,查看发生异常的异常类型码 3、查看发生异常的那条汇编指令 3.1、汇编代码能最直接、最本真的反映出崩溃的原因 3.2、汇编指令中访问64KB小地址内存区,可能是访问了空指针 3.3、汇编指令中访问了很大的内核态的内存地…...
30 天 Python 3 学习计划
30 天 Python 3 学习计划 https://www.runoob.com/python3/python3-tutorial.html 1. Python3 基础语法 2. Python3 基本数据类型 3. Python3 数据类型转换 4. Python3 解释器 5. Python3 注释 6. Python3 运算符 7. Python3 数字(Number) 8. Python3 字符串 …...

【MATLAB实例】批量提取.csv数据并根据变量名筛选
【MATLAB实例】批量提取.csv数据并根据变量名筛选 准备:数据说明MATLAB批量提取参考 准备:数据说明 .csv数据如下: 打开某表格数据,如下:(需要说明的是此数据含表头) 需求说明:需…...

【软件】Ubuntu下QT的安装和使用
【软件】Ubuntu下QT的安装和使用 零、前言 QT是应用得比较广泛的程序框架,是因为其跨平台特性比较好,且用C/C作为开发语言,性能也比较好,故本文介绍如何安装和使用QT,用的版本是QT 6.2.4,由于QT在Windows…...

在Spring Boot中具有多个实现的接口正确注入的六种方式
博客主页: 南来_北往 系列专栏:Spring Boot实战 在Spring Boot中,当一个接口具有多个实现时,正确地将这些实现注入到需要使用它们的地方是一个常见的需求。以下是在Spring Boot中实现这一目标的六种方式: 1. 使用Autowir…...

登陆微软账户太慢了,如何解决
软账号登录慢解决办法: 打开“网络和Internet”选择“以太网”选择“更改适配器选项”选择现用网络,右键->属性选择“IPV4”右键属性更改DNS地址为以下两者4.2.2.14.2.2.2...
Vue3动态组件component不生效问题解决方法
问题: vue3循环渲染动态组件component不生效,页面空白 在vue3使用component动态组件展示组件时,组件就是不展示显示空白。在vue2中使用动态变量component展示组件都是没问题。试了很多方法 踩了很多坑,所以记录下: 登录…...

算力基础篇:从零开始了解算力
什么是算力 算力即计算能力(Computing Power),狭义上指对数字问题的运算能力,而广义上指对输入信息处理后实现结果输出的一种能力。虽然处理的内容不同,但处理过程的能力都可抽象为算力。比如人类大脑、手机以及各类服…...

Redis 万字入门教程
0. 前言 文章已经收录到 GitHub 个人博客项目,欢迎 Star: https://github.com/chenyl8848/chenyl8848.github.io或者访问网站,进行在线浏览: https://chenyl8848.github.io/1. NoSQL 1.1 NoSQL 介绍 NoSQL(Not Only SQL )&…...

LeetCode :LCR 173. 点名
🔥个人主页:guoguoqiang. 🔥专栏:leetcode刷题 LeetCode :LCR 173. 点名 这个题就是缺失的数字,我们可以通过三种方式来解决这个问题。 1.可以通过位异或的方式来找到这个数(相同的数异或为…...

Gin框架操作指南06:POST绑定(下)
官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/ 注:没用过Gin的读者强烈建议先阅读第一节:Gin操作指南:开山篇。 本节继续演示POST绑定,包括将request-body绑定到不同的结构体中&#x…...
LLaMA、llama.cpp和Ollama区别
LLaMA:LLaMA是由Meta(Facebook的母公司)开源的大型语言模型,它提供了不同规模的模型,包括1B、3B、11B和90B等参数规模的版本。LLaMA模型支持多语言对话,并在多个基准数据集上进行了评估,展现出与…...
NDK开发
NDK介绍 app为什么会把代码放到so中 a) C语言历史悠久,有很多现成的代码可用 b) C代码执行效率比Java高 c) Java代码很容易被反编译,而且反编译以后的逻辑很清晰 为什么要学习NDK开发 在安卓的so开发中,其他基本与C/C开发一致ÿ…...
docker overlay 占用空间太大,迁移到 /data/
将 Docker 的 overlay 存储驱动迁移到 /data/ 目录下,可以通过以下步骤完成: 1. 停止 Docker 服务 首先,停止 Docker 服务以确保没有容器在运行,并且数据不会被写入到当前的存储位置。 sudo systemctl stop docker2. 备份现有数…...
Windows性能监控与调优:让电脑运行如飞
一、性能监控 1. 使用任务管理器深入监控 打开任务管理器 我们可以通过按下Ctrl Shift Esc快捷键来打开任务管理器。 或者右键点击任务栏空白处,选择“任务管理器”。 查看性能 在任务管理器中,点击“性能”标签页。 我们可以看到“概览”标签&#x…...
前端响应式布局
1.什么是响应式布局? 响应式布局是一种使网页在不同设备(如手机、平板和桌面)上均能良好显示的设计理念。 2.响应式布局的原理? 通过灵活的网格布局、CSS 媒体查询和弹性单位等技术,实现内容自适应屏幕尺寸变化。 3.响…...

力扣MySQL 1581
先把两张表连接,amount为null 的正是我们需要的,再按customer_id聚合 select Visits.visit_id,customer_id ,Transactions.visit_id ,transaction_id ,amount from Visits left join Transactions on Visits.visit_idTransactions.visit_id 正确代码&…...

就是这个样的粗爆,手搓一个计算器:科学计算器
作为程序员,没有合适的工具,就得手搓一个,PC端,移动端均可适用。废话不多说,直接上代码。 HTML: <div class"calculator"><div class"display-wrapper"><div class"display…...

wordpress使用popup弹窗插件的对比
您在寻找最好的 WordPress 弹出插件吗?大多数网站利用某种形状或形式的弹出窗口来将访问者指向他们希望他们去的地方。例如,这可能用于结帐、电子邮件订阅或用于生成潜在客户。 表现 弹出插件会减慢您的网站速度。当插件使用 WordPress 跟踪弹出窗口的…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...