Redis分布式锁存在的问题以及解决方式

news2025/2/25 11:29:34

☆* o(≧▽≦)o *☆嗨~我是小奥🍹
📄📄📄个人博客:小奥的博客
📄📄📄CSDN:个人CSDN
📙📙📙Github:传送门
📅📅📅面经分享(牛客主页):传送门
🍹文章作者技术和水平有限,如果文中出现错误,希望大家多多指正!
📜 如果觉得内容还不错,欢迎点赞收藏关注哟! ❤️

文章目录

  • Redis分布式锁实现
  • 一、分布式锁
  • 二、 基于Redis的分布式锁
    • 2.1 初级版本
    • 2.2 解决分布式锁误删问题
    • 2.3 分布式锁的原子性问题
    • 2.4 Redis分布式锁存在的问题

Redis分布式锁实现

一、分布式锁

分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:

MySQLRedisZookeeper
互斥利用MySQL本身的互斥锁机制利用setnx互斥命令利用节点的唯一性和有序性实现互斥
高可用
高性能一般一般
安全性断开连接,自动释放锁利用锁超时时间,到期释放临时节点,断开连接自动释放

二、 基于Redis的分布式锁

2.1 初级版本

实现基于Redis的分布式锁需要实现两个基本的方法:

获取锁

互斥:确保只有一个线程获取锁

// 添加锁,利用setnx的互斥特性
setnx lock thread1
// 添加锁过期时间,避免服务器宕机引起的死锁
expire lock 10
// 添加锁,NX是互斥,EX是设置超时时间
set lock thread1 NX EX 10

释放锁

  • 手动释放:删除key即可
  • 超时释放:获取锁时添加一个超时时间
// 释放锁,删除即可
del key

基本逻辑

  • 业务开始时尝试获取锁
    • 获取锁失败,直接返回
    • 获取锁成功,开始执行业务
      • 如果业务超时或服务宕机,自动释放锁
      • 否则执行完业务手动释放锁

存在的问题 :分布式锁误删问题

比如如下的场景:

  • 线程1首先获取锁,正常获取到锁,开始执行自己的业务。
  • 由于某种原因,线程1的业务被阻塞,并且阻塞时间超过了锁的过期时间,导致锁被自动释放
  • 锁被释放后,线程2再来获取锁,因为线程1的锁被释放了,所以线程2也能成功获取到锁,然后开始执行自己的业务。
  • 在线程2执行业务时,线程1的业务完成,线程1手动释放锁,此时,线程1释放的是线程2的锁。
  • 这时候,线程3也来获取锁,因为线程2的锁被线程1释放了,所以线程3也能成功获取到锁,然后开始执行自己的业务。
  • 此时,线程2和线程3是并行执行业务的,会出现错误的结果。

产生原因:

  • 没有唯一的锁标识,所以会产生误删的情况。

在这里插入图片描述

2.2 解决分布式锁误删问题

要想解决分布式锁误删的问题,主要的关键思路在于:如何判断是不是自己的锁。

这时就可以使用**线程标识 **(即线程ID)来当作分布式锁标识:

  • 如果线程标识与当前线程一致,则释放锁;
  • 如果线程标识与当前线程不一致,则不做处理;

处理逻辑

业务开始时尝试获取锁,锁的标识可以是线程ID:

  • 获取锁之前先比较当前线程ID与锁标识是否一致:
    • 不一致,获取锁失败,直接返回
    • 一致,获取锁成功,开始执行业务
      • 如果业务超时或服务宕机,自动释放锁
      • 业务执行完成,比较当前线程ID与锁标识是否一致
        • 一致,手动释放锁
        • 不一致,不做任何处理

存在的问题:分布式锁原子性问题

比如如下的场景:

  • 线程1首先获取锁,正常获取到锁,开始执行自己的业务。
  • 线程1业务执行完毕,需要手动释放锁,获取锁标识并判断是否与自己一致,结果一致,执行手动释放锁的动作,假设此时产生了阻塞,并且阻塞时间超过了锁的过期时间,导致锁被自动释放
  • 锁被释放后,线程2再来获取锁,因为线程1的锁被释放了,所以线程2也能成功获取到锁,然后开始执行自己的业务。
  • 在线程2执行业务过程中,线程1的阻塞结束了,此时继续执行手动释放锁动作,线程1手动释放锁,此时,线程1释放的是线程2的锁。
  • 这时候,线程3也来获取锁,因为线程2的锁被线程1释放了,所以线程3也能成功获取到锁,然后开始执行自己的业务。
  • 此时,线程2和线程3是并行执行业务的,会出现错误的结果。

产生原因:

  • 判断锁标识释放锁是两个操作,没有保证原子性。

在这里插入图片描述

