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

每日八股文6.8

每日八股-6.8

  • Redis
    • 1.Redis的RDB了解过吗?
    • 2.你能简单描述一下 RDB 的执行流程是怎样的吗?
    • 3.Redis 支持哪些常用的数据类型呢?/ Redis常用的数据结构了解哪些呢?
    • 4.Redis 的 Hash数据结构了解吗?
    • 5.渐进式扩容了解过吗?/HashTable 是怎么扩容的?
    • 6.Redis 的跳表(Skiplist)是一种什么样的结构?

Redis

1.Redis的RDB了解过吗?

在这里插入图片描述

Redis的RDB的本质是一个数据快照,以二进制文件的形式存储,他记录的是某一时刻redis数据库的状态,记录了所有键值对。

生成 RDB 文件主要有两种方式:

  1. SAVE (同步保存):

    • 触发方式:由客户端直接执行 SAVE 命令。
    • 过程:如上图所示,由 Redis 主进程负责写入 RDB 文件,期间会阻塞所有其他请求。
    • 适用场景:基本不用于生产环境。只在没有客户端连接,或者可以接受服务暂停时(比如维护、迁移前)手动执行。
  2. BGSAVE (异步保存):

    • 触发方式:客户端直接执行 BGSAVE 命令。
    • 过程:这是 Redis 推荐的方式。Redis 主进程会 fork() 一个子进程,让子进程去负责生成 RDB 文件,而主进程可以继续处理客户端的请求,避免了长时间的阻塞。
    • 适用场景:绝大多数生产环境的默认选择。

RDB 的优缺点

  1. 优点:

    • 恢复速度快: RDB 文件是一个紧凑的二进制文件,里面存储的是某个时间点的数据本身。在 Redis 重启时,可以直接将这个文件加载到内存中,恢复速度远快于需要逐条执行命令的 AOF。
    • 文件体积小: 经过压缩的二进制格式,相比于记录命令的 AOF 文件,体积更小,便于备份和网络传输。
  2. 缺点:

    • 数据丢失风险高: RDB 是间隔性地进行快照。如果在上一次快照之后、下一次快照之前,Redis 服务器发生宕机,那么这期间所有被修改但尚未保存的数据都将全部丢失。

2.你能简单描述一下 RDB 的执行流程是怎样的吗?

在这里插入图片描述

生成rdb文件主要有两种方式,下面分别进行介绍。

SAVE 命令 (同步阻塞)

  1. Redis 主进程接收到 SAVE 命令,开始执行持久化。
  2. 在持久化期间,主进程完全阻塞,无法处理任何其他客户端请求。
  3. 主进程将数据写入 RDB 文件,完成后用新文件替换旧文件。
  4. 持久化结束,主进程解除阻塞,恢复服务。

BGSAVE 命令 (异步非阻塞)

  1. Redis 主进程 fork 一个子进程,fork 后主进程继续处理客户端请求。
  2. 子进程负责将内存数据写入一个临时的 RDB 文件。
  3. 子进程完成写入后,用这个新的临时文件替换掉旧的 RDB 文件。
  4. 子进程退出,整个持久化过程结束,全程几乎不影响主进程。

3.Redis 支持哪些常用的数据类型呢?/ Redis常用的数据结构了解哪些呢?

在这里插入图片描述

Redis 支持多种数据类型,最常用的有以下五种:

  • String(字符串): 这是最基本的数据类型,可以存储文本、数字或者二进制数据,单个 value 的最大容量是 512MB。常用于缓存对象、常规计数、实现分布式锁等。
  • Hash(哈希): 类似于 Map,存储键值对的集合,适合存储对象,可以方便地对对象的属性进行修改,常用于缓存对象、实现购物车等。
  • List(列表): 是一个有序的字符串列表,支持在列表的两端进行添加和删除操作,常用于实现消息队列等。
  • Set(集合): 是一个无序且唯一的字符串集合,常用于做一些集合操作,比如求交集、并集、差集,可以应用于点赞、共同关注等场景。
  • Zset(有序集合): 在 Set 的基础上为每个元素关联一个分数,可以根据分数进行排序,常用于实现排行榜等。

补充:在 Redis 中,所有的 key 都是二进制安全的 String 类型

4.Redis 的 Hash数据结构了解吗?

在这里插入图片描述

Redis 的 Hash 是一种 键值对集合,但与普通的键值对不同的是,Hash 中 每个键对应的值本身又是一个包含多个字段和值的键值对集合。可以把他想成一本书,外层的键对应的是书的名字,全局唯一,我们需要靠他来找到这本书;内层的键值对就像是书内的各个章节及对应的内容。

Redis 的 Hash 特点如下:

  • 适合存储小数据:Hash 特别适合存储具有多个相关属性的小对象。
  • 使用哈希表实现:底层通常使用哈希表(或压缩列表)实现,能够在内存中高效地存储和操作。
  • 支持快速的字段操作:Redis 提供了针对 Hash 中字段的快速增、删、改、查操作,例如 HGET、HSET、HDEL 等,这使得它非常适合存储和管理对象的属性。

5.渐进式扩容了解过吗?/HashTable 是怎么扩容的?

Redis 的 HashTable 扩容采用了 渐进式 rehash 的策略,这是为了避免一次性扩容带来的性能卡顿,将扩容的开销平摊到后续的操作中。

