【Redis知识点总结】(五)——Redis实现分布式锁

Redis知识点总结(五)——Redis实现分布式锁

  • setnx
  • setnx + expire
  • setnx + expire + lua脚本
  • set nx ex
  • set nx ex + 随机值
  • set nx ex + 随机值 + lua脚本
  • set ex nx + 随机值 + lua脚本 + 锁续期
  • Redisson
  • RedLock

在Redis的众多应用场景中,分布式锁是Redis比较重要的一个应用场景,今天我们就来了解一下如何用Redis实现一个分布式锁。

setnx

Redis提供了一个setnx命令,它的作用是在给缓存设置值时,判断key是否存在,如果key已经存在,则不执行操作,只有当缓存中不存在指定key时,才设置该缓存。

使用setnx命令,就可以实现一个简单的分布式锁。我们指定一个特定的值作为setnx命令的key,然后当一个线程要获取分布式锁时,就要通过setnx命令在redis中设置该key,如果设置成功,代表获取分布式锁成功,如果设置失败,表示获取分布式锁失败,那么当前线程就要通过自旋加sleep的机制等待别的线程释放锁。

一个线程通过setnx命令获取到分布式锁后,通过del命令释放锁。释放锁之后,其他线程就可以再次尝试获取锁。

在这里插入图片描述

但是这种方案有一个严重的问题,就是当一个线程获取到锁后,在处理业务逻辑时发生了异常,或者直接宕机了,没能执行del命令释放锁,那么其他线程就会一直获取不到锁。

setnx + expire

单靠setnx命令实现的分布式锁,存在锁得不到释放的风险。因此,我们可以引入expire命令,给key设置一个过期时间。当一个线程执行setnx命令成功后,就通过expire命令给该key设置一个过期时间。假如该线程执行业务逻辑出错,没能执行del命令,那么等该key的过期时间到后,该key也会被失效清理,锁最终还是能得到释放的。

在这里插入图片描述

这样问题就解决了吗?

显然是没有的,因为setnx和expire是两条命令,是非原子性的,如果setnx执行成功,expire命令执行失败,那么锁还是得不到释放。

setnx + expire + lua脚本

setnx命令与expire命令的非原子性问题,可以通过lua脚本去解决,把setnx和expire两条命令包在一个lua脚本里面,就可以保证这两条命令同时成功或者同时失败,这就就具备了原子性。

在这里插入图片描述

除了使用lua脚本,Redis还可以通过一条命令实现setnx加expire两条命令的功能。

set nx ex

我们可以通过以下命令实现setnx命令加expire命令的功能,并且可以保证原子性:

set key value nx ex {过期时间}

在这里插入图片描述

这样,分布式锁得不到释放的问题就彻底解决了。

但是,这样就没问题了吗?显然不是的,还会出现以下这种情况:

在这里插入图片描述

线程1获取分布式锁成功,但是业务处理时间过长,锁早已过期。而线程2随后获取分布式锁成功,进行业务处理。然后这时候线程1处理完了,于是执行del命令释放锁,而此时它释放的是线程2加的锁,并且线程2还没有处理完。线程2的锁被线程1释放后,如果线程3到来,也获取了分布式锁,那么等线程2处理完毕,又会释放掉线程3获取的锁,以此类推,这个分布式锁就失效了。

set nx ex + 随机值

锁错误释放的问题,可以通过给value指定一个随机值来解决,实现方案是这样:

在这里插入图片描述

执行set命令时生成一个随机值作为value值,并且当前线程要保存该随机值。等到当前线程处理完业务逻辑要准备释放锁时,先拿着自己保存的随机值跟redis中的value比对一下,如果相等,才执行del命令释放锁,否则就不能执行del命令。

这样看似可以解决锁误删的问题,一般情况下也确实如此,但是在高并发场景下,有可能会出现以下这种情况:

在这里插入图片描述

线程1执行完业务逻辑后,判断自己的value随机值与redis中的value相等,正准备释放锁,此时正好锁过期了,然后线程2又刚好获取到了锁,然后线程1才执行del命令,那么线程2的锁又被误释放了。

这是低概率事件,非高并发场景其实不用考虑这个问题,但是在高并发场景,还是有可能出现的。问题的原因是if判断与del命令是两个操作,非原子性。

set nx ex + 随机值 + lua脚本

if判断与del命令的非原子性问题,可以通过lua脚本解决,把if判断与del命令用lua脚本包起来,就可以彻底解决锁误释放的问题。

在这里插入图片描述

现在获取锁与释放锁的操作都是原子性的,我们的分布式锁也逐步变得完善,但是还有一个问题,那就是锁过期,也就是业务处理还未结束,锁就过期的这种情况。