2.3 分布式锁的原子性问题

要想解决操作原子性问题,我们可以使用Lua脚本解决多条命令原子性问题。

Redis提供的调用函数,语法如下:

# 执行redis的命令
redis.call('命令名称','key','其他参数',...)

Lua脚本

-- 锁的key
local key = KEYS[1]
-- 当前线程标识
local threadId = ARGV[1]
-- 比较线程标识与锁中的标识是否一致
if (redis.call('get', KEYS[1]) == ARGV[1]) then
	-- 释放锁
	return redis.call('del', KEYS[1])
end
return 0

Lua脚本处理逻辑

  • 获取锁中的线程标识
  • 判断是否与当前线程标识一致
    • 一致,手动删除锁
    • 不一致,不做处理

2.4 Redis分布式锁存在的问题

上面的实现逻辑呢,其实就已经能满足简单的分布式锁的功能了,但是由于它是我们自己实现的,所以还是会有一些问题:

(1)不可重入:同一个线程只能获取一次锁,无法多次获取同一把锁,如果我们有嵌套业务都需要用到分布式锁,那么这种Redis实现的锁就不可以使用了。

(2)不可重试:获取锁时如果获取失败就直接返回了,没有重试机制,这种对性能来说其实并不友好。

(3)超时释放:锁超时释放虽然可以避免死锁,但是如何业务执行耗时较长也会导致锁超时释放,存在不可预估的问题。

(4)主从一致性无法保证:如果Redis提供了主从集群,因为主从同步存在延迟,并且一般都是主写从读。如果线程在主节点获取了锁,并且尚未同步给从节点的过程中,突然主节点宕机,虽然Redis会重新选取一个从节点作为新的主节点,但是新主节点中没有锁的标识,所以也会出现多线程并行执行业务的情况(情况出现概率极低)。

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

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

相关文章

ROS---传感器集成

ROS—传感器集成 对于ROS机器人,如果想让其启动,我们需要逐一启动底盘控制与激光雷达,操作有点冗余。并且如果只是简单启动这些节点,那么在在 rviz 中显示时,会发现出现了TF转换异常,比如参考坐标系设置为o…

如何设置Windows 11的WSL系统用作备用桌面环境

如何设置Windows 11的WSL系统用作开发环境(含Astrill设置) 如何设置Windows 11的WSL系统用作备用桌面环境 引子: 2023年末,公司突然遭遇网络攻击,调整了防火墙设置,连接VPN用来飞X软件,与原来…

JAVA基础----String类型的简单介绍

文章目录 1. String类的重要性2. 常用方法2.1 字符串构造2.2 String对象的比较2.3 字符串查找2.4 转化2.5 字符串替换2.6 字符串拆分2.7 字符串截取2.8 其他操作方法2.9 字符串的不可变性2.10 字符串修改2.11 借助StringBuffer 和 StringBuilder 观察String进行修改的效率 3. S…

实时语音多实例实现设计方案(服务端)

1.端上接入协议 如何自行开发代码访问阿里语音服务_智能语音交互(ISI)-阿里云帮助中心 2.接口修改结果逻辑及端上调用步骤 阿里client server交互流程图: 阿里语音接收识别结果: begin_time time 含义 客户端循环发送语音数据,持续接收…

vue学习,使用provide/inject通信

提示&#xff1a;组件的provide&#xff0c;可以被其内所有层级的组件&#xff0c;通过inject引用 文章目录 前言一、通信组件二、效果三、参考文档总结 前言 需求&#xff1a;使用provide/inject通信 一、通信组件 1、AA.vue <template><div class"test"…

【开发实践】前端jQuery+gif图片实现载入界面

一、需求分析 载入界面&#xff08;Loading screen&#xff09;是指在计算机程序或电子游戏中&#xff0c;当用户启动应用程序或切换到新的场景时&#xff0c;显示在屏幕上的过渡界面。它的主要作用是向用户传达程序正在加载或准备就绪的信息&#xff0c;以及提供一种视觉上的反…

腾讯云2核2G4M云服务器值得买吗?

随着云计算技术的不断发展和普及&#xff0c;越来越多的企业和个人开始意识到云服务器的优势&#xff0c;并选择将其业务迁移至云端。作为国内领先的云计算服务提供商&#xff0c;腾讯云一直致力于为用户提供高品质的云服务器服务。其中&#xff0c;腾讯云2核2G4M云服务器备受关…

Docker 安装 MySQ

Docker 安装 MySQL MySQL 是世界上最受欢迎的开源数据库。凭借其可靠性、易用性和性能&#xff0c;MySQL 已成为 Web 应用程序的数据库优先选择。 1、查看可用的 MySQL 版本 访问 MySQL 镜像库地址&#xff1a;https://hub.docker.com/_/mysql?tabtags 。 可以通过 Sort b…

