黑马Java面试笔记之Redis篇(分布式锁)

article/2025/8/10 4:34:03

面试题

我看你做的项目中,都用到了redis,你在最近的项目中那些场景使用了redis呢

         如果回答了分布式锁,那么就会有以下这个问题

redis分布式锁,是如何实现的?

 需要结合项目中的业务进行回答,通常情况下,分布式锁使用的场景

集群情况下的定时任务、枪单、幂等性场景

案例

以下设置一个抢券场景

抢券执行流程

        当线程1查询优惠券时,查到还有一张,当进行查询库存是否充足时,线程2也进行查询,此时线程2也可以查到一张优惠券,线程1和线程2同时减1,咋会出现超卖情况

如果项目是单体项目,并且只启动一台服务,加synchronized锁可以解决这个问题,如下

但是为了支持更多的并发请求,往往会把项目进行集群部署,即将代码部署到多台服务器上,如果使用集群部署的话,再使用synchronized锁就会出现问题

         synchronized锁是本地的锁,属于gvm,每个服务都有各自的gvm,只能解决同一个gvm下线程的互斥,解决不了多个gvm下线程的互斥,所以在集群情况下,就不能使用本地的锁来解决了

只能使用外部的锁来解决,即分布式锁,Redis就可以作为分布式锁

一. Redis分布式锁

        Redis实现分布式锁主要利用Redis的setnx命令。setnx时SET if not exists(如果不存在 ,则AET)的简写。

这里面试官有可能就问了

这里有两种方案,一种是根据业务执行时间预估,一种是给锁续期

根据业务执行时间预估是不可行的,如果出现卡顿等问题,都会导致业务执行时间变慢;

第二种给锁续期也就是redisson实现的分布式锁,以下是执行流程(问的比较多)

如果面试官问:

使用redisson实现的分布式锁是否可以重入?

 同一个线程是可以重入的,不是同一个线程则不可以重入

redisson实现的分布式锁能保证主从数据一致性吗?

 使用RedLock红锁保证分布式锁的主从一致性

但是红锁是由缺点的,实现复杂,性能差,运维繁琐,所以使用的很少。

 总结

面试官:Redis分布式锁如何实现?

候选人:在redis中提供了一个命令setnx(SET if not exists)

        由于redis是单线程的,用了命令之后,只能有一个客户端对某一个key设置值,在没有过期或者删除key的时候是其他客户端不能设置这个key的

面试官:好的,那你如何控制Redis实现分布式锁的有效时长呢?

候选人:嗯,的确,redis的setnx指令不好控制这个问题,我们当时采用的redis的一个框架redisson实现的。

        在redisson中需要手动加锁,并且可以控制锁的失效时间和等待时间,当锁住的一个业务还没有执行完成的时候,在redisson中引入了一个看门狗机制,就是说每隔一段时间就检查当前业务是否还持有锁,如果持有就增加加锁的持有时间,当业务完成之后需要使用释放锁就可以了

       还有一个好处就是 在高并发下,一个业务有可能会执行很快,先客户1持有锁的时候,客户2来了以后并不会马上拒绝,他会自选不断尝试获取锁,如果客户1释放之后,客户2就可以马上持有锁,性能也得到了提升。

面试官:好的,redisson实现的分布式锁是可重入的吗?

候选人:嗯,是可重入的。这样做是为了避免死锁的产生。这个重入其实在内部就是判断是否是当前线程持有的锁,如果是当前线程持有的锁就会计数,如果释放锁就会在计算上减一。在存储数据的时候采用hash结构,大key可以按照自己的业务进行定制,其中小key是当前线程的唯一标识,value是当前线程重入的次数

面试官:redisson实现的分布式锁能解决主从一致性问题吗?

候选人:这个是不能的,但是可以使用redisson提供的红锁来解决,但是这样的话,性能就太低了,如果业务中非要保证数据的强一致性,建议采用zookeeper实现的分布式锁


还有一些redis其他的面试问题,这些问题可能跟业务没啥关系,但是仍是一些高频面试问题

二. Redis集群方案