我们可以给锁设置一个较长的过期时间,但是我们无法百分之一百保证所有的业务处理都在锁过期前得到释放,如果在某种特殊情况下处理时间比平常的要长,锁还是过期了,那么还是有问题的。

set ex nx + 随机值 + lua脚本 + 锁续期

锁过期的解决办法,就是开一个“看门狗”线程,进行锁续期,这个线程会定时地不断的检测主线程释放处理完毕并且释放了锁,如果主线程还没有处理完毕,那么这个“看门狗”线程就会执行expire命令进行锁续期。

在这里插入图片描述

此时,我们的分布式锁就完美了。但是,这样太复杂了吧?我们为了实现一个分布式锁,居然要处理这么多问题,使得原本简单的代码变得非常复杂,那有没有一个开源框架,可以帮我们实现这一切,我们只需要简单的调用一下就完事了呢?

当然是有的,那就是使用Redisson的分布式锁。

Redisson

Redisson是一个用Java语言实现的用于操作Redis的客户端工具包,比起原生的Jedis工具包,Redisson是更好用,功能更强大的。

Redisson就自带了分布式锁的实现,把我们上面说到的获取锁的原子性、释放锁的原子性、利用看门狗线程进行锁续期等一系列的操作都包装起来,对外暴露了简单的获取锁和释放锁的方法,我们无需手动编码实现这复杂的获取锁与释放锁的逻辑,只要使用Redisson提供的分布式锁的方法,就可以实现分布式锁的功能。

在这里插入图片描述

使用Redisson,我们就可以轻松简单的实现分布式锁的功能,但是如果Redis是单节点的话,Redis宕机了,那么所有线程都无法获取到锁了。

在这里插入图片描述

解决Redis单节点的问题,自然是上多个Redis节点。但是上了多个Redis节点之后,分布式锁又怎么实现呢?

RedLock

Redis的作者提出了一个多redis节点的分布式锁实现方案,那就是RedLock。

首先,我们要启5个redis节点,但是这5个节点是独立的节点,互相之间没有主从关系,也没有组成集群。

当一个线程加锁时,需要按顺序的访问这五个节点,还是利用set nx ex或set nx px命令进行加锁。

当一个线程在至少3个以上的redis节点成功执行了set命令,那么就表示获取锁成功,此时该线程要计算锁的有效期,需要用锁的有效期减去加锁耗费的时间,如果还有剩余时间,表示获取锁成功,如果没有剩余时间了,那么表示获取锁失败。

如果一个线程获取锁失败,要按相反的顺序向所有redis节点执行del命令释放锁。

在这里插入图片描述

这个RedLock的功能,同样可以通过Redisson实现,只需要调用Redisson提供的简单的API方法即可,无需我们编写复杂的RedLock代码。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FDA: 用于语义分割的傅里叶域自适应

论文链接:https://arxiv.org/abs/2004.05498 代码链接:GitHub - YanchaoYang/FDA: Fourier Domain Adaptation for Semantic Segmentation 机构:UCLA 发表于2020CVPR 这篇文章别的地方略读了,主要看看方法,感兴趣自…

淘宝商品详情API接口采集商品上货

使用淘宝商品详情API接口采集商品信息以进行上货是一个常见的需求,但需要注意的是,淘宝的API接口使用受到严格的限制和规定,需要遵循淘宝的开放平台政策。以下是一般性的步骤和建议,但请确保在实际操作中遵循淘宝的官方文档和规定…

极智芯 | 解读移动端芯片荟萃篇 主流移动芯片性能对比

欢迎关注我的公众号「极智视界」,获取我的更多技术分享 大家好,我是极智视界,本文分享一下 解读移动端芯片荟萃篇 主流移动芯片性能对比。 要说芯片的应用场景一般都会说云边端、云边端的,这里的移动端芯片当然是会属于云边端中的端场景了,主要是面向手机、平板等应用。下…

springboot实战笔记

用户模块开发 用户登录接口实现 根据token获取用户信息 检查账号是否可用 用户注册接口实现

【每日算法】理论:常见AIGC模型; 刷题:力扣单调栈

上期文章 【每日算法】理论:生成模型基础; 刷题:力扣单调栈 文章目录 上期文章一、上期问题二、理论问题1、stable diffusion模型的网络架构2、T5的网络架构(Text-To-Text Transfer Transformer模型)3、SDXL模型4、DA…

【网络安全】 MSF生成木马教程