SpringBoot教程(十二) | SpringBoot集成JPA

SpringBoot教程(十二) | SpringBoot集成JPA 1. JPA简介 概念&#xff1a; JPA顾名思义就是Java Persistence API的意思&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。 优势&#xff1a; 标准化 …

Postman使用方法指南,最全面的教程

Postman使用教程 一、Postman介绍 ​ Postman是一个英语单词&#xff0c;名词&#xff0c;作名词时意为“邮递员&#xff1b;邮差”。 ​ Postman是一个接口测试工具,在做接口测试的时候,Postman相当于一个客户端,它可以模拟用户发起的各类HTTP请求,将请求数据发送至服务端,获…

【PS】PS设计图欣赏、学习、借鉴

【PS】PS设计图欣赏、学习、借鉴 bilibili萌新PS学习计划&#xff1a;PS教程全套零基础教学视频&#xff08;全套81节全新版本&#xff09;

Flink1.17 基础知识

Flink1.17 基础知识 来源&#xff1a;B站尚硅谷 目录 Flink1.17 基础知识Flink 概述Flink 是什么Flink特点Flink vs SparkStreamingFlink的应用场景Flink分层API Flink快速上手创建项目WordCount代码编写批处理流处理 Flink部署集群角色部署模式会话模式&#xff08;Session …

conda install命令无法安装pytorch

由于网络问题&#xff0c;直接采用conda install命令可能无法直接下载对应的cuda包。 方法一&#xff1a;采用pip命令替代 步骤1&#xff1a;切换pip的源为国内源&#xff1a; 若只是临时切换&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-p…

分子动力学模拟—LAMMPS 模拟(固体和液体)数据后处理软件(六)

记录一下检索到一篇分子动力学模拟数据后处理的软件。 感谢论文的原作者&#xff01; 主要功能&#xff1a; Structure Analysis Ackland Jones Analysis CentroSymmetry Parameter Common Neighbor Analysis Common Neighbor Parameter Atomic Structure Entropy Stein…

9个在线图像压缩工具,可让您直接压缩 JPG、PNG 和 GIF 文件。

在这篇文章中&#xff0c;我们收集了九个出色的在线图像优化工具&#xff0c;可让您直接从网络浏览器压缩 JPG、PNG 和 GIF 文件。 除了分享有关每个工具的信息之外&#xff0c;我们还将分享测试 JPG 和 PNG 图像的真实测试数据&#xff0c;以便您了解每个工具可以节省的文件大…

C# 实现单线程异步互斥锁

文章目录 前言一、异步互斥锁的作用是什么&#xff1f;示例一、创建和销毁 二、如何实现&#xff1f;1、标识&#xff08;1&#xff09;标识是否锁住&#xff08;2&#xff09;加锁&#xff08;3&#xff09;解锁 2、异步通知&#xff08;1&#xff09;创建对象&#xff08;2&a…

SpringBoot基础:一步步创建SpringBoot工程

摘要 本文介绍了&#xff0c;从零开始创建SpringBoot工程&#xff0c;且在每一步给出分析和原因。创建maven – 转Springboot – 引入jdbc – 引入数据库操作框架&#xff0c;最后给出了不同场景指定不同配置文件的方案。 背景 为什么要使用SpringBoot工程&#xff1f; 使用Sp…

YOLOv8全网首发:DCNv4更快收敛、更高速度、更高性能,效果秒杀DCNv3、DCNv2等 ,助力检测

💡💡💡本文独家改进:DCNv4更快收敛、更高速度、更高性能,完美和YOLOv8结合,助力涨点 DCNv4优势:(1) 去除空间聚合中的softmax归一化,以增强其动态性和表达能力;(2) 优化存储器访问以最小化冗余操作以加速。这些改进显著加快了收敛速度,并大幅提高了处理速度,DCN…

X Winner受邀出席泰国政府加密峰会,上演未来独角兽的独角戏

​在近日&#xff0c;游戏化流动性&#xff08;Gamified Liquidity&#xff09;的基础设施 X WINNER &#xff0c;受邀出席了由泰国政府举办的“Blockchain to Government Conference ”大会。据了解&#xff0c;该会议是泰国政府布局 Web3 产业的一个重要标志&#xff0c;同时…

《WebKit 技术内幕》之四(2): 资源加载和网络栈

2.Chromium 多进程资源加载 2,1 多进程 资源的实际加载在各个WebKit移植中有不同的实现。Chromium采用的多进程的资源加载机制。 ResourceHandle 类之下的部分是不同移植对获取资源的不同实现&#xff0c;Chromium 中是 多进程资源加载 。主要是多个Renderer进程和Browser进程…