java从头开始-黑马点评-Redission

下面四种都是比较极端情况下可能出现的问题,其实前面实现的已经很够用了

Redission



Redission可重入锁的原理

之前的方法无法实现可重入锁

可重入锁的实现其实就是换成Hash类型,然后添加一个申请次数,线程号是自己就+1,释放锁就-1.最后一次执行删除。但是比较复杂的是Hash中没有setnx,所以要先判断再申请,把流程拆开



完整流程,其实可以用Lua脚本实现



解决不可重试问题

最核心的一句,这一步是获取锁的剩余有效期:

获得剩余时间以后会判断当前还有没有剩余等待时间,没有就返回失败,有就继续判断

释放锁的时候有一行发布一个释放消息

继续执行的代码会执行一个订阅操作,订阅的就是释放锁的消息。然后紧跟判断,如果在最大剩余等待时间以内订阅消息一直没有出现,会取消订阅并返回false。


如果依然有剩余等待时间,就会重新提交一次请求锁操作


解决超市释放的安全问题

如果TTL快到期了,但是程序还没执行完,此时实现了一个TTL续约的机制

这里的putIfAbsent是如果 key 不存在,就把 key-value 放进去;如果 key 已经存在,不覆盖,直接返回旧值。

下面是具体的续约机制

newTimeout是一个延时的任务,会在参数的时间到期以后执行。执行完成以后外面会调用自己,此时锁的有效时间就会无限延期

执行刷新有效期

同样怎么让他不在刷新呢,其实就是在解锁过程中取消订阅执行。

取消定时任务

不可重试+超时释放完整流程


主从一致性导致的锁失效问题

最开始有主节点和从节点,主节点负责写,从节点负责读

但是出现了问题,主节点宕机了,此时会从从节点中选择一个作为主节点。但是此时java应用和之前的主节点的锁失效,此时新的主节点相当于没有锁,所有的线程都可以去申请加锁

一种解决方法就是放弃主从,全部加锁

但是这样就没有主从了,因此我们给多个主节点都加上从节点。对多个主节点加锁,全部加上锁才算是获取成功,其他主节点的锁没有释放当然不可以被获取。

如果一个主节点宕机,此时还有其他主节点存在,此时的锁还没有被释放,因此其他线程不能加锁。因为此时是对多个主节点加锁,全部加上锁才算是获取成功,其他主节点的锁没有释放当然不可以被获取。

redis分布式联锁的实现

首先实现了多个节点,也就是建立了多个redis数据库,此时我们当然要给每一个都进行配置

配置的时候也写上多个redis

创建联锁,这里会将多个锁加入一个List中,加锁的时候会把所有的锁全都进行加锁,如果全部成功才算是获取锁成功。然后具体的加锁解锁流程和普通的lock一样。
注意,联锁中的每一个锁都是可重入锁

相关推荐
lUie INGA18 小时前
在2023idea中如何创建SpringBoot
java·spring boot·后端
小糖学代码19 小时前
LLM系列:1.python入门:15.JSON 数据处理与操作
开发语言·python·json·aigc
handler0119 小时前
从源码到二进制:深度拆解 Linux 下 C 程序的编译与链接全流程
linux·c语言·开发语言·c++·笔记·学习
geBR OTTE19 小时前
SpringBoot中整合ONLYOFFICE在线编辑
java·spring boot·后端
Porunarufu19 小时前
博客系统UI自动化测试报告
java
小白学大数据19 小时前
现代Python爬虫开发范式:基于Asyncio的高可用架构实战
开发语言·爬虫·python·架构
渔舟小调19 小时前
P19 | 前端加密通信层 pikachuNetwork.js 完整实现
开发语言·前端·javascript
不爱吃炸鸡柳20 小时前
数据结构精讲:树 → 二叉树 → 堆 从入门到实战
开发语言·数据结构
网络安全许木20 小时前
自学渗透测试第21天(基础命令复盘与DVWA熟悉)
开发语言·网络安全·渗透测试·php
t***54420 小时前
如何在Dev-C++中使用Clang编译器
开发语言·c++