本文章仅用于信息安全学习,请遵守相关法律法规,严禁用于非法途径。若读者因此作出任何危害网络安全的行为,后果自负,与作者无关。 环境准备: 名称系统位数IP攻击机Kali Linux6410.3.0.231客户端Windows 76410.3.0.234…

二叉搜索树、B-树、B+树

二叉搜索树 二叉查找树,也称为二叉搜索树、有序二叉树或排序二叉树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;若任意节点的右子树不空&#xff0…

java入门-基本数据类型

今天开始开贴关注初学java的同学,写些基础内容,希望对大家有所帮助。如果对大家有帮助会一直写下去。 java基本语法-基本数据类型 概述 基本数据类型在程序运行中,需要内存空间来存储数据。数据存储的大小有不同,申请合理的内存空…

POJO简介

文章目录 简介POJO与ELB的区别POJO真正的意思 常见的POJO类DTODAOPOVOEntity 简介 什么是POJO?POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB(EJB是Enterprise Java Beans技…

Docker【docker使用】

文章目录 前言一、概念二、常用方法1.镜像2.容器 三、镜像构建贺管理 前言 上一篇文章讲了docker的安装,本片文章我们来聊聊docker的一些常用操作。以及镜像、容器之间的关系 一、概念 docker三大核心概念:镜像 Image、容器 Container、仓库 Reposito…

Opencv4+稀疏光流算法详解+实现

0. 写在前面 项目需要用到光流法找到图像中的点运动方向,想到光流法刚好适用。原理部分参考: 图像处理算法--光流法-原理-CSDN博客 1. Opencv4.5.4稀疏光流函数说明 1.1 稀疏光流API介绍 prevImg:视频前一帧图像/金字塔,单通道CV_…

获取远程管理软件保存的凭据

点击星标,即时接收最新推文 本文选自《内网安全攻防:红队之路》 扫描二维码五折购书 内网敏感数据的发现 内网的核心敏感数据,不仅包括数据库、电子邮件,还包括个人数据及组织的业务数据、技术数据等。可以说,价值较高…

(零)OpenOFDM接收端整体思路

一旦捕获射频信号并将其下变频至基带,解码管道就会启动,包括: OFDM,多载波调制的一种。通过频分复用实现高速串行数据的并行传输, 它具有较好的抗多径衰落的能力,能够支持多用户接入。 OFDM主要思想是:将信…

(1)fopen,fseek,fread,ftell,rewind作用和使用方法,大端小端

文章目录 1.fopen,fseek,fread,ftell,rewind作用和使用方法2.bin文件里从0x0000到0x0x0007是00 00 DF 00 00 01 00 00,但是用fread读出来前四个字节是DF0000,然后是0x1000,这是为什么&#xff1…

2024蓝桥杯每日一题(回溯)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一:木棒 试题二:n皇后问题 试题三:糖果 试题四:飞机降落 试题五:生日蛋糕 试题一:木棒 【问题描述】 乔治拿来一组等长…

steam_api.dll“是什么?打开游戏出现找不到steam_api.dll无法继续执行代码如何解决

"steam_api.dll"是什么?,steam_api.dll它是由windows系统Visual C Redistributable for Visual Studio提供的。当这个文件损坏或丢失时,会导致一些应用程序无法运行,显示找不到"steam_api.dll"缺失错误。本文…

马斯克开源的grok AI大模型

马斯克践行诺言,坚持开源原则,选择开源自家的 AI 大模型——Grok-1 下载链接如下: https://github.com/xai-org/grok-1 Grok-1 开源仅过去了 10 个小时,该项目便获得了 超过16k 的 Star,成为众人关注的焦点所在。 后续继续更新…

Python二级备考(1)考纲+基础操作

考试大纲如下: 基本要求 考试内容 考试方式 比较希望能直接刷题,因为不懂的比较多可能会看视频。 基础操作刷题: 知乎大头计算机1-13题 import jieba txtinput() lsjieba.lcut(txt) print("{:.1f}".format(len(txt)/len(ls)…

springcloud:4.2 GateWay结合JWT实现网关鉴权

概述 概述 简介 JWT是一种用于双方之间传递安全信息的简洁的、URL安全的声明规范。 定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。 特别适用于分布式站点的单点登录(SSO)场景 传统的session认证的缺点 安全性:CSRF攻击因为基于cookie来…

掌握AI写作工具:引领内容创作潮流

随着技术发展,AI技术正日益渗透到各行各业,并对内容创作领域产生了深远影响。随着AI写作工具的不断发展和普及,内容创作者们正逐渐看到了AI在提高效率、创造力和质量方面的巨大潜力。本文将探讨AI写作工具如何引领内容创作潮流,以…