Redis分布式锁

2 Redis分布式锁

2.1 分布式锁

Sychonized只能保证单个jvm内部多个线程的互斥

多个jvm需要分布式锁:每个jvm都有内部的锁监视器,要用jvm外部的锁监视器,让每个进程都能看见锁监视器

image-20240131210411523

线程1占用锁,在锁监视器监视下执行业务逻辑,其他线程获取锁失败重试,等待锁释放

分布式锁满足分布式系统或集群模式下多进程可见并且互斥的锁

在这里插入图片描述

实现分布式锁的核心就是实现多进程之间的互斥,以下是三种实现分布式锁的方式

image-20240131223905514

2.2 初步实现基于redis的分布式锁

如果获取锁之后,服务宕机了,会造成死锁,所以就需要给值设置一个过期时间 expire key seconds

ttl key 查看过期时间

keys * 查看所有键的信息

如果获取锁之后,设置过期时间之前宕机,还是死锁,所以要保证获取锁和设置过期时间的原子性:使用命令set key value ex seconds nx / SETEX key seconds value

jdk中提供了两种锁机制:

  • 获取锁失败之后阻塞等待
  • 如果获取失败会立即结束并返回一个结果,而不是继续等待

image-20240131225824412

image-20240131225905017

代码实现:

image-20240131230506784

image-20240131230652710

image-20240131231123840

image-20240131231418785

自动拆箱,封箱带来的空指针问题

Boolean到boolean会有自动拆箱的过程,如果success为null,会导致空指针问题,所以为了避免空指针,使用Boolean.True.equals(success),true返回true,false和null都返回false

2.3 分布式锁误删锁问题

问题描述:线程1未执行完业务,但是阻塞了,阻塞期间redis超时释放锁,这时线程2获取锁执行业务,线程2执行业务期间,线程1业务执行完成之后,线程1不知道自己锁释放之后被别人获取了,线程1执行释放锁操作,结果把线程2的锁释放了,线程2还在执行,线程3又来获取锁执行业务,导致线程安全问题

image-20240131232007468

image-20240131232706625

解决方案:释放锁之前,判断锁标识,看是不是自己的锁------------加线程id和uuid判断

image-20240131232045970

image-20240131232810066

2.4 解决误删问题

image-20240131232940760

代码修改

在这里插入图片描述

image-20240131233120715

2.5 分布式锁原子性问题

问题描述:判断锁标识和删除锁是两个操作,如果在线程1判断完锁标识之后,发现是自己的锁,但是在释放锁的时候阻塞了,此时的阻塞可能是由垃圾回收导致的fullGC会导致所有的线程阻塞。阻塞期间,线程1的redis锁过期释放,线程2在这时获取锁执行业务,在线程2执行业务的时候,线程1恢复并释放锁,这时候线程3再获取锁执行业务逻辑,造成线程安全问题

image-20240131234139737

redis是有事务的,但是redis的事务能保证原子性,但是不能保证一致性

redis的事务中的多个操作是批处理操作,最终一次执行,先去查询,再判断,再释放,如果基于redis事务只能使用乐观锁机制确保释放时没有被修改

2.6 Lua脚本解决原子性问题

image-20240131234852406

执行脚本

image-20240131235011260

image-20240131235209106

---------image-20240131235405996

image-20240131235430752

代码改进

image-20240131235545942

新建文件:

image-20240131235657342

image-20240131235754959

image-20240131235833126

image-20240131235843134

image-20240131235934744

2.7 进一步优化

除了上面解决的问题,还存在下面的问题

image-20240201000106722

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值