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

Redis的基础,经典,高级问题解答篇

目录

一,基础

二,经典

缓存雪崩:

1. Redis事务的原子性

2. 与MySQL事务的区别

1. 主从复制原理

2. 哨兵模式故障转移流程

3. 客户端感知故障转移

三,高级


  • 一,基础

  1. Redis的5种基础数据类型及使用场景?Zset底层实现原理?

    1. String(字符串)

      • 场景:缓存简单键值对(如用户会话信息、计数器)、分布式锁(如SETNX)、二进制数据存储(如图片Base64)。

      • 特点:支持原子操作(如INCRDECR),最大存储512MB。

    2. List(列表)

      • 场景:消息队列(LPUSH/RPOP实现生产者-消费者)、最新消息排行(如微博时间线)、阻塞式任务调度。

      • 特点:双向链表,支持按索引操作(但时间复杂度高)。

    3. Hash(哈希表)

      • 场景:存储对象(如用户信息字段:HSET user:1 name "Alice")、聚合数据(如购物车商品信息)。

      • 特点:支持单字段读写,内存优化(底层为ziplist或hashtable)。

    4. Set(集合)

      • 场景:去重数据(如用户标签)、共同好友(SINTER求交集)、随机抽奖(SRANDMEMBER)。

      • 特点:无序、自动去重,支持集合运算(并/交/差)。

    5. Zset(有序集合)

      • 场景:排行榜(按分数排序)、延迟队列(以时间戳为score)、带权重的任务调度。

      • 特点:元素唯一但score可重复,支持范围查询(ZRANGEBYSCORE)。

    6. Zset的底层由 跳跃表(Skip List) 和 字典(Dict) 组成,或在小数据量时使用 listpack(替代旧版的ziplist)

      • 跳跃表

        • 多层链表结构,高层链表作为“快速通道”,支持O(log N)的查询、插入、删除。

        • 每个节点包含scorevalue,按score排序,支持高效范围操作(如ZRANGE)。

      • 字典

        • 维护value -> score的映射,实现O(1)的单元素查询。

      • 内存优化

        • 元素数≤zset-max-listpack-entries且元素大小≤zset-max-listpack-value时,使用listpack存储。

  2. Redis持久化机制RDB和AOF的区别?如何选择?

    1. 特性RDBAOF
      原理定时生成全量数据快照(二进制文件)记录所有写命令(追加日志文件)
      文件体积小(压缩二进制)大(文本命令,需重写优化)
      恢复速度快(直接加载内存)慢(重放命令)
      数据安全可能丢失最后一次快照后的数据可配置fsync策略(无/秒级/每次写)
      资源消耗高(fork子进程内存开销)低(追加日志,重写时才有fork开销)
    2. 选择策略

      1. 高数据安全:选择AOF(appendfsync everysec),容忍秒级丢失。

      2. 快速恢复/备份:选择RDB(如每日备份)。

      3. 混合模式:Redis 4.0+支持RDB+AOF,AOF记录增量,RDB做全量备份。

  3. 如何用Redis实现分布式锁?需要注意哪些问题?

    1. 实现步骤

    2. // 加锁:SET key unique_value NX PX 30000
      String result = jedis.set("lock_key", "client1", "NX", "PX", 30000);
      if ("OK".equals(result)) {// 执行业务逻辑
      } // 解锁:Lua脚本保证原子性
      String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";
      Object unlockResult = jedis.eval(script, Collections.singletonList("lock_key"), Collections.singletonList("client1"));

      注意事项

      1. 锁过期时间:需预估业务耗时,建议设置自动续期(如Redisson的看门狗)。

      2. 唯一标识:value使用唯一值(如UUID+线程ID),避免误删其他客户端的锁。

      3. 优化方案

      4. 使用Redisson库,内置看门狗、可重入锁、红锁(RedLock)实现。

      5. 对锁操作添加重试机制(如指数退避)。

      6. 原子性操作:加锁(SET NX PX)和释放锁(Lua脚本)必须原子化。

      7. 集群问题

        • 主从异步复制:主节点宕机可能导致锁丢失,可考虑RedLock算法(需部署多实例)。

        • RedLock争议:依赖系统时钟一致性,需权衡CAP。

  • 二,经典

  1. 什么是缓存穿透/雪崩/击穿?分别给出解决方案
    1. 缓存穿透:
      1. 问题:大量请求查询数据库中不存在的数据(如非法ID),绕过缓存直接压垮数据库。
        解决方案:        

        1. 布隆过滤器(Bloom Filter):在缓存层前加布隆过滤器,预存所有合法键的哈希值,拦截非法请求。

          • 特点:存在一定误判率(可能将非法请求误判为合法),需权衡内存占用。

        2. 缓存空值:对查询结果为null的键,缓存空值并设置短过期时间(如30秒)。

          • 注意:需定期清理无效空值,避免内存浪费。

    2. 缓存雪崩:
      1. 问题:大量缓存同时过期或缓存服务宕机,导致请求全部涌向数据库。
        解决方案

        1. 随机过期时间:为缓存设置基础过期时间 + 随机偏移值(如 TTL = 24h + random(0, 1h))。

        2. 永不过期 + 异步更新

          • 缓存不设过期时间,通过后台线程定期更新。

          • 结合双缓存策略:主缓存永不过期,备份缓存设置过期时间作为兜底。

        3. 熔断降级:使用Hystrix等工具,在数据库压力过大时直接返回默认值或限流。

    3. 缓存击穿:
      1. 问题热点数据过期时,高并发请求瞬间击穿缓存,直接访问数据库。
        解决方案

      2. 互斥锁(Mutex Lock)

        • 当缓存失效时,通过分布式锁(如Redis的SETNX)控制只有一个线程重建缓存,其他线程等待。

        • 示例代码:

        • public String getData(String key) {String value = redis.get(key);if (value == null) {if (redis.setnx("lock_" + key, "1", 10)) { // 获取锁value = db.query(key);redis.setex(key, 3600, value);redis.del("lock_" + key); // 释放锁} else {Thread.sleep(100); // 等待后重试return getData(key);}}return value;
          }
        • 逻辑过期:缓存永不过期,但存储的数据中增加逻辑过期时间字段,由业务代码判断是否需要异步更新。

  2. Redis事务的原子性如何理解?与MySQL事务的区别?
    1. 1. Redis事务的原子性
      • 实现方式:通过MULTI(开启事务)、EXEC(提交事务)、DISCARD(取消事务)命令实现。

      • 原子性含义

        • 命令队列的原子执行:事务中的命令会被序列化并按顺序执行,不会被其他客户端命令打断。

        • 不支持回滚:若事务中某条命令执行失败(如语法错误),其他命令仍会继续执行,无回滚机制。

        • 示例:

        • MULTI
          SET key1 "A"  # 入队
          INCR key2     # 入队(若key2非数值类型,执行时报错)
          EXEC          # 提交事务,第二条命令执行失败,但第一条仍生效
      • 2. 与MySQL事务的区别
        特性RedisMySQL
        原子性仅保证命令队列的批量执行,无回滚支持ACID,失败时自动回滚
        隔离性无隔离级别,事务执行期间可能被其他客户端修改数据支持多隔离级别(如读已提交、可重复读)
        持久性依赖持久化机制(RDB/AOF)依赖Redo Log和Binlog保证持久性
        使用场景简单批量操作(如批量SET)复杂业务逻辑(如转账、订单处理)
  3. Redis主从复制原理?哨兵模式如何实现故障转移?
    1. 1. 主从复制原理
    2. 核心流程

      1. 全量同步(首次连接)

        • 从节点发送PSYNC ? -1命令请求同步。

        • 主节点执行BGSAVE生成RDB文件并发送给从节点,同时缓存期间的写命令到复制缓冲区。

        • 从节点加载RDB后,主节点发送缓冲区中的写命令使其追上最新状态。

      2. 增量同步(断线重连)

        • 从节点发送PSYNC <runid> <offset>,主节点根据offset从复制缓冲区发送增量数据。

        • 若复制缓冲区数据丢失(如缓冲区溢出),触发全量同步。

    3. 关键配置

      • repl-backlog-size:调整复制缓冲区大小,避免频繁全量同步。

    4. 2. 哨兵模式故障转移流程

      哨兵(Sentinel)是Redis的高可用解决方案,负责监控、通知和自动故障转移:

    5. 监控

      • 每个哨兵节点定期向主节点、从节点和其他哨兵发送PING命令检测存活状态。

    6. 主观下线(SDOWN)

      • 若哨兵在down-after-milliseconds时间内未收到主节点的有效响应,标记其为主观下线。

    7. 客观下线(ODOWN)

      • 当超过半数哨兵认为主节点主观下线,则标记为客观下线。

    8. 选举Leader哨兵

      • 通过Raft算法选举一个Leader哨兵来执行故障转移。

    9. 故障转移

      • Leader哨兵从从节点列表中选出一个新的主节点(基于优先级、复制偏移量等)。

      • 向其他从节点发送SLAVEOF命令,使其复制新主节点。

      • 更新客户端配置,通知其连接新主节点。

    10. 3. 客户端感知故障转移
    11. 客户端通过订阅哨兵的+switch-master事件获取新主节点地址,或通过哨兵API动态查询。

  • 三,高级

  1. Redis Cluster集群模式的数据分片原理?如何实现动态扩容?
    1. 数据分片原理
      Redis Cluster采用哈希槽(Hash Slot)机制进行数据分片,共有16384个槽位。每个键通过CRC16(key)计算哈希值,再对16384取模确定所属槽位。集群中的每个节点负责一部分槽,数据分布由槽分配决定。客户端请求时,若连接节点不负责该槽,会返回MOVED重定向错误,引导客户端访问正确节点。节点间通过Gossip协议交换集群状态,维护槽分配信息的一致性。

      动态扩容实现

    2. 添加新节点:使用CLUSTER MEET将新节点加入集群。

    3. 迁移槽数据

      • 使用redis-cli --cluster reshard触发槽重新分片。

      • 源节点将槽内键逐个迁移到目标节点,期间对正在迁移的键的请求,源节点返回ASK重定向,客户端需重试到目标节点。

    4. 更新槽分配:迁移完成后,槽归属信息通过Gossip协议同步到整个集群。

    5. 副本扩展:新增副本节点通过CLUSTER REPLICATE同步主节点数据。

  2. Redis内存淘汰策略有哪些?如何设计大Key热Key的解决方案?
    1. 内存淘汰策略(通过maxmemory-policy配置)

    2. noeviction:拒绝写入新数据(默认)。

    3. volatile-ttl:淘汰过期时间最近的键。

    4. LRU/LFU策略

      • allkeys-lru/volatile-lru:基于最近最少使用。

      • allkeys-lfu/volatile-lfu:基于访问频率(4.0+)。

    5. 随机淘汰allkeys-random/volatile-random

    6. 大Key解决方案

    7. 拆分:如将大Hash拆分为多个小Hash,通过键名后缀分片。

    8. 异步删除:使用UNLINK代替DEL,非阻塞释放内存。

    9. 压缩:对Value进行压缩(如GZIP),但会增加CPU开销。

    10. 监控:通过redis-cli --bigkeys定期扫描大Key。

    11. 热Key解决方案

    12. 多级缓存:本地缓存(如Guava)减少Redis访问。

    13. 读写分离:通过副本节点分散读压力。

    14. 分片打散:使用Hash Tag(如{user1000}.profile)强制热Key分布到同一节点,并增加副本。

    15. Proxy支持:如Twemproxy或Codis自动分散请求。

  3. Redis多线程模型演进(从单线程到IO多线程)?管道技术原理?
    1. 多线程演进

    2. 单线程模型(6.0前):单线程处理所有网络I/O、命令解析和执行,避免锁竞争,但无法利用多核CPU。

    3. I/O多线程(6.0+)

      • 多线程网络I/O:主线程负责接收连接,I/O线程处理读写(配置io-threads启用)。

      • 单线程命令执行:命令执行仍为单线程,保证原子性。

    4. 性能提升:高并发场景下,网络I/O瓶颈缓解,吞吐量显著提升。

    5. 管道技术(Pipeline)原理

    6. 批量发送:客户端将多个命令打包发送,减少网络往返次数(RTT)。

    7. 服务端顺序执行:服务器按顺序依次执行命令,全部完成后一次性返回结果。

    8. 优势:适用于批量操作(如批量写入),提升吞吐量。

    9. 注意点:不保证原子性,且返回结果需客户端按序解析。

相关文章:

Redis的基础,经典,高级问题解答篇

目录 一&#xff0c;基础 二&#xff0c;经典 缓存雪崩&#xff1a; 1. Redis事务的原子性 2. 与MySQL事务的区别 1. 主从复制原理 2. 哨兵模式故障转移流程 3. 客户端感知故障转移 三&#xff0c;高级 一&#xff0c;基础 Redis的5种基础数据类型及使用场景&#xf…...

uniapp uni-swipe-action滑动内容排版改造

在uniapp开发中 默认的uni-swipe-action滑动组件 按钮里的文字都是横排的 不能换行的 如果是在一些小屏设备 比如PDA这种&#xff0c;同时按钮文字又都是4个字 多按钮的情况 就会发现滑动一下都直接满屏了 观看体验都不好 但默认的官方组件又没有样式的设置&#xff0c;下面就告…...

电脑卡怎么办?提升电脑流畅的方法

电脑已经成为我们工作、学习和娱乐不可或缺的伙伴。然而&#xff0c;随着使用时间的增长&#xff0c;许多用户会遇到电脑运行变慢、卡顿的情况&#xff0c;这不仅影响了工作效率&#xff0c;也大大降低了使用体验。本文将为大家分析电脑卡顿的常见原因&#xff0c;并提供一套实…...

SpringBoot报错解决方案

org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException: the request was rejected because its size (31297934) exceeds the configured maximum (10485760) 文件上传大小超过限制...

知识表示方法之二:产生式表示法(Production System)

有关知识表示方法之一:一阶谓词逻辑的内容可以看我的文章:https://blog.csdn.net/lzm12278828/article/details/146541478 一、定义 “产生式”这一术语是有美国数学家博斯特(E.Post)在1943年首先提出来的,他根据串替代规则提出了一种称为波斯特机的计算模型,模型中的每…...

SQL Server中账号权限

目录标题 查看现有权限授予权限拒绝权限撤销权限角色管理 在SQL Server中管理账号权限主要通过以下几个关键步骤&#xff1a; 查看现有权限 可以使用系统视图来查看账号的权限&#xff0c;比如 sys.database_permissions 视图&#xff0c;示例查询如下&#xff1a; SELECT d…...

软件需求未明确非功能性指标(如并发量)的后果

软件需求未明确非功能性指标&#xff08;如并发量&#xff09;可能带来的严重后果包括&#xff1a;系统性能下降、用户体验恶化、稳定性降低、安全风险增加、后期维护成本高企。其中&#xff0c;系统性能下降尤为显著。当软件系统在设计和开发阶段未明确并发量需求时&#xff0…...

VScode-i18n-ally-Vue

参考这篇文章&#xff0c;做Vue项目的国际化配置&#xff0c;本篇文章主要解释&#xff0c;下载了i18n之后&#xff0c;该如何对Vscode进行配置 https://juejin.cn/post/7271964525998309428 i18n Ally全局配置项 Vscode中安装i18n Ally插件&#xff0c;并设置其配置项&#…...

Spring Boot项目快速创建-开发流程(笔记)

主要流程&#xff1a; 前端发送网络请求->controller->调用service->操纵mapper->操作数据库->对entity数据对象赋值->返回前端 前期准备&#xff1a; maven、mysql下载好 跟学视频&#xff0c;感谢老师&#xff1a; https://www.bilibili.com/video/BV1gm4…...

车架号查询车牌号接口如何用Java对接

一、什么是车架号查询车牌号接口&#xff1f; 车架号查询车牌号接口&#xff0c;即传入车架号&#xff0c;返回车牌号、车型编码、初次登记日期信息。车架号又称车辆VIN码&#xff0c;车辆识别码。 二、如何用Java对接该接口&#xff1f; 下面我们以阿里云接口为例&#xff0…...

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本的处理方法

1、安装了node.js后&#xff0c;windows powershell中直接输入npm&#xff0c;然后就报错 2、出现原因&#xff1a;权限不够 系统禁用了脚本的执行&#xff0c;所以我们在windows powershell输入npm -v的时候&#xff0c;就会报上面的错误。 3、解决 Set-ExecutionPolicy Un…...

【java笔记】泛型、包装类、自动装箱拆箱与缓存机制

一、泛型&#xff1a;类型安全的基石 1. 泛型的本质与原理 Java 泛型&#xff08;Generics&#xff09;是 JDK 5 引入的特性&#xff0c;通过类型参数化实现代码的通用性。泛型类、接口和方法允许在定义时声明类型参数&#xff08;如 T、E、K、V&#xff09;&#xff0c;这些…...

数仓开发那些事(11)

某神州优秀员工&#xff1a;一闪&#xff0c;领导说要给我涨米。 一闪&#xff1a;。。。。&#xff08;着急的团团转&#xff09; 老运维&#xff1a;Oi&#xff0c;两个吊毛&#xff0c;看看你们的hadoop集群&#xff0c;健康度30分&#xff0c;怎么还在抽思谋克&#xff1f…...

自动化测试【Python3.7+Selenium3】

1、自动化测试环境搭建之selenium3安装 方法1&#xff1a;cmd环境下&#xff0c;用pip install selenium &#xff08;速度很慢&#xff0c;不推荐&#xff09; 方法2&#xff1a;下载selenium安装包手动安装 下载地址&#xff1a;https://pypi.org/project/selenium/ 在解压…...

从零开始完成冒泡排序(0基础)——C语言版

文章目录 前言一、冒泡排序的基本思想二、冒泡排序的执行过程&#xff08;一&#xff09;第一轮排序&#xff08;二&#xff09;第二轮排序&#xff08;三&#xff09;第三轮排序&#xff08;四&#xff09;第四轮排序 三、冒泡排序的代码实现&#xff08;C语言&#xff09;&am…...

工业级POE交换机:助力智能化与自动化发展

随着工业互联网、物联网&#xff08;IoT&#xff09;和自动化技术的快速发展&#xff0c;网络设备在工业领域的应用日益广泛。然而&#xff0c;在严苛环境下&#xff0c;传统网络设备往往难以应对复杂的温湿度变化、电磁干扰和供电不稳定等挑战。为同时满足数据传输与供电一体化…...

使用ZYNQ芯片和LVGL框架实现用户高刷新UI设计系列教程(第五讲)

在上一讲我们讲解了按键回调函数的自定义函数的用法&#xff0c;这一讲继续讲解回调函数的另一种用法。 首先我们将上一讲做好的按键名称以及自定义回调事件中的按键名称修改&#xff0c;改为默认模式为“open”当点击按键时进入回调函数将按键名称改为“close”&#xff0c;具…...

Burp Suite Professional 2024版本安装激活指南

文章目录 burpsuite简介Burp Suite的主要组件&#xff1a;Burp Suite的版本使用场景 下载地址使用教程 burpsuite简介 Burp Suite 是一个广泛使用的网络安全测试工具&#xff0c;特别是在Web应用程序安全领域。它主要用于发现和修复Web应用中的安全漏洞&#xff0c;特别适用于渗…...

【c++深入系列】:类与对象详解(上)

&#x1f525; 本文专栏&#xff1a;c &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 你仰望的星辰并非遥不可及&#xff0c;而是跋涉者脚印的倒影&#xff1b;你向往的远方未必需要翅膀&#xff0c;只要脚下始终有路&#x…...

6、进程理论和简单进程创建

一、了解进程推荐看这个视频&#xff0c;很详细 1、概念 进程(Process)程序的运行过程&#xff0c;是系统进行资源分配和调度的独立单元程序的运行过程&#xff1a;多个不同程序 并发&#xff0c;同一个程序同时执行多个任务。 就需要很多资源来实现这个过程。 每个进程都有一…...

java八股文之JVM

1.什么是程序计数器 程序计数器是 JVM 管理线程执行的“定位器”&#xff0c;记录每个线程当前执行的指令位置&#xff0c;确保程序流程的连续性和线程切换的准确性。线程私有的&#xff0c;每个线程一份&#xff0c;内部保存的字节码的行号。用于记录正在执行的字节码指令的地…...

Todesk介绍

文章目录 ToDesk 软件介绍1. 软件概述2. ToDesk 的功能特点2.1 简单易用2.2 高质量的图像与流畅的操作2.3 跨平台支持2.4 多屏显示与协作2.5 文件传输功能2.6 实时聊天与语音通话2.7 远程唤醒与自动启动2.8 多种权限设置与安全性2.9 无需公网 IP 3. ToDesk 的应用场景3.1 个人使…...

每日总结3.27

蓝桥刷题 1. 团建 &#xff08;树dfs&#xff09; #include <bits/stdc.h> using namespace std; const int N200005; int a[N],b[N]; int ans; map<int,vector<int>>m1,m2; void dfs(int x,int y,int count) { if(a[x]!b[y]) {return;} ansmax(ans,c…...

Linux 进程3-fork创建子进程继承父进程缓冲区验证

目录 1. fork创建子进程继承父进程缓冲区验证 1.1 write向标准输出&#xff08;终端屏幕&#xff09;写入数据验证 1.1.1 write函数写入数据不带行缓冲刷新 \n 1.1.2 write函数写入数据带行缓冲刷新 \n 1.2 fork创建前执行printf函数 1.2.1 fork创建前执行printf函数带\n…...

应用服务接口第二次请求一直pending问题

目录 一、问题背景二、问题排查过程三、解决方案四、总结 一、问题背景 升级内容发布到灰度环境&#xff0c;验证相关服务&#xff0c;查看接口调用日志&#xff0c;发现第一次请求正常&#xff0c;第二次相同接口请求就一直pending&#xff0c;其他服务也是如此 二、问题排查…...

基于FPGA的ESP8266无线数据传输(温湿度DTH11、光照强度BH1750、WIFI模块)连接中国移动onenet云平台,仿真+上板

文章目录 一、创建云平台产品设备二、FPGA仿真WIFI模块通信过程仿真分析2.上板 总结 一、创建云平台产品设备 使用串口助手测试传输过程 相关信息记录 二、FPGA仿真WIFI模块通信过程 仿真分析 //各个状态tx_dataalways (posedge clk or negedge rst_n) beginif(!rst_n) beg…...

5款视觉OCR开源模型

一、号称「世界上最好的 OCR 模型」Mistral OCR Mistral OCR 擅长理解复杂的文档元素&#xff0c;包括交错图像、数学表达式、表格和高级布局&#xff08;如 LaTeX 格式&#xff09;。该模型可以更深入地理解丰富的文档&#xff0c;尤其是包含图表、图形、公式和数字的科学论文…...

计算机二级(C语言)考试高频考点总汇(三)—— 结构体和共用体、结构体对齐规则、联合体大小计算

目录 九、结构体和共用体 十、结构体对齐规则 十一、联合体大小计算 九、结构体和共用体 141. 结构体是&#xff08;不同类型成员的集合&#xff09;&#xff0c;是⼀种用户自定义的数据类型&#xff0c;可以将不同类型的成员组合在⼀起&#xff0c;用于表示&#xff08;复…...

transformers中学习率warmup策略具体如何设置

在使用 get_linear_schedule_with_warmup&#xff08;如 Hugging Face Transformers 库中的学习率调度器&#xff09;时&#xff0c;参数的合理设置需要结合 数据量&#xff08;dataset size&#xff09;、批次大小&#xff08;batch size&#xff09; 和 训练轮数&#xff08;…...

“线程通信“一个案例

今天在处理项目需求的时候, 遇到这样一个问题: 项目中需要将用户界面上传的某种模型文件转换成另一种格式的文件, 以便进行预览操作. 而这个转换的过程需要调用到专业软件的脚本程序, 简单来说就是一个比较耗时的步骤. 并且这个转换还要分为两步进行, 需要调用两个脚本程序. 简…...