业界内分布式锁
技术主题
在分布式系统中,面对分布式微服务日益流行的场景,分布式锁一直是分布式系统老生常谈的内容。分布式锁可以防止用户重复点击,对于电商场景中,分布式锁可以防止用户重复下单,给用户带来更好的体验。
技术实现方式
一基于Redis的实现方式
通过在Redis中存储一个唯一的key,利用Redis的原子性操作来实现锁的获取和释放
二基于ZooKeeper的实现方式
利用Zookeeper的节点临时性和唯一性特点,在一个节点上创建一个临时节点表示锁的占用状态,释放锁时直接删除该节点
三基于数据库的实现方式
通过在数据库中创建一张表,将表的相关信息作为表的字段,通过事务的控制来实现锁的获取和释放
技术具体实现原理
一基于Redis的具体实现原理
- Redis操作必须是原子的:获取锁和释放锁的Redis操作必须是原子的,可以使用Redis的setnx命令实现。它可以原子地执行一次 SET 命令,当且仅当 key 不存在,可以设置成功。
- 设置过期时间:为避免死锁,需要设置锁的过期时间,若处理业务超时导致锁未被释放,则其他节点可以重新竞争获取锁。使用Redis的expire命令可以设置key的过期时间。
- 避免误删:为避免误删其他线程的锁,建议在删除前先判断锁是否属于自己。尽管不同线程生成的随机字符串保持一定的唯一性,但是无法完全避免重复。
二基于ZooKeeper的具体实现原理
- ZooKeeper操作必须是原子的:获取锁和释放锁的ZooKeeper操作必须是原子的,可以使用ZooKeeper的create命令实现。它可以原子地创建一个唯一且临时的节点。
- 设置临时节点:在ZooKeeper中创建一个临时节点,表示锁的占用状态。当该节点的客户端断开连接或删除该节点时,ZooKeeper将自动清除该节点。
- 利用顺序号:在创建临时节点时,可以利用ZooKeeper中的顺序号进行排序,使得节点可以按照一定的顺序排列。其他客户端在同样的目录下依照节点顺序创建临时节点,获得锁的客户端是首个创建临时节点的客户端。
- 避免死锁:由于删除节点操作可以避免死锁,因此在释放锁的时候需要删除该节点。如果释放锁的时候出现异常导致无法删除节点,可以设置一个超时时间,让ZooKeeper自动删除该节点。
- 处理异常情况:在分布式系统中,可能会出现各种异常情况,比如网络异常、ZooKeeper节点宕机等情况,需要对这些异常情况进行处理。通常的做法是捕获异常并释放锁。
三基于数据库的实现原理
基于数据库乐观锁实现分布式锁的方法是,为每个需要锁定的资源在数据库中创建一个对应的记录,记录包含以下信息:
- 资源名称(resource)
- 当前锁定者的标识(owner)
- 最后一次锁定时间(last_lock_time)
- 版本号(version)
其中,owner、last_lock_time 和 version 可以使用数据库的行版本号实现,而资源名称是唯一的。
实现步骤如下:
- 当需要锁定资源时,在数据库中执行以下 SQL 语句:
UPDATE lock_table SET owner=<当前线程标识>, last_lock_time=NOW(), version=version+1
WHERE resource=<资源名称> AND owner IS NULL;
该语句会尝试更新 lock_table 表中指定资源的记录,并将 owner 设置为当前线程的标识。如果更新成功,则表示当前线程获取了锁;如果更新失败,则表示有其他线程正在持有该资源的锁。
- 当释放锁时,在数据库中执行以下 SQL 语句:
UPDATE lock_table SET owner=NULL, last_lock_time=NOW(), version=version+1
WHERE resource=<资源名称> AND owner=<当前线程标识> AND version=<当前版本号>;
该语句会尝试将持有资源锁的线程标识和版本号更新为 NULL 和当前版本号+1。如果更新成功,则表示当前线程成功释放了锁;如果更新失败,则表示要么该资源并没有被当前线程锁定,要么在锁定期间该资源的版本号已经被修改了。
需要注意的是,由于乐观锁是基于数据版本号的,因此在高并发情况下,会有一定的冲突率,需要在应用程序中进行重试或回退等操作来保证锁定操作的可靠性。另外,该实现方案也需要确保数据库的事务隔离级别为 SERIALIZABLE,以避免并发情况下的数据不一致性问题。
四数据库悲观锁
数据库的被关锁
此外,MySQL 还支持通过 SELECT FOR UPDATE 或 SELECT … LOCK IN SHARE MODE 语句来实现悲观锁。例如:
SELECT field1, version FROM your_table WHERE id = your_id FOR UPDATE;
该语句会将该记录上锁,防止其他事务修改该记录,从而实现悲观锁的效果。在 MySQL 中,悲观锁机制使用的是表锁和行锁,因此在高并发情况下,也需要注意锁冲突导致的性能问题。
相关文章:
业界内分布式锁
技术主题 在分布式系统中,面对分布式微服务日益流行的场景,分布式锁一直是分布式系统老生常谈的内容。分布式锁可以防止用户重复点击,对于电商场景中,分布式锁可以防止用户重复下单,给用户带来更好的体验。 技术实现…...

