【实战企业级Java二】渐进式理解Redis分布式锁

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 渐进式理解Redis分布式锁。分布式锁需要满足的条件互斥性、同一性、可重入性、容错性,四个条件的含义,为什么需要这个条件,如何理解分布式锁

渐进式理解Redis分布式锁

并发场景下,由于修改和保存数据的过程不是原子性的,部分操作可能会丢失,在单服务中我们常用本地锁来避免并发带来的问题。但是本地锁无法在多服务器之间生效。

1. 分布式锁需要满足的条件

  • 互斥性:任意时刻,只能有一个客户端获取锁。
  • 同一性:锁只能被持有该锁的客户端删除。
  • 可重入性:持有锁的客户端可继续对该锁加锁,实现锁的续租。
  • 容错性:持有锁的客户端下线,到期释放锁,防止死锁。

2. 如何实现Redis分布式锁?

2.1 如何使用Redis加锁❓
最直白的做法:SETNX

SETNX is short for "SET if Not eXists",即设置KEY如果不存在的话,value我们可以暂定设置1。

SETNX lockName 1

返回1说明key不存在设置成功,即获取到了锁,返回0则加锁失败。

2.2 加锁就需要解锁,使用Redis解锁❗️
删除命令:DEL
DEL lockName

删除了该key,此时其他线程就可以通过SETNX获取锁了。

2.3 为了保证容错性,需要设置锁的超时时间❗️
设置key的过期时间:EXPIRE
EXPIRE lockName 20

为key设置一个超时时间,以保证即使锁没有被显示的释放时,在到达过期时间后也能自动释放锁,防止死锁的产生。

2.4 即第一版的分布式锁伪代码为:⁉️
if(setnx(key,1) == 1){
    expire(key,30)
    try {
        work....
    } finally {
        del(key)
    }
}
2.5 问题1:加锁和设置过期时间是非原子操作❗️

在极端情况下,当线程执行完SETNX还未执行EXPIRE时服务挂掉。

此时该锁既不会被显示的解锁,也不会自动过期,其他线程再也无法获取到该锁了,game over。

2.6 如何解决死锁的问题呢❓
SET命令加锁
SET lockName 1 EX 30

SETNX命令是不支持传入超时时间的,不过幸好Redis2.6.12以后为SET指令增加了可选参数EX、PX属性,这样加锁和设置超时时间就是原子操作了。

2.7 问题2:锁到期,任务未完成❗️

回忆一下我们实现的锁机制,如果锁到期了任务未完成将产生两个严重问题。

image-20220802183924210.png

  1. 将其他线程的锁释放(不满足同一性)。
  2. 其他线程提前获取到了锁,即本不应该同时执行的任务同事执行(不满足互斥性)。
2.8 如何解决释放其他线程锁的问题❓

解决这个问题,我们只需要在删除之前验证key对应的value是不是自己的线程。

我们可以把线程ID作为key对应的value,在删除之前验证一下锁是不是自己的锁。

伪代码:

加锁:
String threadId = Thread.currentThread().getId()
set(key,threadId ,30,EX)
解锁:
if(threadId .equals(redisClient.get(key))){
    del(key)
}

这里,判断锁和删除锁是两个独立操作,不是原子操作。

我们可以使用lua脚本来实现:

String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

这样,判断和删除过程就是原子操作了。

2.9 如果解决两个线程同时获取到锁的问题❓

上面我们解决了释放非自己锁的问题,但是AB两个线程同时执行任务也是不完美的。

我们可以让获得锁的线程开启一个守护线程,用来给快到期的锁续期。

image-20220803010521389.png

3. 下一篇Redisson分布式锁

Redis分布式锁在生产中使用自然不需要我们自己去实现每一个细节,Redis分布式锁在java中的解决方案官方推荐就是Redisson

【Distributed Locks with Redis】

🏄🏻作者简介:CSDN博客专家,华为云云享专家,阿里云专家博主,疯狂coding的普通码农一枚

🚴🏻‍♂️个人主页:莫逸风

🇨🇳喜欢文章欢迎大家👍🏻点赞🙏🏻关注⭐️收藏📄评论↗️转发

🏋️‍♂️公众号:莫逸风

📱微信:moyifengxue

目录
相关文章
|
2月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
2月前
|
安全 Java 开发者
告别NullPointerException:Java Optional实战指南
告别NullPointerException:Java Optional实战指南
249 119
|
3月前
|
人工智能 Java API
Java AI智能体实战:使用LangChain4j构建能使用工具的AI助手
随着AI技术的发展,AI智能体(Agent)能够通过使用工具来执行复杂任务,从而大幅扩展其能力边界。本文介绍如何在Java中使用LangChain4j框架构建一个能够使用外部工具的AI智能体。我们将通过一个具体示例——一个能获取天气信息和执行数学计算的AI助手,详细讲解如何定义工具、创建智能体并处理执行流程。本文包含完整的代码示例和架构说明,帮助Java开发者快速上手AI智能体的开发。
1053 8
|
3月前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
485 12
|
3月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
441 100
|
3月前
|
存储 前端开发 Java
【JAVA】Java 项目实战之 Java Web 在线商城项目开发实战指南
本文介绍基于Java Web的在线商城技术方案与实现,涵盖三层架构设计、MySQL数据库建模及核心功能开发。通过Spring MVC + MyBatis + Thymeleaf实现商品展示、购物车等模块,提供完整代码示例,助力掌握Java Web项目实战技能。(238字)
348 0
|
3月前
|
存储 SQL NoSQL
Redis-常用语法以及java互联实践案例
本文详细介绍了Redis的数据结构、常用命令及其Java客户端的使用,涵盖String、Hash、List、Set、SortedSet等数据类型及操作,同时提供了Jedis和Spring Boot Data Redis的实战示例,帮助开发者快速掌握Redis在实际项目中的应用。
293 1
Redis-常用语法以及java互联实践案例
|
3月前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
|
3月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
217 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
Oracle Cloud Native Java
如何进行基于Anolis OS的企业级Java应用规模化实践?|龙蜥技术
提供了7×24小时的专属钉钉或者电话支持,响应时间保证到在业务不可用情况下10分钟响应,业务一般的问题在一小时可以获得响应,主要城市可以两小时内得到到达现场的服务。
如何进行基于Anolis OS的企业级Java应用规模化实践?|龙蜥技术