当 HashTable 的 负载因子(used / size) 超过一定的阈值时,就会触发扩容。具体来说,触发条件有两个:

  1. 当服务器当前没有执行 BGSAVE 命令或者 BGREWRITEAOF 命令,并且哈希表的负载因子大于等于 1 时。
  2. 当哈希表的负载因子大于等于 5 时,即使当前正在执行 BGSAVE (用来快照持久化)命令或者 BGREWRITEAOF(用来瘦身AOF文件) 命令,也会强制进行扩容。

补充:BGSAVE 和 BGREWRITEAOF 这两个命令本来就是内存密集型的,fork() 子进程会共享父进程的内存空间,如果此时再进行大规模的 rehash(也会分配新内存),可能会导致物理内存不足(OOM, Out-of-Memory),对系统造成巨大压力。因此,Redis 采取了更保守的策略,在后台持久化期间,将 rehash 的触发阈值从 1 提高到 5

扩容的过程如下:

  1. Redis 会为 HashTable 的 1 号哈希表分配空间,这个新哈希表的大小通常是 第一个大于等于 0 号哈希表当前已使用节点(used)的两倍的 2 的整数次幂。
  2. Redis 会将 rehashidx 索引计数器设置为 0,表示开始进行 rehash 操作。
  3. 在 rehash 进行期间,每次对 HashTable 执行添加、删除、查找或者更新操作时,除了完成正常的操作外,还会顺带将 rehashidx 位置上的所有键值对从 0 号哈希表迁移到 1 号哈希表,并将 rehashidx 的值加 1。
  4. 随着时间的推移和操作的不断进行,0 号哈希表中的所有键值对都会被迁移到 1 号哈希表中。
  5. 当所有的键值对都迁移完毕后,Redis 会释放 0 号哈希表的空间,然后将 1 号哈希表设置为新的 0 号哈希表,并创建一个新的空的 1 号哈希表,最后将 rehashidx 的值设置为 -1,表示 rehash 操作完成。

在渐进式 rehash 期间,对 HashTable 的 CRUD 操作会有些特殊:

  • 查询操作:会先在 0 号哈希表中查找,如果没找到,会继续在 1 号哈希表中查找。
  • 写入操作:新的键值对会直接写入到 1 号哈希表中,这样可以保证 0 号哈希表中的数据只会减少不会增加,最终会变成空表。
  • 删除操作:需要在 0 号和 1 号哈希表中都进行查找和删除。
    通过这种渐进式 rehash 的方式,Redis 可以平滑地完成哈希表的扩容操作,避免了因为一次性大量数据迁移而导致服务出现明显的卡顿。

6.Redis 的跳表(Skiplist)是一种什么样的结构?

在这里插入图片描述

Redis 跳表:多级跳跃的有序链表

  1. 本质: 一种有序链表的升级版。
  2. 核心思想: 空间换时间。
  3. 如何优化: 在普通链表上加了多层“索引”。
    • 底层是完整数据(有序链表)。
    • 上层是稀疏的、跳跃式的索引。
    • 层级越高,跳过的节点越多。
  4. 查找/增删: 从最顶层索引开始“跳”,快速定位,平均时间复杂度接近 O(logN)。
  5. 关键组成:
    • 节点: 每个节点包含 数据、分值、和最重要的 层 数组(多个向前指针)。
    • 层数组长度: 随机生成(决定节点参与多少层索引)。
  6. Redis 应用: 主要用于实现 ZSet(有序集合)。

补充:
7. zskiplist结构体包含Header、Tail、Level、Length四个属性,其中Header指向该层的第一个节点,Tail指向指向整个跳表中顺序上的最后一个节点,Level表示整个跳表当前的最大层数(不含头结点,在这里是4),Length表示跳表中节点的总个数(同样不包括头结点,这里是3)

  1. 图中的这些 L1、L2、L3 是跳表中 不同层级的前向指针,也可以理解为 索引层,用于加速搜索。每个节点会随机生成高度(层数)。
  2. 节点中的BW表示反向指针,除了header外每一个节点都有一个反向指针,支持从后往前遍历,可用来实现ZREVRANGE(倒序输出)。

相关文章:

  • 通过Cline使用智能体
  • WebFuture 升级提示“不能同时包含聚集KEY和大字段””的处理办法
  • DDR供电设计中的VTT与VREF作用和区别
  • 深究二分查找算法:从普通到进阶
  • 【AIGC】RAGAS评估原理及实践
  • 可可·香奈儿 活出自己
  • 使用Mathematica实现Newton-Raphson收敛速度算法(简单高阶多项式)
  • Beckhoff(倍福) -- MES(ITAC) TCP 通讯
  • Wise Disk Cleaner:免费高效的系统清理专家
  • C++课设:从零开始打造影院订票系统
  • Java中的抽象类
  • 2.1.3_2 编码和调制(下)
  • 用 DeepSeek 创作一首属于自己的歌
  • 图的邻接表存储及求邻接点操作
  • 【QT】QT多语言切换
  • 极客时间:在 Google Colab 上尝试 Prefix Tuning
  • 01.SQL语言概述
  • 算法-构造题
  • CSS悬停闪现与a标签嵌套的问题
  • vue3:十六、个人中心-修改密码
  • 个人做网站用哪个主机好/关键词查询优化
  • 卖书的网站怎么做/百度问答seo
  • 上海景泰建设有限公司网站/百度seo怎么提高排名
  • 外贸网站屏蔽国内ip/今日特大新闻新事
  • wordpress搬家 数据库/北京中文seo
  • 医院网站建设的指导思想/seo技术蜘蛛屯