温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Redis中分布式锁如何解决锁超时问题

发布时间:2021-07-29 17:38:19 来源:亿速云 阅读:444 作者:Leah 栏目:大数据

本篇文章给大家分享的是有关Redis中分布式锁如何解决锁超时问题,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

一、前言

关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题), 但代码执行时间可能需要30s, 然后redis服务端10s后将锁删除, 此时, B线程恰好申请锁, redis服务端不存在该锁, 可以申请, 也执行了代码, 那么问题来了, A、B线程都同时获取到锁并执行业务逻辑, 这与分布式锁最基本的性质相违背: 在任意一个时刻, 只有一个客户端持有锁, 即独享

二、准备工作

压测工具jmeter


https://pan.baidu.com/share/init?surl=NN0c0tDYQjBTTPA-WTT3yg提取码: 8f2a

redis-desktop-manager客户端


https://pan.baidu.com/share/init?surl=NoJtZZZOXsk45aQYtveWbQ提取码: 9bhf

postman


https://pan.baidu.com/share/init?surl=28sGJk4zxoOknAd-47hE7w提取码: vfu7

也可以直接官网下载, 我这边都整理到网盘了

需要postman是因为我还没找到jmeter多开窗口的办法, 哈哈

三、说明

1、springmvc项目

2、maven依赖

Redis中分布式锁如何解决锁超时问题

3、核心类

  • 分布式锁工具类: DistributedLock

  • 测试接口类: PcInformationServiceImpl

  • 锁延时守护线程类: PostponeTask

四、实现思路

先测试在不开启锁延时线程的情况下, A线程超时时间设为10s, 执行业务逻辑时间设为30s, 10s后, 调用接口, 查看是否能够获取到锁, 如果获取到, 说明存在线程安全性问题

同上, 在加锁的同时, 开启锁延时线程, 调用接口, 查看是否能够获取到锁, 如果获取不到, 说明延时成功, 安全性问题解决

五、实现

1、版本01代码

1)、DistributedLock

Redis中分布式锁如何解决锁超时问题

Redis中分布式锁如何解决锁超时问题

说明: 就2个方法, 加锁解锁, 加锁使用jedis setnx方法, 解锁执行lua脚本, 都是原子性操作

2)、PcInformationServiceImpl

Redis中分布式锁如何解决锁超时问题

说明: 测试类很简单, value随机生成, 保证唯一, 不会在超时情况下解锁其他客户端持有的锁

3)、打开redis-desktop-manager客户端, 刷新缓存, 可以看到, 此时是没有add_information_lock的key的

Redis中分布式锁如何解决锁超时问题

4)、启动jmeter, 调用接口测试

设置5个线程同时访问, 在10s的超时时间内查看redis, add_information_lock存在, 多次调接口, 只有一个线程能够获取到锁

往期100篇回顾:一百期面试题汇总

redis

Redis中分布式锁如何解决锁超时问题

1-4个请求, 都未获取到锁

Redis中分布式锁如何解决锁超时问题

第5个请求, 获取到锁

Redis中分布式锁如何解决锁超时问题

OK, 目前为止, 一切正常, 接下来测试10s之后, A仍在执行业务逻辑, 看别的线程是否能获取到锁

Redis中分布式锁如何解决锁超时问题

可以看到, 操作成功, 说明A和B同时执行了这段本应该独享的代码, 需要优化。

往期100篇回顾:一百期面试题汇总

2、版本02代码

1)、DistributedLock

Redis中分布式锁如何解决锁超时问题

Redis中分布式锁如何解决锁超时问题

Redis中分布式锁如何解决锁超时问题

说明: 新增了锁延时方法, lua脚本, 自行脑补相关语法

2)、PcInformationServiceImpl不需要改动

3)、PostponeTask

Redis中分布式锁如何解决锁超时问题

Redis中分布式锁如何解决锁超时问题

说明: 调用lock同时, 立即开启PostponeTask线程, 线程等待超时时间的2/3时间后, 开始执行锁延时代码, 如果延时成功, add_information_lock这个key会一直存在于redis服务端, 直到业务逻辑执行完毕, 因此在此过程中, 其他线程无法获取到锁, 也即保证了线程安全性

下面是测试结果

10s后, 查看redis服务端, add_information_lock仍存在, 说明延时成功

Redis中分布式锁如何解决锁超时问题

此时用postman再次请求, 发现获取不到锁

Redis中分布式锁如何解决锁超时问题

看一下控制台打印

Redis中分布式锁如何解决锁超时问题

Redis中分布式锁如何解决锁超时问题

A线程在19:09:11获取到锁, 在10 * 2 / 3 = 6s后进行延时, 成功, 保证了业务逻辑未执行完毕的情况下不会释放锁

A线程执行完毕, 锁释放, 其他线程又可以竞争锁

OK, 目前为止, 解决了锁超时而业务逻辑仍在执行的锁冲突问题, 还很简陋, 而最严谨的方式还是使用官方的 Redlock 算法实现, 其中 Java 包推荐使用 redisson, 思路差不多其实, 都是在快要超时时续期, 以保证业务逻辑未执行完毕不会有其他客户端持有锁

以上就是Redis中分布式锁如何解决锁超时问题,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI