当前位置: 首页 > news >正文

【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、抢券场景 正常思路&#xff1a; 代码实现&#xff1a; 比如优惠券数量为1。正常情况下&#xff1a;用户A的请求过来&a…...

GpuMall智算云:QwenLM/Qwen1.5/Qwen1.5-7B-Chat

Qwen 是阿里巴巴集团 Qwen 团队的大型语言模型和大型多模态模型系列&#xff0c;现在大型语言模型已经升级到 Qwen1.5 版本。 GpuMall智算云 | 省钱、好用、弹性。租GPU就上GpuMall,面向AI开发者的GPU云平台 无论是语言模型还是多模态模型&#xff0c;都在大规模的多语言和多模…...

CentOS6.5 下编译 FreeSWITCH 1.2.23 版本

命题作文&#xff0c;慢慢来&#xff0c;一边做&#xff0c;一边记录。 老古董了&#xff0c;查资料很不容易&#xff0c;但朋友说不着急&#xff0c;这很好。 生命的意义在于折腾&#xff0c;不是吗&#xff1f; 先下载 CentOS6.5&#xff0c; 查了下资料&#xff0c;最后…...

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章中&#xff0c;我介绍了接口的内存管理的关键要素。与对象不同&#xff0c;接口是受管理且具有引用计数。如我所提到的&#xff0c;接口引用会增加所引用对象的引用计数&#xff0c;但您可以声明接口引用为弱引用以禁用引用计数&#xff08;但…...

【记录贴】docker镜像格式报错

1&#xff0c;错误内容 最近想要补一补docker的基础知识&#xff0c;跟着练习的时候&#xff0c;发现下面的错误。 换了其他镜像&#xff08;docker pull ubantu&#xff09;也存在同样的问题&#xff1a; 错误内容&#xff1a;docker: mediaType in manifest should be appli…...

设计模式 19 模板模式 Template Pattern

设计模式 19 模板模式 Template Pattern 1.定义 模板模式&#xff08;Template Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤的具体实现延迟到子类中。在模板模式中&#xff0c;定义了一个抽象类&#xff0c;其中包含了一个…...

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 &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;…...

容器(Container)的详细介绍

容器&#xff0c;作为现代软件开发和部署的核心技术之一&#xff0c;已经成为云计算、微服务架构等领域的基石。容器技术通过提供轻量级的虚拟化环境&#xff0c;实现了应用程序的快速部署、迁移和扩展&#xff0c;极大地提高了软件开发的效率和灵活性。本文将详细介绍容器的概…...

Python 网格变换之平移、旋转、缩放、变换矩阵

网格变换 一、平移1.1、代码示例1.2、结果示例二、旋转2.1、代码示例2.2、结果示例三、缩放3.1、代码示例3.2、结果示例四、变换矩阵4.1、代码示例4.2、结果示例一、平移 网格平移:将网格沿着特定的方向移动一段距离。 1.1、代码示例...

推荐10款优秀的组件库(一)

1.Ant Desgin UI 网址&#xff1a; https://ant-design-mobile.antgroup.com/zh Ant Design - 一套企业级 UI 设计语言和 React 组件库 "Ant Design Mobile"是一个在线的移动端Web体验平台&#xff0c;让你探索移动端Web的体验极限。 添加图片注释&#xff0c;不…...

freertos的信号量和互斥锁学习笔记

freertos的信号量和互斥锁有两个比较形象的例子可以解释两者的主要用途。 第一个是信号量&#xff1a; 使用信号量的最初目的是为了给共享 资源建立一个标志&#xff0c;该标志表示该共享资源被占用情况。这样&#xff0c;当一个任务在访问共享资源之前&#xff0c;可以先对这…...

C++基础——vector的详解与运用

vector的介绍 文档介绍 vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;…...

const指针,星号判断方法

一 示例代码 1. const char *p // 指向常量的指针 2. char const *p // 指向常量的指针 3. char * const p // 指针常量二 判断方法 const在星号左边&#xff0c;指向常量的指针&#xff0c;指针p可修改。 const在星号右边&#xff0c;指针常量&#xff0c;指针p不可修改。...

移动摄像头专网需要解vlan,如何解决

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…...

5.27周报

这两周邻近毕业故没有很多时间来学习课余内容&#xff0c;另外最近身体有些不舒服【偏头痛】&#xff0c;所以学的内容不多&#xff0c;包括SVM向量机和ResNet【不包括代码复现】 1.SVM支持向量机的大概内容 1、目的&#xff1a; 主要内容是如何找到分类的那条线【超平面】—…...

C-数据结构-树状存储的基本实现

/* 理解和记忆递归的关键在于把握递归的本质和函数调用的过程。递归函数在每次调用时会把当前状态压入调用栈&#xff0c;直到满足终止条件后开始回溯。理解基准条件和递归步骤&#xff1a;每个递归函数都需要有基准条件&#xff08;如节点为空时返回&#xff09;&#xff0c;并…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...