如何用Redis实现分布式锁?


theme: smartblue

分布式锁是什么?为什么要有这个技术,解决了什么问题?

讲到分布式锁,我们会很容易联想到单机锁。在java多线程编程中,通常我们会使用锁来保护共享变量,来保证线程安全。这里面的锁作用范围是同一个进程中。如果是多个进程,应该怎么保护共享资源?这就是分布式锁来解决的问题。分布式解决的是在多个进程,如果确保对共享资源操作的正确性。
那我们应该如何实现分布式锁?
需要借助其他第三方服务来解决,比如mysql、zookeeper、Redis等。

不同实现方案

mysql

利用数据库的唯一约束特性来实现锁的互斥性。比如创建一张锁表,表中包含锁名称(用于区分不同的业务锁)、锁定状态等字段。当某个服务要获取锁时,向表中插入一条对应锁名称的记录,如果插入成功则表示获取到锁,若插入失败(违反唯一约束)则说明锁已被其他服务占有。释放锁时,只需删除对应的记录即可。

  • 优点
    实现相对简单,理解容易,借助数据库的稳定性和持久性保证锁的可靠性,适用于并发量不是特别巨大的场景。
  • 缺点
    性能相对较差,获取锁和释放锁涉及数据库操作,有一定的 I/O 开销;存在单点故障问题,如果数据库出现故障,整个分布式锁机制将受到影响;可能会出现死锁情况,比如获取锁的服务崩溃,没来得及释放锁。

基于 Zookeeper 实现分布式锁

Zookeeper 是一个分布式协调服务,它通过节点的创建和删除以及节点的顺序性等特性来实现分布式锁。通常利用临时顺序节点来实现,当一个服务要获取锁时,在 Zookeeper 指定路径下创建一个临时顺序节点,然后获取该路径下所有子节点,判断自己创建的节点是否是序号最小的节点,如果是则表示获取到锁;如果不是,则监听序号比自己小的节点的删除事件,当监听的节点被删除时,再次判断自己是否为最小节点来获取锁。释放锁就是删除对应的临时顺序节点。在 Java 中可以通过 Curator 等框架来方便地操作 Zookeeper 实现分布式锁。

  • 优点
    可靠性高,基于 Zookeeper 的分布式一致性协议(如 ZAB 协议),能保证在集群环境下锁的一致性;具备高可用和容错性,Zookeeper 集群可以应对节点故障等情况;可以实现阻塞式获取锁,方便处理需要等待锁释放的业务场景。
  • 缺点
    性能相比 Redis 稍差一些,因为涉及到节点的创建、查询、监听等一系列操作,有一定的网络开销和 Zookeeper 服务器的处理成本;实现相对复杂,需要对 Zookeeper 的相关概念和操作比较熟悉,代码的编写和理解成本相对较高。

Redis分布式锁方案

一款优秀分布式锁应该具有什么特点?

互斥性

含义:在任意时刻,对于同一个被保护的资源,只能有一个客户端能够获取到分布式锁,其他客户端若尝试获取,需等待当前持有锁的客户端释放锁之后才有机会获取。这确保了在分布式环境下针对共享资源的并发访问能够按照顺序依次进行,避免多个客户端同时操作资源而导致数据不一致等问题。

可重入性

一个已经获取到分布式锁的客户端,在锁未释放期间,如果再次请求获取该锁,仍然能够成功获取,并且锁的释放次数需要和获取次数严格匹配才能最终真正释放锁。这在一些具有递归调用或者嵌套调用逻辑的业务场景中非常重要,避免自己把自己 “锁死” 而无法继续后续操作。类似java多线程中的可冲入锁概念

阻塞特性与超时机制

  • 阻塞特性
  • 含义:当客户端尝试获取锁但当前锁已被其他客户端持有时,该客户端能够阻塞等待,直到获取到锁或者超时为止,而不是立刻返回失败结果。这样可以保证在高并发情况下,客户端有机会获取到锁去操作资源,不用频繁地发起获取锁的请求去轮询。

  • 超时机制

  • 含义:为了防止某个客户端获取锁后由于异常情况(比如进程崩溃、网络故障等)一直没有释放锁,导致其他客户端无限期等待,需要给锁设置一个超时时间,一旦超过这个时间,锁会自动释放,让其他客户端有机会获取锁。

具体实现:

单机版本的分布式锁

