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一样。
注意,联锁中的每一个锁都是可重入锁

相关推荐
JAVA学习通2 小时前
北京明光云振铎数据科技Java面经
java·开发语言·科技
贫民窟的勇敢爷们8 小时前
SpringBoot整合AOP切面编程实战,实现日志统一记录+接口权限校验
java·spring boot·spring
jerryinwuhan8 小时前
基于各城市站点流量的复合功能比较
开发语言·php
AC赳赳老秦9 小时前
供应链专员提效:OpenClaw自动跟踪物流信息、更新库存数据,异常自动提醒
java·大数据·服务器·数据库·人工智能·自动化·openclaw
迈巴赫车主9 小时前
Java基础:list、set、map一遍过
java·开发语言
灵犀学长10 小时前
基于 Spring ThreadPoolTaskScheduler + CronTrigger 实现的动态定时任务调度系统
java·数据库·spring
南 阳10 小时前
Python从入门到精通day66
开发语言·python
好家伙VCC11 小时前
【无标题】
java
十八旬11 小时前
快速安装ClaudeCode完整指南
开发语言·windows·python·claude
前进的李工12 小时前
EXPLAIN输出格式全解析:JSON、TREE与可视化
开发语言·数据库·mysql·性能优化·explain