【Java面试】三、Redis篇(下)
文章目录
- 1、抢券场景
- 2、Redis分布式锁
- 3、Redisson实现分布式锁
- 4、Redisson实现的分布式锁是可重入锁
- 5、Redisson实现分布式锁下的主从一致性
- 6、面试
1、抢券场景
正常思路:

代码实现:

比如优惠券数量为1。正常情况下:用户A的请求过来(对应线程1),查库存,抢券、改库存,然后用户B也来请求(对应线程2),继续查库存,抢券,此时,库存为0,抢券失败,没问题。

但既然是抢券,就不会一个请求一个请求的来,并发下,线程必然交替执行。

线程1查完库存,num=1,挂起,同时线程2执行,查库存,num=1,此时,线程2被挂起,线程1抢完券,改库存减一,库存为0。线程2继续执行,其挂起前查的num为1,也去扣减库存,此时,就会超卖。先考虑加锁,因为是并发抢夺同一个资源:

时序图:

如此,就解决了问题。但生产环境,一般不是单节点部署,如果抢券接口所在的微服务被部署在了三个节点或者实例上,这三个实例对应三个JVM

此时,线程1、2的请求被路由到8080的实例,线程3、4的请求被路由到8081的实例,则线程1和线程3都能获取到互斥锁。因为:代码里获取的synchronize锁属于本地锁,这个锁是属于JVM里的,现在一份代码跑在多个实例中,每个实例都启动了一个JVM。也就是说,synchronize能解决通一个JVM下的互斥,但解决不了多个JVM下的互斥,所以,集群下,不能使用本地锁来实现了,要用一个外部的锁

由此,引入分布式锁(超出JVM之外的外部锁):

2、Redis分布式锁
Redis实现分布式锁,依靠setnx命令,setnx即set if not exists,不存在就set:
//获取锁,NX是互斥,EX是设置超时时间
SET lock value NX EX 10
//释放锁,删除即可
DEL key
通过set来获取锁时,之所以设置过期时间,倒不是担心发生异常,导致锁释放失败,这个可以try-finally,如果不是异常,而是获取锁后服务器宕机,则这个锁永远不会被释放。

但这个超时时间如何控制,根据业务时间估算是不靠谱的,考虑开个线程:如果业务还在执行的话,就去给锁续期 ⇒ 关于这个思想的落地:redission
3、Redisson实现分布式锁
和单纯的setnx相比,Redisson除了加锁,还会单开一个线程(看门狗)去给锁续期,没releaseTime/3做一次续期,releaseTime即锁的超时时间,默认30秒。即watch dog线程每10秒给持有分布式锁的线程做一次续期,将其重置为默认的30秒。最后线程释放分布式锁的时候,通知对应的watch dog线程,不用再做监听了。

此外,线程A持有分布式锁的时候,线程B再来尝试获取锁,如果获取失败,会while循环尝试加锁,循环次数达到阈值后,还没获取成功,则返回获取锁失败。

代码实现:
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.16.3</version> <!-- 替换需要的版本号 -->
</dependency>
@Resource
private RedissonClient redissonClient;public void redissonLock() {//获取锁(重入锁)RLock lock = redissonClient.getLock("your-key");try {//tryLock方法重载,形参1为获取锁的最大等待时间,形参2为锁超时释放时间,形参3为时间单位boolean isLock = lock.tryLock(10, TimeUnit.SECONDS);//注意下面,如果传了锁超时释放时间,则watch dog机制失效,redisson认为你自己可以控制超时时间,不传或传-1,则有看门狗续期//boolean isLock = lock.tryLock(10, 30, TimeUnit.SECONDS);//获取锁成功if (isLock) {System.out.println("执行业务");}} catch (InterruptedException e) {//打印必要的loge.printStackTrace();} finally {//释放锁lock.unlock();}
}
最后,以上加锁、设置过期时间灯操作是基于Lua脚本完成,原子性有保证
4、Redisson实现的分布式锁是可重入锁
redisson实现的分布式锁是可重入锁:
public void add1(){RLock lock = redissonClient.getLock("your-key");boolean isLock = lock.tryLock();//执行业务add2();//释放锁lock.unlock();
}public void add2(){RLock lock = redissonClient.getLock("your-key");boolean isLock = lock.tryLock();//执行业务//释放锁lock.unlock();
}
判断是同一个线程ID,就可重入,内部用hash结构记录线程ID和可重入的次数

5、Redisson实现分布式锁下的主从一致性
Java应用尝试获取分布式锁(Set lock xx)到master节点,线程获取锁成功,正常接下来应该主从同步。

若此时master宕机,没来得及同步到slave,然后主从故障转移,从slave中选出一个新的master,线程2又来获取锁,此时,对新的master,自然可以set成功,即获取分布式锁成功,如此,就出现了两个线程同时获取到了分布式锁。