最简单的分布式锁: setnx 这个命令代表如果key不存在,然后才设置。操作完成后del删除这个key就行。
但是有一个很大的问题,客户端1拿到锁之后,如果没有释放锁,或者进程挂了,没机会释放锁。其他客户端就永远没有机会拿到锁。
如何解决?
很自然的一个思路,给这个锁设置一个有效时间,类似锁设置一个超时时间,过了这个时间,自动释放锁,给其他客户端一个机会获取临界资源。我们可以使用redis 提供的 SET key 1 EX 10 NX 该命令是原子性的。
看起来很完美了,但是我们再细想一下。首先就是这个过期时间,现实中很难设置准确,设置太长,导致资源浪费,设置太短,又没法确保客户端执行完业务代码。我们有没有一种机制能够自动给锁延长时间呢?答案是存在的,我们开启一个守护线程(我们通常称为看门狗线程),定时检测这个锁的失效时间,如果锁快要过期了,操作共享资源还没有完成,我们就可以自动给锁进行续期,重新设置过期时间。
这个时候我们再想一下,还存在什么问题? 客户端释放锁,会无脑释放,并不会检查是不是自己的锁,我们需要在客户端加锁的时候,设置一个唯一标识,比如UUID,线程id等。释放锁的时候,先判断一下是不是自己的锁,是自己的锁,才会进行释放。这个时候,会设计到redis不同命令。redis通过lua脚本来确保原子性。
大概流程是:
加锁。 设置锁,并且设置一个唯一标识来标识这个锁, 操作共享资源,释放锁,lua脚本,先判断是不是自己的锁,然后再del锁。

分布式场景下的锁

如果有多台redis实例,如何实现呢?
1、客户端先获取当前时间戳t1。
2、客户端依次向n个redis实例发起加锁命令,并且每一个请求设置超时时间(这个时间要远小于锁的有效时间,不然你还没设置,锁就到期了,没有意义),如果某个实例加锁失败,就立即向下一个实例申请加锁。
3、如果超过一般以上的redis实例加锁成功,就再次获取当前时间戳t2。t2-t1看一下是否超过了锁的超时时间,没有代表客户端加锁成功,否则失败。
4、加锁成功就可以操作共享资源。
5、如果加锁失败,就需要向全部节点释放锁的请求。

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

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

相关文章

AS-REP Roasting离线爆破攻击

针对一个域内用户,其账户选项有个设置叫作 “不要求 kerberos 预身份验证”,它默认是关闭的。 当 “不要求 kerberos 预身份验证” 选项被勾选,会出现以下效果: as-req 报文中不需要添加用户 hash 加密的时间戳,自动返…

JMeter配置原件-计数器

一、面临的问题: 由于本人的【函数助手对话框】中counter计数器每次加2,且只显示偶数(如下图所示),因此借助【配置原件-计数器】来实现计数功能。 如果有大佬知道解决方式,麻烦评论区解答一下,谢谢。 二、配置原件-c…

基于“2+1 链动模式商城小程序”的微商服务营销策略探究

摘要:本文探讨在竞争激烈的市场经济与移动互联网时代背景下,微商面临的机遇与挑战。着重分析“21 链动模式商城小程序”如何助力微商改变思路,通过重视服务、提升服务质量,以服务营销放大利润,实现从传统微商模式向更具…

Grad-CAM-解释CNN决策过程的可视化技术

Grad-CAM(Gradient-weighted Class Activation Mapping)是一种用于解释卷积神经网络(CNN)决策过程的可视化技术。其核心思想是通过计算分类分数相对于网络确定的卷积特征的梯度,来识别图像中哪些部分对分类结果最为重要…

文件防泄漏 | 文件防泄漏软件解决方案分享,网络数据泄露防护系统

文件防泄漏 | 文件防泄漏软件解决方案分享,网络数据泄露防护系统 企业面临的一大挑战是数据安全和隐私保护。 网络数据泄露不仅会导致经济损失,还会损害企业的声誉和客户关系。 为了应对这一挑战,域智盾软件应运而生,成为众多企…

EGO Swarm翻译

目录 摘要 Ⅰ 介绍 Ⅱ 相关工作 A . 单四旋翼局部规划 B . 拓扑规划 C. 分布式无人机集群 Ⅲ 基于梯度的局部规划隐式拓扑轨迹生成 A.无需ESDF梯度的局部路径规划 B.隐式拓扑轨迹生成 Ⅳ 无人机集群导航 A 机间避碰 B. 定位漂移补偿 C. 从深度图像中去除agent Ⅴ …

直流充电桩基本工作原理

