redis续期_面试官: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依赖

5a85c926bde6d12ae1726a2801269f50.png

3、核心类

  • 分布式锁工具类: DistributedLock
  • 测试接口类: PcInformationServiceImpl
  • 锁延时守护线程类: PostponeTask

四、实现思路

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

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

五、实现

1、版本01代码

1)、DistributedLock

9711eb44161f4a0c4a26cf0f90319db1.png
5e0bdb4ab1c1a555907408e9569cd8ee.png

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

2)、PcInformationServiceImpl

a4553825223b9829c6c3ae62361bed06.png

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

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

79c9b4f515990368c918e28f2e129ca9.png

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

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

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

redis

3ff99ec1c86aa949468cbbe7526eca13.png

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

91242e07244cc9e6c8f7fd2696f939d5.png

第5个请求, 获取到锁

97c738c30dfc9f8a74416e5b07f4117d.png

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

960065521a4df0f6ef5c2ca30d763832.png

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

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

2、版本02代码

1)、DistributedLock

173ad90b9f7113a3eec790f907116967.png
16fbe669c635c6d4071ce0530be055d5.png
3f3cd429f0a24d0f991c4f6e0eceb04c.png

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

2)、PcInformationServiceImpl不需要改动

3)、PostponeTask

9d8a9fea98f6bc705a3c41731557d804.png
9b2200e4db5a763b3ccdd6dfc6e4ed69.png

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

下面是测试结果

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

31f35436911440ede87d399b780c0c69.png

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

508724fd8e4611b35453cb2d6fd56506.png

看一下控制台打印

8568ff31ff03713ea45a428abb065a1b.png
b60e268af382a1e2dc7ab7c16b787113.png

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

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

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


关于面试面试我还通过一些渠道整理了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

77e0259245166c0ad9763da0817115c4.png

珍藏多年的230个高端简历模板,也一起送给大家

4ebd007f451b64e847c248e405444e83.png

资料领取步骤

1、关注,转发

2、私信发送:电子书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

markdown如何设置图片大小_不会吧,还不会用markdown排版吗

请使用 Chrome 浏览器。请阅读下方文本熟悉工具使用方法,本文可直接拷贝到微信中预览。1 Markdown Nice 简介支持自定义样式的 Markdown 编辑器支持微信公众号、知乎和稀土掘金欢迎扫码回复「排版」加入用户群2 主题https://preview.mdnice.com/themes/欢迎提交主题…

此次边路调整系统推荐射手走哪路_王者荣耀地图重大对称改动,终于能射手对射手,上单对上单了...

兄弟萌,一直困扰大家的地图问题终于要改了,王者峡谷将在今年的周年庆版本,迎来一次玩法体验的大升级!调整介绍我们将尝试改造边路的地形&资源,促进更合理的同职业分路对线。以往通过职业、英雄的调整确实很难实质改…

二阶振荡环节的谐振频率_困惑了很久的串联/并联谐振电路详解

在含有电阻、电感和电容的交流电路中,电路两端电压与其电流一般是不同相的,若调节电路参数或电源频率使电流与电源电压同相,电路呈电阻性,称这时电路的工作状态为谐振。谐振现象是正弦交流电路的一种特定现象,它在电子…

安装不成功_iOS12.4.1 安装失败?教你百分百不掉签

说重点:近日,苹果频繁封杀证书,导致企业证书很缺,补上又封,想越狱又不能安装,实在困扰了很久,今天就分享百分百安装成功的方法,安装后配合自动续签插件,简直完美。接下来…

指定的参数已超出有效值的范围_整流二极管的特性和重要参数

一、 二极管的半导体原理略二、 二极管的特性曲线研究电路也有两种方法,一个是从它的内部工作原理去分析,另一个是从它表现出的外部特征去分析,把电路看成一个黑匣子,不管它内部什么结构什么原理,只研究它表现出来的特…

count返回0_MySQL实战 | 14 为什么count(*)越来越慢?

select count(*) 应该是一个比较常用的语句,用来统计记录行数。但是,慢慢地你会发现,这个语句越来越慢了,为什么呢?count(*) 的实现方式首先,我们来看下它的实现方式。MySQL 中,不同的存储引擎&…

sql管理:索引超出范围必须为非负值并小于集合大小_java面试基础知识-数据库基础知识(数据库索引部分)...

1.1数据库架构:如何设计一个关系型数据库?存储模块(文件系统)用块或者页作为存储单位 程序实例:存储管理缓存机制 不宜过大,要有淘汰机制SQL解析日志管理权限划分容灾机制索引管理锁管理1.2 索引为什么要使用索引&…

编译原理语法分析_斯坦福大学《编译原理》学习记录 - 第二章:语法分析器