基于Java+Springboot+Vue+elememt甜品屋蛋糕商城系统设计和实现
基于JavaSpringbootVueelememt甜品屋蛋糕商城系统设计和实现 博主介绍:5年java开发经验,专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系…...

C/C++每日一练(20230424)
目录 1. 只出现一次的数字 🌟 2. 有效的括号 🌟🌟 3. 递归反序正整数 🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 只出现一次…...

三百左右的蓝牙耳机哪个音质好?三百左右音质最好的蓝牙耳机推荐
在外出携带的数码产品中,蓝牙耳机的出现频率居高不下,一部手机,一副耳机已经成为不少人外出的标配。蓝牙耳机无外乎是用来听的,下面,我来给大家推荐几款三百左右音质好的蓝牙耳机,一起来看看吧。 一、南卡…...

把阿里大鸟花3个月时间整理的软件测试面经偷偷给室友,差点被他开除了···
写在前面 “这份软件测试面经看起来不错,等会一起发给他吧”,我看着面前的面试笔记自言自语道。 就在这时,背后传来了leder“阴森森”的声音:“不错吧,我可是足足花了三个月整理的” 始末 刚入职阿里的我收到了大学…...
跳槽时的决策逻辑是什么?
你好,我是辰洋,《郭东白的架构课》的项目负责人。 我们正文的第二个模块已经更新过半。之前已经预告过,东白老师会时不时邀请一些不同行业的技术领导者来交流与对话,为你提供更多的视角、更宽阔的视野和更多元的思考维度。 正值…...

vs2022下配置zxing cpp环境
生成zxing 下载zxing,zxing-cpp-master https://github.com/zxing-cpp/zxing-cpp Cmake生成项目,点Generate,把OpenCV_DIR修改了,NameValue没有报红就点Generate。然后点Open Project打开项目。 打开项目后,右击解决…...

【linux】linux入门级别指令
一些基础指令 前言用户登录新建用户 ls指令pwd命令cd 指令which指令alias指令touch指令mkdir指令rmdir指令 && rm 指令rmdirrm man指令cp指令mv指令catmoreless指令head 指令tail指令输出重定向时间相关的指令cal指令find指令grep指令zip/unzip指令tar指令bc指令uname指…...

Android 开发之核心技术点——性能优化篇(带面试题)~
性能优化对于Android开发的重要性非常大。随着Android设备的不断升级,用户对应用的要求也越来越高,包括应用的运行速度、响应速度、流畅度等方面。如果应用的性能不能满足用户的需求,很可能会导致用户流失、差评以及应用被卸载等情况。 另外…...