针对这个问题,刚第一反应是等同步到slave了再返回写入成功,即抢锁成功,但这样也性能太差了,没意义了。 ⇒ 红锁方案:红锁即ReadLock,指不能只在一个redis实例上创建锁,应该在(n/2+1)个节点上创建锁成功(n为Redis节点的数量),但这样Redis集群运维难度大、性能差,也有局限性,不推荐。

最后,Redis集群优先是AP,即高可用,如果需要数据的强一致性,那可使用zookeeper来实现分布式锁
6、面试


相关文章:
【Java面试】三、Redis篇(下)
文章目录 1、抢券场景2、Redis分布式锁3、Redisson实现分布式锁4、Redisson实现的分布式锁是可重入锁5、Redisson实现分布式锁下的主从一致性6、面试 1、抢券场景 正常思路: 代码实现: 比如优惠券数量为1。正常情况下:用户A的请求过来&a…...
GpuMall智算云:QwenLM/Qwen1.5/Qwen1.5-7B-Chat
Qwen 是阿里巴巴集团 Qwen 团队的大型语言模型和大型多模态模型系列,现在大型语言模型已经升级到 Qwen1.5 版本。 GpuMall智算云 | 省钱、好用、弹性。租GPU就上GpuMall,面向AI开发者的GPU云平台 无论是语言模型还是多模态模型,都在大规模的多语言和多模…...
CentOS6.5 下编译 FreeSWITCH 1.2.23 版本
命题作文,慢慢来,一边做,一边记录。 老古董了,查资料很不容易,但朋友说不着急,这很好。 生命的意义在于折腾,不是吗? 先下载 CentOS6.5, 查了下资料,最后…...
2024年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 在Python中,hex(2023)的功能是?( ) A:将十进制数2023转化成十六进制数 B:将十进制数2023转化成八进制数 C:将十六进制数2023转化成十进制数 D:将八进制数2023转化成十进制数 答案:A …...
Redis篇 数据的编码方式和单线程模型
编码方式和单线程模型 一.redis中的数据类型二. Redis中查询编码方式命令三. 单线程模型四. 经典面试题,redis为何这么快?什么是IO多路复用? 一.redis中的数据类型 在redis中,数据类型大致分为5种 1.字符串类型 2.哈希 3.列表 4.集合 5.有序集合 redis底层在实现这些数据结构…...
(delphi11最新学习资料) Object Pascal 学习笔记---第13章第4节 (内存管理和接口)
13.4 内存管理和接口 在第11章中,我介绍了接口的内存管理的关键要素。与对象不同,接口是受管理且具有引用计数。如我所提到的,接口引用会增加所引用对象的引用计数,但您可以声明接口引用为弱引用以禁用引用计数(但…...
【记录贴】docker镜像格式报错
1,错误内容 最近想要补一补docker的基础知识,跟着练习的时候,发现下面的错误。 换了其他镜像(docker pull ubantu)也存在同样的问题: 错误内容:docker: mediaType in manifest should be appli…...
设计模式 19 模板模式 Template Pattern
设计模式 19 模板模式 Template Pattern 1.定义 模板模式(Template Pattern)是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的具体实现延迟到子类中。在模板模式中,定义了一个抽象类,其中包含了一个…...
PHP如何实现实时计算使用者消耗服务器资源费用?
最近几天遇到一个客户,提出一个很有意思的东西!当然客户的项目方案这里不方便说,这里就假定客户的项目是腾讯云?哈哈哈哈哈 以前客户的收费方案是按月、按季度、按年收费,现在半路杀出了很多程咬金,导致之前的收费方案有点儿贵,没啥性价比,那就搞一个看起来很“便宜”…...
在C++中自定义命名空间,在命名空间中定义string变量,同时定义一个函数实现单词逆置
代码 #include <iostream> #include <cstring> using namespace std; namespace my_space {string s;void reverse(string s);//定义逆置函数 } using namespace my_space; void my_space::reverse(string s){int lens.size();int i0;int jlen-1;while(i<j){//…...
【leetcode 141】环形链表——快慢指针(龟兔赛跑)
给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(…...
容器(Container)的详细介绍
容器,作为现代软件开发和部署的核心技术之一,已经成为云计算、微服务架构等领域的基石。容器技术通过提供轻量级的虚拟化环境,实现了应用程序的快速部署、迁移和扩展,极大地提高了软件开发的效率和灵活性。本文将详细介绍容器的概…...
Python 网格变换之平移、旋转、缩放、变换矩阵
网格变换 一、平移1.1、代码示例1.2、结果示例二、旋转2.1、代码示例2.2、结果示例三、缩放3.1、代码示例3.2、结果示例四、变换矩阵4.1、代码示例4.2、结果示例一、平移 网格平移:将网格沿着特定的方向移动一段距离。 1.1、代码示例...
推荐10款优秀的组件库(一)
1.Ant Desgin UI 网址: https://ant-design-mobile.antgroup.com/zh Ant Design - 一套企业级 UI 设计语言和 React 组件库 "Ant Design Mobile"是一个在线的移动端Web体验平台,让你探索移动端Web的体验极限。 添加图片注释,不…...
freertos的信号量和互斥锁学习笔记
freertos的信号量和互斥锁有两个比较形象的例子可以解释两者的主要用途。 第一个是信号量: 使用信号量的最初目的是为了给共享 资源建立一个标志,该标志表示该共享资源被占用情况。这样,当一个任务在访问共享资源之前,可以先对这…...
C++基础——vector的详解与运用
vector的介绍 文档介绍 vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,…...
const指针,星号判断方法
一 示例代码 1. const char *p // 指向常量的指针 2. char const *p // 指向常量的指针 3. char * const p // 指针常量二 判断方法 const在星号左边,指向常量的指针,指针p可修改。 const在星号右边,指针常量,指针p不可修改。...
移动摄像头专网需要解vlan,如何解决
🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…...
5.27周报
这两周邻近毕业故没有很多时间来学习课余内容,另外最近身体有些不舒服【偏头痛】,所以学的内容不多,包括SVM向量机和ResNet【不包括代码复现】 1.SVM支持向量机的大概内容 1、目的: 主要内容是如何找到分类的那条线【超平面】—…...
C-数据结构-树状存储的基本实现
/* 理解和记忆递归的关键在于把握递归的本质和函数调用的过程。递归函数在每次调用时会把当前状态压入调用栈,直到满足终止条件后开始回溯。理解基准条件和递归步骤:每个递归函数都需要有基准条件(如节点为空时返回),并…...
【Python 3.14 JIT性能调优权威指南】:20年CPython核心开发者亲授3大接入瓶颈突破法
第一章:Python 3.14 JIT编译器的演进脉络与接入价值Python 3.14 引入了实验性但高度集成的内置 JIT(Just-In-Time)编译器,标志着 CPython 运行时首次在官方发行版中提供可生产级启用的动态编译能力。该 JIT 并非独立运行时或第三方…...
英语祈使句结构
英语祈使句:极简结构 + 直白例句(一看就懂) 核心: 主语一律省略(默认 You 你 / 你们),直接用动词开头,用来命令 / 请求 / 禁止 一、基础核心结构(3 种万能模板) 1 肯定祈使句(直接让做某事) 结构:动词原形 + 其他成分(宾语 / 状语) 例句: Open the door.…...
intv_ai_mk11部署教程:公网IP+端口直连的安全加固方案(反向代理+访问限流)
intv_ai_mk11部署教程:公网IP端口直连的安全加固方案(反向代理访问限流) 1. 环境准备与快速部署 1.1 系统要求 操作系统:Ubuntu 20.04/22.04 LTSGPU:NVIDIA显卡(至少16GB显存)内存࿱…...
Selenium—xpath定位方法
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 今天我们来聊聊selenium -- xpath定位方法,我们都知道selenium有八大定位策略分别是id、name、class name、tag name、link text、partial link text、…...
Stable Yogi Leather-Dress-Collection企业应用:服装品牌AI趋势图快速验证系统
Stable Yogi Leather-Dress-Collection企业应用:服装品牌AI趋势图快速验证系统 1. 项目概述 Stable Yogi Leather-Dress-Collection是一款专为服装品牌设计的AI趋势图快速验证工具,基于先进的Stable Diffusion技术开发。这个工具能够帮助设计师和品牌快…...
Netty-learning-example数据持久化实战:JPA+MySQL与MyBatis+MongoDB对比
Netty-learning-example数据持久化实战:JPAMySQL与MyBatisMongoDB对比 【免费下载链接】netty-learning-example :egg: Netty实践学习案例,见微知著!带着你的心,跟着教程。我相信你行欧。 项目地址: https://gitcode.com/gh_mir…...
awesome-rust数据备份恢复:灾难恢复与业务连续性
awesome-rust数据备份恢复:灾难恢复与业务连续性 数据丢失可能导致项目停滞、业务中断甚至经济损失。在开源项目管理中,建立完善的数据备份与灾难恢复机制是保障业务连续性的关键。本文将介绍如何利用awesome-rust中精选的Rust工具构建可靠的备份恢复系…...
图卷积网络代码规范:PyGCN项目Python风格与最佳实践终极指南
图卷积网络代码规范:PyGCN项目Python风格与最佳实践终极指南 【免费下载链接】pygcn Graph Convolutional Networks in PyTorch 项目地址: https://gitcode.com/gh_mirrors/py/pygcn 图卷积网络(Graph Convolutional Networks, GCN)是…...
新手入门Windows驱动开发:从快马生成ahflt.sys示例代码开始
今天想和大家分享一下我最近学习Windows驱动开发的小心得。作为一个刚接触系统编程的新手,我发现ahflt.sys这个系统文件是个不错的切入点。通过InsCode(快马)平台,我快速生成了一个简单的驱动示例,下面就把这个学习过程记录下来。 驱动开发基…...
哈尔滨工业大学学位论文latex模板下载及编译方法
1、下载文件夹chinese:https://download.csdn.net/download/wzz110011/92774930?spm1011.2124.3001.6210 2、安装TexStudio 3、设置TexStuidio编译器为XeLaTex,具体设置方法可百度...