Redis集群有哪些方案,知道吗?

 在Redis中提供集群方案总共有三种

  • 主从复制
  • 哨兵模式
  • 分片集群

在集群中其他的面试问题有以下几个

2.1 主从复制

特点:单节点Redis的并发能力是有上限的,要进一步提高redis的并发能力,就需要搭建主从集群,实现读写分离

主从数据同步原理

主从全量同步

主从增量同步

 总结

2.2 哨兵模式

作用:Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵结构和作用如下

极大保障redis主从的高可用

服务状态监控

        Sentinel基于心跳机制检测服务状态,每隔一秒向集群的每个实例发送ping命令:

  • 主管下线:如果sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

哨兵模式会出现脑裂问题

        这是一个正常结合哨兵模式的主从架构

         此时由于网络问题,主节点master和哨兵模式处在不同分区,此时哨兵只能检测从节点,检测不了主节点

         当网络恢复后

解决方案如下: 

 总结

 

 2.3 分片集群

主从和哨兵可以解决高可用,高并发读的问题。但是仍然有两个问题没有解决:

  • 海量数据存储问题
  • 高并发写的问题

使用分片集群可以解决上述问题,分片集群的特征:

  • 集群中有多个master,每个master保存不同数据
  • 每个master都可以有多个slave节点
  • master之间通过ping检测彼此健康状态
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

 分片集群结构-数据读写

        Redis分片集群引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模解决放置哪个槽,集群的每一个节点负责一部分hash槽。

 总结

 

面试官:redis的分片集群有什么作用?

候选人:分片集群主要解决的是,海量数据存储的问题,集群中有多个master,每个master保存不同数据,并且还可以给每一个master设置多个slave节点,就可以继续增大集群的高并发能力。同时每个master之间通过ping检测彼此健康状态,就类似于哨兵模式了。当客户端请求可以访问集群任意节点,最终都会被转发到正确节点

面试官:Redis分片集群中数据是怎么存储和读取的?

候选人:嗯,在redis集群中是这样的

        Redis集群引入了哈希槽的概念,有16384个哈希槽,集群中每个主节点绑定了一定范围的哈希槽范围,key通过CRC16校验后对16384取模来决定放置哪个槽,通过槽找到对应的节点进行存储。

        取值的逻辑是一样的。


三.其他面试问题

Redis是单线程的,但是为什么还那么快?

  •  Redis是纯内存操作,执行速度非常快
  • 采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题
  • 使用I/O多路复用模型,非阻塞IO

能解释一下I/O多路复用模型吗

         Redis是纯内存操作,执行速度非常快,他的性能瓶颈是网络延迟而不是执行速度,I/O多路复用模型主要就是实现了搞笑的网络请求

  • 用户空间和内核空间
  • 常见的IO模型
    • 阻塞IO(Blocking IO)
    • 非阻塞IO(Nonblocking IO)
    • IO多路复用(IO Multiplexing)
  • Redis网络模型

3.1 用户空间和内核空间

 3.2 阻塞IO(Blocking IO)

 3.3 非阻塞IO(Nonblocking IO)

 3.4 IO多路复用(IO Multiplexing)

        IO多路复用是利用单个线程来同时监听多个Socket,并在某个Socket可读,可写时得到通知,从而避免无效的等待,充分利用CPU资源。不过监听Socket的方式,通知的方式又有多种实现,常见的有:

  • select
  • poll
  • epoll

三者是有差异的

 3.4 Redis网络模型

        Redis通过IO多路复用来提高网络性能,并且支持各种不同的多路复用实现,并且将这些实现进行封装,提供了统一的高性能事件库

 总结

能解释一下I/O多路复用模型吗?

面试官:Redis是单线程的,为什么还那么快?

候选人:嗯,这个有几个原因

        1.完全基于内存,C语言编写

        2. 采用单线程,避免不必要的上下文切换可竞争条件

        3.使用多路I/O复用模型,非阻塞IO

        例如:bgsave和bgrewriteaof都是在后台执行操作,不影响主线程的正常使用,不会产生阻塞。

面试官:能解释一下I/O多路复用模型?