1、控制导引电路 2、电动汽车直流快充工作原理 1)第一阶段 未充电自然状态阶段 充电枪处于自然阶段,充电枪上的按钮没有按下,也就是电路图中的开关S处于接通状态,此时R1 、 R2串联,检测点1处的电压为6V 2)…

七、网络安全-企业数据脱敏

文章目录 前言一、数据脱敏方法二、企业脱敏方案1. 数据库脱敏方案2. 历史数据脱敏3. 具体实现 三、日志脱敏方案四、输出脱敏 前言 数据脱敏‌ 随着用户对个人隐私数据的重视和法律法规的完善,数据安全显得愈发重要。一方面可以加强权限管理,减少能够接…

任务2 配置防火墙firewalld

基本概念 概述 支持动态更新防火墙规则 不重启即可创建、修改和删除规则 使用区域和服务来简化防火墙配置 区域 一组预定义的规则,防火墙策略集合(或策略模板) 把网络分配到不同的区域中,并为网络及其关联的网络接口或流量源…

HIPT论文阅读

题目《Scaling Vision Transformers to Gigapixel Images via Hierarchical Self-Supervised Learning》 论文地址:[2206.02647] Scaling Vision Transformers to Gigapixel Images via Hierarchical Self-Supervised Learning 项目地址:mahmoodlab/HI…

重拾设计模式--状态模式

文章目录 状态模式(State Pattern)概述状态模式UML图作用:状态模式的结构环境(Context)类:抽象状态(State)类:具体状态(Concrete State)类&#x…

[WiFi] WiFi 802.1x介绍及EAP认证流程整理

802.1X Wi-Fi 802.1X 是一种网络访问控制协议,常用于保护无线网络。它提供了一种基于端口的网络访问控制机制,主要用于在用户和网络之间建立安全的连接。以下是 802.1X 的一些关键特点: 认证框架 802.1X 使用 EAP(可扩展认证协议…

服务器数据恢复—V7000存储中多块磁盘出现故障导致业务中断的数据恢复案例

服务器存储数据恢复环境: 一台V7000存储上共12块SAS机械硬盘(其中1块是热备盘),组建了2组Mdisk,创建了一个pool。挂载在小型机上作为逻辑盘使用,小型机上安装的AIXSybase。 服务器存储故障: V7…

网络安全防范

实践内容 学习总结 PDR,$$P^2$$DR安全模型。 防火墙(Firewall): 网络访问控制机制,布置在网际间通信的唯一通道上。 不足:无法防护内部威胁,无法阻止非网络传播形式的病毒,安全策略…

你的第一个博客-第一弹

使用 Flask 开发博客 Flask 是一个轻量级的 Web 框架,适合小型应用和学习项目。我们将通过 Flask 开发一个简单的博客系统,支持用户注册、登录、发布文章等功能。 步骤: 安装 Flask 和其他必要库: 在开发博客之前,首…

LLaMA-Factory(一)环境配置及包下载

LLaMA-Factory(一)环境配置及包下载 本机配置1. git下载2.创建虚拟环境3. 下载官方包内依赖4. 下载bitsandbytes5. 启动项目6. 可能出现问题1:pip install 出现 error: subprocess-exited-with-error 错误7. 可能出现问题2: ModuleNotFoundEr…

clickhouse-题库

1、clickhouse介绍以及架构 clickhouse一个分布式列式存储数据库,主要用于在线分析查询 2、列式存储和行式存储有什么区别? 行式存储: 1)、数据是按行存储的 2)、没有建立索引的查询消耗很大的IO 3)、建…

计算机网络:运输层 —— TCP 的选择确认(SACK)

文章目录 TCP 的选择确认协商与启用工作机制接收方发送方 TCP 的选择确认 在 TCP 传输过程中,由于网络拥塞、链路故障等因素,数据可能会出现丢失或乱序的情况。传统的 TCP 确认机制是累积确认,TCP 接收方只能对按序收到的数据中的最高序号给…

HTML语法规范

HTML语法规则 HTML 标签是由尖括号包围的关键词&#xff0c;标签通常是成对出现的&#xff0c;例如 <html> 和 </html>&#xff0c;称为双标签 。标签对中的第一个标签是开始标签&#xff0c;第二个标签是结束标签单标签比较少&#xff0c;例如<br />&#x…

STL 剖析

STL 六大组件 「STL 六大组件的交互关系」 Container 通过 Allocator 取得数据储存空间Algorithm 通过 Iterator 存取 Container 内容Functor 可以协助 Algorithm 完成不同的策略变化Adapter 可以修饰或套接 Functor、Iterator 配置器(allocator) 配置器&#xff1a;负责空间…