首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Redis系列(二):Redis的分布式锁解析及应用

Redis系列(二):Redis的分布式锁解析及应用

作者头像
鳄鱼儿
发布于 2024-05-21 09:09:29
发布于 2024-05-21 09:09:29
22100
代码可运行
举报
运行总次数:0
代码可运行

在开发中,一个进程中多个线程需要竞争某一资源的时候,我们通常会用一把锁来保证只有一个线程获取到资源。如加上synchronize关键字或ReentrantLock锁等操作。但如果是多个进程相互竞争一个资源,如何保证资源只会被一个操作者持有呢?

比如在微服务的架构下,多个应用服务要同时对同一条数据做修改,要确保数据的正确性,那就只能有一个应用修改成功。

Redis实现分布式锁

上一篇文章中在String-字符串类型中可以用作分布式锁,那么具体是如何实现的呢?

首先 Redis 是一个单独的非业务服务,不会受到其他业务服务的限制,所有的业务服务都可以向Redis发送写入命令,且只有一个业务服务可以写入命令成功,那么这个写入命令成功的服务即获得了锁,可以进行后续对资源的操作,其他未写入成功的服务,则进行阻塞处理。

String类型实现

使用setnx(SET if Not Exists)指令实现,即如果 key 不存在,才会设置它的值,否则什么也不做。

假设有两个客户端同时竞争锁,即向Redis写入lock_key,A客户端写入成功则A先获取到锁,客户端B写入失败则B未获取到锁。A客户端在使用完资源后,将redis中lock_key删除,即释放锁。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# A执行写入
> setnx lock_key true
(integer) 1
# A获得锁,执行A的业务
> del lock_key
(integer) 1
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# B执行写入
> setnx lock_key true
(integer) 0
# B未获取锁,阻塞

但这样是存在一些问题的,试想如果A客户端在获取锁后,出现了故障,导致del语句没有调用,这样lock_key就一直得不到释放,即该资源锁一直存在,那么其他服务也就永远得不到该资源了。那么如何避免呢?

避免死锁

在Redis写入数据时,可以设置数据过期时间,这样即便在服务故障,锁也能自动释放。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> setnx lock_key true
(integer) 1
> expire lock_key 5
(integer) 1
#  执行业务
> del lock_key
(integer) 1

通过expire指令实现锁过期时间害存在一些问题,试想如果expire出错,没有成功执行,那么也将会造成前面的死锁情况。

因为 setnx 和 expire 是两条指令而不是原子指令,在Redis2.8版本中,可以通过set key velue ex timeout nx来实现setnx和expire两条指令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> set lock_key true ex 5 nx
OK
#  执行业务
> del lock_key
(integer) 1

虽然解决了死锁,但这样又引入了新问题,试想A的业务执行过长,超过了锁的过期时间,A锁已经被释放,但此时B重新又获得了锁,A执行完后释放锁,可能就释放了B刚获取到的锁。这就出现了锁过期,释放其他服务锁的问题

避免锁超时问题

每个服务在设置value的时候,带上自己服务的唯一标识,如UUID,或者一些业务上的独特标识。这样在删除key的时候,只删除自己服务之前添加的key就可以了。

但匹配value和删除key是两条指令,不是原子操作,且redis中没有提供set这样的扩展参数,没法直接通过指令实现原子操作。