候选人:嗯,I/O多路复用是指利用单个线程来同时监听多个Socket,并在某个Socket可读,可写时得到通知,从而避免无效的等待,充分利用CPU资源。目前的I/O多路复用都是采用的epoll模式实现,他会在通知用户进程Socket就绪的同时,把已就绪的Socket写入用户空间,不需要挨个遍历Socket来判断是否就绪,提升了性能。

        其中Redis的网络模型就是使用I/O多路复用结合事件的处理器来应对多个Socket请求,比如,提供了连接应答处理器,命令回复处理器,命令请求处理器。

        在Redis6.0之后,为了提升更好的性能,在命令回复处理器使用了多线程来处理回复事件,在命令请求处理器中,将命令的转换使用了多线程,增加命令转换速度,在命令执行的时候,依然是单线程


http://www.hkcw.cn/article/FNWeyCvFaV.shtml

相关文章

建筑兔零基础python自学记录102|Beautiful Soup库(1)-15

1、安装Beautiful Soup 2、使用测试网页获取源代码 This is a python demo page a)法1:直接网页右键获取 b)法2:request库 import requests rrequests.get(https://python123.io/ws/demo.html) print(r.text) 3、使用Beautiful Soup库 同样解析出了源…

【Java学习笔记】枚举

枚举(enum) 一、基本介绍 引出关键字:enum,全称为enumerate 枚举是一组常量集合 理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象 二、使用场景 当一个类的属性有限定条件时(例如一个星期只能有七天&…

FFmpeg学习笔记

1. 播放器的架构 2. 播放器的渲染流程 3. ffmpeg下载与安装 3.0 查看PC是否已经安装了ffmpeg ffmpeg 3.1 下载 wget https://ffmpeg.org/releases/ffmpeg-7.0.tar.gz 3.2 解压 tar zxvf ffmpeg-7.0.tar.gz && cd ./ffmpeg-7.0 3.3 查看配置文件 ./configure …

buuctf-web

[极客大挑战 2019]Havefun 控制台检查代码修改url [极客大挑战 2019]EasySQL 密码输入 出现 sql输入错误 判断为 单引号注入 [ACTF2020 新生赛]Include 点击提示出现?file说明是文件包含问题 构造url filephp://filter/readconvert.base64-encode/resourceflag.php php:…

SAR ADC 异步逻辑设计

SAR ADC的逻辑是重要的一个模块,可以分为同步逻辑和异步逻辑,对于低速SAR ADC,一般采用同步逻辑,对于高速SAR ADC,一般采用异步逻辑。 这里讲一下异步逻辑的设计,异步逻辑一般不需要外部时钟(当…

广告拦截器:全方位拦截,畅享无广告体验

在数字时代,广告无处不在。无论是浏览网页、使用社交媒体,还是观看视频,广告的频繁弹出常常打断我们的体验,让人不胜其烦。更令人担忧的是,一些广告可能包含恶意软件,威胁我们的设备安全和个人隐私。AdGuar…

MMRL: Multi-Modal Representation Learning for Vision-Language Models(多模态表示学习)

摘要 预训练的VLMs,对于跨任务的迁移学习至关重要,然而,在few-shot数据集上微调会导致过拟合,降低在新任务上的性能。为解决这个问题,提出一种新的多模态表征学习框架(MMRL),该框架引入了一个共享、可学习…

【芯片学习】555

一、引脚作用 二、原理图 三、等效原理图 1.比较器 同相输入端大于反相输入端,输出高电平,反之亦然 2.三极管 给它输入高电平就可以导通 3.模拟电路部分 4.数字电路部分 这部分的核心是RS触发器,R-reset代表0,set是置位代表1&am…

从线性代数到线性回归——机器学习视角

真正不懂数学就能理解机器学习其实是个神话。我认为,AI 在商业世界可以不懂数学甚至不懂编程也能应用,但对于技术人员来说,一些基础数学是必须的。本文收集了我认为理解学习本质所必需的数学基础,至少在概念层面要掌握。毕竟&…

DAY 36 超大力王爱学Python

仔细回顾一下神经网络到目前的内容,没跟上进度的同学补一下进度。 作业:对之前的信贷项目,利用神经网络训练下,尝试用到目前的知识点让代码更加规范和美观。探索性作业(随意完成):尝试进入nn.Mo…

【Oracle】数据备份与恢复

个人主页:Guiat 归属专栏:Oracle 文章目录 1. Oracle备份恢复概述1.1 为什么备份这么重要?1.2 Oracle备份策略全景图 2. 物理备份详解2.1 冷备份 - 最简单粗暴的方式2.1.1 冷备份的步骤2.1.2 冷备份恢复过程 2.2 热备份 - 不停机的备份艺术2.…

使用BERT/BiLSTM + CRF 模型进行NER进展记录~

使用代码处理数据集,发现了一些问题,以及解决办法~ 下载了一组数据集,数据存放在CSV中,GBK格式。如下: 首先对每一列直接进行NER抽取,结果非常不好: 几乎是乱抽取的,解决办法是自己创…

18. Qt系统相关:多线程

一、概述 在Qt中,使用QThread类对系统线程进行了封装。QThread代表一个在应用程序中可独立控制的线程,也可以和进程中的其他线程共享数据。 二、QThread常用API 三、QThread使用 自定义一个类,继承自QThread,并且只有一个线程处…

YOLOv7 辅助检测头与重参数化解析2025.6.1

YOLOv7 是目标检测领域的一个重要模型,其在速度和精度之间取得了较好的平衡。其中的**辅助检测头(Auxiliary Head)和重参数化(Re-parameterization)**是其核心创新点。以下是对这两个技术的详细解析: 一、辅…

CP4-OFDM模糊函数原理及仿真

文章目录 前言一、互补P4码序列二、barker-OFDM 信号1、OFDM 信号表达式2、模糊函数表达式 三、MATLAB 仿真1、MATLAB 核心源码2、仿真结果①、CP4-OFDM 模糊函数②、CP4-OFDM 距离分辨率③、CP4-OFDM 速度分辨率④、CP4-OFDM 等高线图 四、资源自取 前言 本文进行 CP4-OFDM 的…

【C语言预处理详解(上)】--预定义符号,#define定义常量,#define定义宏,带有副作用的宏参数,宏替换的规则,宏和函数的对比

目录 一.预定义符号 二.#define定义常量 三.#define定义宏 3.1--定义宏的方法和注意事项 3.2--带有副作用的宏参数 3.3--宏替换的规则 四.宏与函数的对比 🔥个人主页:草莓熊Lotso的个人主页 🎬作者简介:C研发方向学习者 &a…

CppCon 2014 学习:C++ Memory Model Meets High-Update-Rate Data Structures

这段内容是对一个主题的概览(Overview),涉及并行更新的问题,特别是“Issaquah Challenge”这个具体案例。详细解读如下: Overview(概览) The Issaquah Challenge 这是一个特定的挑战或问题&am…

如何用利用deepseek的API能力来搭建属于自己的智能体-优雅草卓伊凡

如何用利用deepseek的API能力来搭建属于自己的智能体-优雅草卓伊凡 上一篇文章我们已经介绍了智能体和大模型AI的区别,现在我们开始搭建自己的智能体进行工作 1. 了解 DeepSeek 提供的 AI 能力 DeepSeek 提供强大的 大语言模型(LLM)&#x…

智能制造之精读——RPA制造行业常见场景【附全文阅读】

RPA 在制造行业应用广泛,为企业带来显著价值,是极具潜力的智能化解决方案。它能节省成本,降低人力与管理成本;提升运营效率,减少人机交互损耗;提高质量,保障流程准确性;还能增强合规…

【2025.06】jupyter notebook 7+ 新手安装、配置、扩展应用(windows篇)

本文目录 前述一、安装二、配置2.1 jupyter_notebook_config.py生成配置文件2.2 服务器与网络设置a. 修改端口号b. 允许远程访问c. 设置工作目录 2.3 安全与认证a. 禁用密码登录(仅限本地安全环境)b. 设置登录密码c. 启用SSL加密(HTTPS&#…