05-01: Introduction to Parsing 语法分析parser的作用:05-02: Context Free Grammars 上下文无关文法CFG(上下文无关文法)回答了一个字符串是否属于某语言:CFG的组成:终止符非终止符开始符生成式生成式production &am…

mysql永远不用utf8_永远不要在 MySQL 中使用「utf8」

题图:by apple from Instagram本文出自极客邦「聊聊架构」公众号的编译。我自己当年也被这个问题坑过,当时并没有如此详细的分析文章。我觉得有责任再次分享一下,让更多人知道这个事情。程序员不帮助程序员,还能指望谁呢&#xff…

sqoop mysql parquet_Sqoop抽取Hive Parquet表数据到MySQL异常分析

温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。Fayson的github:https://github.com/fayson/cdhproject1.问题描述在CDH集群中我们需要将Hive表的数据导入到RDBMS数据库中,使用Sqoop工具可以方便的将Hive表数据抽取…

mysql架设_主从mysql架设

主从mysql架设二进制安装mysqltar xvf mysql-5.1.46-linux-i686-glibc23.tar -C /usr/localcd /usr/localln -sv mysql-5.1.46-linux-i686-glibc23.tar mysqlcd mysqlgroupadd mysqluseradd -g mysql -s /sbin/nologin -M -r mysqlmkdir /mysql/datachown -R mysql.mysql /mysq…

日志文件和mysql同步到kafka_logstash_output_kafka:Mysql 同步 Kafka 深入详解

0、题记实际业务场景中,会遇到基础数据存在 Mysql 中,实时写入数据量比较大的情景。迁移至kafka是一种比较好的业务选型方案。而mysql写入kafka的选型方案有:方案一:logstash_output_kafka 插件。方案二:kafka_connect…

java 命令行参数 _java命令行参数

原标题:java命令行参数命令行参数就是main方法里面的参数String[] args他就是一个数组,args只是数据类型的一个名称,就是一个数组的变量,名称无所谓,类型没变就行了。这个就是程序的入口点。如图7.4所示:图…

java 最小生成树_图的最小生成树(java实现)

1.图的最小生成树(贪心算法)我两个算法的输出都是数组表示的,当前的索引值和当前索引对应的数据就是通路,比如parent[2] 5;即2和5之间有一个通路,第二个可能比较好理解,第一个有点混乱是什么?将一个有权图中的 所有顶…

java 自定义注解 生成json_用自定义注解实现fastjson序列化的扩展

这篇文章起源于项目中一个特殊的需求。由于目前的开发方式是前后端分离的,基本上是通过接口提供各个服务。而前两天前端fe在开发中遇到了一些问题:他们在处理字符串类型的时间时会出现精度丢失的情况,所以希望后台是以时间戳的形式返回给前端…

工厂模式 java场景_研磨设计模式之简单工厂模式(场景问题)

简单工厂不是一个标准的设计模式,但是它实在是太常用了,简单而又神奇,所以还是需要好好掌握的,就当是对学习设计模式的热身运动吧。为了保持一致性,我们尽量按照学习其它模式的步骤来进行学习。1 场景问题大家都知道&…

java asm jndi_GitHub - Q1ngShan/JNDI: JNDI 注入利用工具

JNDI 注入利用工具介绍本项目为 JNDI 注入利用工具,生成 JNDI 连接并启动后端相关服务,可用于 Fastjson、Jackson 等相关漏洞的验证。本项目是基于 welk1n 的 JNDI-Injection-Exploit,在此项目的基础服务框架上,重新编写了攻击利用…

java中fis和fos_java中-的流-与操作

/*字节输出流 OutputStrema:* OutputStream抽象类* write(int b); 将指定的字节写入此流中* write(byte[] b); 将指定的数组 输入此流中* write(byte[] b , int a , int c); 将指定的数组输入此流中 从a索引开始 获取c 个* close(); 将此流关闭 并释放资源* fl…

yolov4用1050ti_简单粗暴的多目标跟踪神器 – DeepSort

目标跟踪问题一直是计算机视觉的热点任务之一,简单的可以分为单目标跟踪与多目标跟踪,最常见的目标跟踪算法都是基于检测的跟踪算法,首先发现然后标记,好的跟踪算法必须具备REID的能力。今天小编斗胆给大家推荐一个结合传统算法跟…

类java的步骤_java类加载的过程

类加载就是三个过程:加载、链接、初始化链接又可以分为验证、准备、解析1.加载将class字节码文件通过类加载器装入内存中2.验证确保当前class文件的字节流所包含的内容符合当前JVM的规范要求,并且不会出现危害JVM自身安全的代码,当前字节流不…