如何使用Redis实现分布式锁?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 如何使用Redis实现分布式锁?

首先来说 Redis 作为一个独立的三方系统,其天生的优势就是可以作为一个分布式系统来使用,因此使用 Redis 实现的锁都是分布式锁,理解了这个概念才能看懂本文所说的内容。

分布式锁的示意图,如下所示:
image.png

分布式锁实现

使用 Redis 实现分布式锁,可以通过 setnx(set if not exists)命令实现,当我们使用 setnx 创建键值成功时,则表明加锁成功,否则既代码加锁失败。因为 Redis 主线程是单线程运行的,所以也不会有同时加锁成功的情况。
实现命令如下:

127.0.0.1:6379> setnx lock true
(integer) 1 #创建锁成功
#逻辑业务处理...
127.0.0.1:6379> del lock
(integer) 1 #释放锁

当我们重复加锁时执行结果如下:

127.0.0.1:6379> setnx lock true # 第一次加锁
(integer) 1
127.0.0.1:6379> setnx lock true # 第二次加锁
(integer) 0

从上述命令中可以看出,我们可以使用执行的结果是否为 1 来判断加锁是否成功。

分布锁问题

然而,使用 setnx 实现分布锁有一个【死锁问题】,就是当加锁的线程(或应用)掉电或崩溃之后,其他线程只能无限等待下去的问题。

此时,我们解决死锁问题可以通过添加设置锁的过期时间来实现
也就是 setnx 和 expire 配合使用,在 Redis 2.6.12 版本之后,新增了一个强大的功能,我们可以使用一个原子操作也就是一条命令来执行 setnx 和 expire 操作了,实现命令如下:

127.0.0.1:6379> set lock true ex 30 nx
OK #创建锁成功
127.0.0.1:6379> set lock true ex 30 nx
(nil) #在锁被占用的时候,企图获取锁失败

其中 ex 为设置超时时间, nx 为元素非空判断,用来判断是否能正常使用锁的。

小结

Redis 作为一个独立的三方系统,其优势是天生可以实现分布式锁。它实现分布式锁是通过 setnx 来实现的,然而只有 nx(not exists)可能会发生死锁的问题,所以我们最终实现死锁应该使用 set nx ex 的方式来实现。

小思考:当设置了过期时间之后,Redis 实现分布式依然会有一个小小的问题,有人知道这个问题和解决方案吗?欢迎评论区写出你的答案。
此文章点赞过 100,我会给出标准答案。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
73 2
基于Redis的高可用分布式锁——RedLock
|
2月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
19天前
|
存储 NoSQL Redis
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
Redis持久化、RDB和AOF方案、Redis主从集群、哨兵、分片集群、散列插槽、自动手动故障转移
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
|
2月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
2天前
|
NoSQL 安全 关系型数据库
20)用 Redis 实现分布式锁
20)用 Redis 实现分布式锁
10 0
|
2月前
|
NoSQL 安全 Java
nicelock--一个注解即可使用Redis分布式锁!
Nicelock的引入为分布式系统中的资源同步访问提供了一个简单高效和可靠的解决方案。通过注解的方式,简化了锁的实现和使用,使开发人员可以将更多精力专注于业务逻辑的实现,而不是锁的管理。此外,Nicelock在保持简单易用的同时,也提供了足够的灵活性和可靠性,满足了不同应用场景下对分布式锁的需求。
33 1
|
2月前
|
NoSQL Go Redis
用 Go + Redis 实现分布式锁
用 Go + Redis 实现分布式锁
|
NoSQL Java 关系型数据库
浅谈Redis实现分布式锁
浅谈Redis实现分布式锁
|
存储 canal 缓存
|
NoSQL PHP Redis
redis实现分布式锁
redis实现分布式锁
169 0
redis实现分布式锁