typescript全局安装卸载以及npm相关问题
全局安装 npm install -g typescript 全局安装之后,如果想要卸载要使用 npm uninstall -g typescript 全局安装之后可以在终端使用 tsc xxx 编译ts文件 本地安装,也就是在项目目录下安装 npm install typescript 本地卸载 npm uninstall type…...

一条SQL如何被MySQL架构中的各个组件操作执行的?
文章目录 1. 单表查询SQL在MySQL架构中的各个组件的执行过程2. SELECT的各个关键字在哪里执行?3. 表关联查询SQL在MySQL架构中的各个组件的执行过程4. LEFT JOIN将过滤条件放在子查询中再关联和放在WHERE子句上有什么区别?5. 聚集索引和全表扫描有什么区…...
Go语言面试题--进阶语法(30)
文章目录 1.下面的代码能否正确输出?2.下面代码输出什么?3.下面的代码有什么问题?4.下面代码有什么不规范的地方吗? 1.下面的代码能否正确输出? func main() {var fn1 func() {}var fn2 func() {}if fn1 ! fn2 {pri…...

JavaScript概述四(DOM文档对象模型)
1.DOM(Document Object Model) 会把网页里面的元素当成对象去操作,包含对象的属性,属性值,方便我们去 操作网页。 整个页面最终会形成一个对象 :document ,页面里面的所有的元素(如 标签 ) 最终都会转换成 js 里面的对象。 1.1 获取页面的元素(通过选择器࿰…...
【玩转client-go】如何获取 Kubernetes API 客户端的 *rest.Config 对象
目录 1. 使用 kubeconfig 文件 2. 使用 Kubernetes 集群内的 Service Account 3. 直接指定 API Server 的地址和认证信息 4. 使用 genericclioptions.NewConfigFlags() 总结 在使用 Kubernetes API 客户端——client-go 的过程中,我们通常需要获取 *rest.Config 配…...

保护模式段描述符
目前为止,内存还是分段模式,所以想要保护内存,就需要保存段。由于CPU的扩展导致了32位的段基地址和段内偏移,所以16位的段寄存器就无法放下这些信息。现在就需要把这些信息放到内存中,这些信息被封装成特定的段描述符。…...

两个数组的交集
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 思路: 由于这道题目,输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的, 同时可…...

原创文章生成器在线版-ai写作生成器
随着人工智能技术的迅猛发展,越来越多的人开始意识到,利用AI可以实现许多以前不可能想象的事情。其中,一种最能体现人工智能技术优势的应用就是“ai原创文章生成器”。它可以为营销从业者提供一种全新的营销推广方式。 那么,什么是…...
打造高性能CSS的九个技巧我是这么做的
在Web开发中,CSS是不可或缺的一部分。但是,如果CSS代码不够优化,会导致页面加载速度变慢,用户体验下降。以下是九个技巧,用于打造高性能的CSS代码。 避免使用通配符选择器:通配符选择器会匹配页面中的所有…...
python tqdm教程
文章目录 1. 搭配迭代器使用2. 设置动态数据打印3. 中途打印不干扰进度条4. 在jupyter中打印不干扰进度条5. 使用gui显示进度条6. 双循环嵌套进度条7. enumerate和tqdm搭配使用参考文献tqdm是python中打印进度条的一个简易工具包,可以方便查看循环的进度。具体见tqdm文档 1. …...

深度学习 - 41.Word2vec、EGES 负采样实现 By Keras
目录 一.引言 二.实现思路 1.样本构建 2.Word2vec 架构 3.EGES 架构 4.基于 NEG 的 Word2vec 架构 三.Keras 实现 Word2vec 1.样本构建 2.模型构建 3.向量获取 四.keras 实现 EGES 1.样本构建 2.模型构建 3.Dot Layer 详解 3.1 init 方法 3.2 call 方法 3.3 完…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...