这里就需要使用Lua脚本处理,Lua脚本可以保证连续多个指令的原子性执行,将这两个操作合并成一个操作,就可以保证其原子性了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# delifequals
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Redis 之分布式锁的实现
我们在系统中修改已有数据时,需要先读取,然后进行修改保存,此时很容易遇到并发问题。由于修改和保存不是原子操作,在并发场景下,部分对数据的操作可能会丢失。在单服务器系统我们常用本地锁来避免并发带来的问题,然而,当服务采用集群方式部署时,本地锁无法在多个服务器之间生效,这时候保证数据的一致性就需要分布式锁来实现。
架构狂人
2023/08/16
9820
Redis 之分布式锁的实现
Redis-分布式锁
https://mp.weixin.qq.com/s/RnSokJxYxYDeenOP_JE3fQ
Get
2024/03/10
2480
Redis分布式锁到底安全吗?
与分布式锁相对应的是「单机锁」,我们在写多线程程序时,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来「互斥」,以保证共享变量的正确性,其使用范围是在「同一个进程」中。
Vincent-yuan
2021/09/29
8680
Redis系列(十三)应用之分布式锁
分布式锁有着多种多样的实现方式,今天就来介绍一下 如何用 Redis 实现一个分布式锁。
呼延十
2020/09/20
5550
初识Redis · 分布式锁
到了分布式锁这一章之后,我们首先能联想到的问题就是线程安全的问题,线程安全指的是多个线程在并发执行的时候先手顺序是不确定的,那么就会出现同时对一个变量操作的情况,对于这种情况我们要保证的就是顺序问题,保证程序在任意执行顺序下的逻辑都是没问题的。
_lazy
2025/04/30
1500
初识Redis · 分布式锁
2023-06-19:讲一讲Redis分布式锁的实现?
要实现分布式锁,确实需要使用具备互斥性的Redis操作。其中一种常用的方式是使用SETNX命令,该命令表示"SET if Not Exists",即只有在key不存在时才设置其值,否则不进行任何操作。通过这种方式,两个客户端进程可以执行SETNX命令来实现互斥,从而达到分布式锁的目的。
福大大架构师每日一题
2023/08/29
3610
2023-06-19:讲一讲Redis分布式锁的实现?
谈谈基于Redis的分布式锁
在我们没有了解分布式锁前,使用最多的就是线程锁和进程锁,但他们仅能满足在单机jvm或者同一个操作系统下,才能有效。跨jvm系统,无法满足。因此就产生了分布式锁,完成锁的工作。
一个风轻云淡
2023/11/25
6330
基于redis的分布式锁
概述 在之前, 我也使用redis做过分布式锁, 当时的做法是这样的: setnx: 向 redis中创建一个过期时间为1s的key, 若创建失败, 则锁获取失败 expire: 获取锁成功后, 给锁
烟草的香味
2020/03/26
3960
Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析 & 七种方案!探讨Redis分布式锁的正确使用姿势!
采用 redis 实现分布式锁,主要是利用其单线程命令执行的特性,一般是 setnx, 只会有一个线程会执行成功,也就是只有一个线程能成功获取锁; 看着很完美。然而,。。。
一个会写诗的程序员
2022/11/30
2.6K0
Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析 & 七种方案!探讨Redis分布式锁的正确使用姿势!
七种方案!探讨Redis分布式锁的正确使用姿势!
日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式。如果有不正确的地方,欢迎大家指出哈,一起学习一起进步。
macrozheng
2021/03/24
1K0
七种方案!探讨Redis分布式锁的正确使用姿势!
基于redis实现的分布式锁
借助于redis中的命令setnx(key, value),key不存在就新增,存在就什么都不做。同时有多个客户端发 送setnx命令,只有一个客户端可以成功,返回1(true);其他的客户端返回0(false)。
一个风轻云淡
2023/12/05
5350
Redis分布式锁的10个坑
日常开发中,经常会碰到秒杀抢购等业务。为了避免并发请求造成的库存超卖等问题,我们一般会用到Redis分布式锁。但是使用Redis分布式锁,很容易踩坑哦~ 本文田螺哥将给大家分析阐述,Redis分布式锁的10个坑~
捡田螺的小男孩
2022/12/29
1.7K0
Redis分布式锁的10个坑
【Redis】Redis 分布式锁
随着业务发展的需要,原单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的 Java API 并不能提供分布式锁的能力。为了解决这个问题就需要一种跨 JVM 的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!
终有救赎
2023/10/26
4710
【Redis】Redis 分布式锁
七种方案!探讨Redis分布式锁的正确使用姿势
日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式。如果有不正确的地方,欢迎大家指出哈,一起学习一起进步。
捡田螺的小男孩
2021/03/15
1.5K0
012:Redis分布式锁
比如一个操作要修改用户的状态,修改状态需要先读出用户的状态,在内存里进行修 改,改完了再存回去。如果这样的操作同时进行了,就会出现并发问题,因为读取和保存状态这两个操作不是原子的。(Wiki 解释:所谓 原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch 线程切换。)
李玺
2021/11/22
8950
012:Redis分布式锁
Redis 分布式锁没这么简单,网上大多数都有 bug
Redis 分布式锁这个话题似乎烂大街了,不管你是面试还是工作,随处可见,「码哥」为啥还写?
码哥字节
2021/11/16
1.3K0
redis分布式锁的实现(setNx命令和Lua脚本)
本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结
全栈程序员站长
2022/08/31
3.7K0
Node.js 中实践基于 Redis 的分布式锁实现
在一些分布式环境下、多线程并发编程中,如果对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题。
五月君
2019/12/05
3.3K0
面试官:你真的了解Redis分布式锁吗?
说到Redis,我们第一想到的功能就是可以缓存数据,除此之外,Redis因为单进程、性能高的特点,它还经常被用于做分布式锁。
鄙人薛某
2021/01/15
8690
面试官:你真的了解Redis分布式锁吗?
深入理解分布式锁
假设这里有一个分布式应用,它拥有多个客户端,每个客户端都会对存储在Redis中的数据进行计算并修改,计算的前提是获取到最新的数据,然后进行计算,最后写回Redis。在一个不存在并发的程序中,程序可以直接读取Redis中的数据进行计算并写回结果,也不会产生什么问题,因为计算的过程是一个串行的过程,但是如果在一个并发环境中,多个客户端完全存在并行读取,并行写入的情景,那么就可能会产生并发问题,导致最终计算的数据产生偏差。
itlemon
2020/04/03
5070
深入理解分布式锁
相关推荐
Redis 之分布式锁的实现
更多 >
领券
一站式MCP教程库,解锁AI应用新玩法
涵盖代码开发、场景应用、自动测试全流程,助你从零构建专属AI助手
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验