【Java面试题】Redis上篇(基础、持久化、底层数据结构)

文章目录

  • 基础
    • 1.什么是Redis?
    • 2.Redis可以用来干什么?
    • 3.Redis的五种基本数据结构?
    • 4.Redis为什么这么快?
    • 5.什么是I/O多路复用?
    • 6.Redis6.0为什么使用了多线程?
  • 持久化
    • 7.Redis的持久化方式?区别?
    • 8.RDB和AOF的优缺点?
    • 9.RDB和AOF如何选择
    • 10.Redis的数据恢复?
    • 11.Redis4.0的混合持久化了解吗?
  • 底层数据结构
    • 12.说说Redis的底层数据结构?
    • 13.跳跃表是如何实现的?原理?

基础

1.什么是Redis?

  1. Redis即 Remote Dictionary Service 三个单词中加粗字母的组合,是一种基于键值对(key-value)的 NoSQL 数据库。
  2. value值支持多种数据结构:string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、HyperLogLogopen in new window(基数估算)、GEO(地理信息定位)
  3. Redis 的所有数据都存放在内存当中,所以它的读写性能非常出色
  4. Redis 还可以将内存数据持久化到硬盘上,这样在发生类似断电或者机器故障的时候,内存中的数据并不会“丢失”

2.Redis可以用来干什么?

  1. 热点数据缓存
  2. 计数器(记录浏览量、点赞收藏量)
  3. 分布式锁(SETNX命令+过期时间+Lua脚本)
  4. 排行榜(有序集合)
  5. 社交网络(共同好友/喜好)

3.Redis的五种基本数据结构?

介绍应用场景底层数据结构
string1. 字符串是最基础的数据结构
字符串(简单的字符串、复杂的字符串(例如 JSON、XML))
数字 (整数、浮点数)
甚至是二进制(图片、音频、视频),但最大不能超过 512MB。
1.缓存token
2.计数功能
hash键值对集合,value = {name: ‘沉默王二’, age: 18}1.缓存用户信息
2.缓存对象
listlist 是一个简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)1.消息队列
2.文章列表
set集合是字符串的无序集合,集合中的元素是唯一的,不允许重复。1.共同好友
sorted set有序集合1.排序功能
2.点赞收藏统计

4.Redis为什么这么快?

Redis 的速度⾮常快,单机的 Redis 就可以⽀撑每秒十几万的并发,性能是 MySQL 的⼏⼗倍。速度快的原因主要有几点:

  1. 基于内存的数据存储,Redis 将数据存储在内存当中,使得数据的读写操作避开了磁盘 I/O。而内存的访问速度远超硬盘,这是 Redis 读写速度快的根本原因。
  2. 单线程模型,Redis 使用单线程模型来处理客户端的请求,这意味着在任何时刻只有一个命令在执行。这样就避免了线程切换和锁竞争带来的消耗
  3. 高效的数据结构,Redis 提供了多种高效的数据结构,如字符串(String)、列表(List)、集合(Set)、有序集合(Sorted Set)等,这些数据结构经过了高度优化,能够支持快速的数据操作。
  4. IO 多路复用,基于 Linux 的 select/epoll 机制。该机制允许内核中同时存在多个监听套接字和已连接套接字,内核会一直监听这些套接字上的连接请求或者数据请求,一旦有请求到达,就会交给 Redis 处理,就实现了所谓的 Redis 单个线程处理多个 IO 读写的请求。

5.什么是I/O多路复用?

引用知乎上一个高赞的回答来解释什么是 I/O 多路复用。假设你是一个老师,让 30 个学生解答一道题目,然后检查学生做的是否正确,你有下面几个选择:

  • 第一种选择:按顺序逐个检查,先检查 A,然后是 B,之后是 C、D。。。这中间如果有一个学生卡住,全班都会被耽误。这种模式就好比,你用循环挨个处理 socket,根本不具有并发能力。
  • 第二种选择:你创建 30 个分身,每个分身检查一个学生的答案是否正确。 这种类似于为每一个用户创建一个进程或者- 线程处理连接。
  • 第三种选择,你站在讲台上等,谁解答完谁举手。这时 C、D 举手,表示他们解答问题完毕,你下去依次检查 C、D 的答案,然后继续回到讲台上等。此时 E、A 又举手,然后去处理 E 和 A。

第一种就是阻塞 IO 模型,第三种就是 I/O 复用模型

多路复用模型

6.Redis6.0为什么使用了多线程?

  1. Redis6.0 的多线程是用多线程来处理数据的读写和协议解析,但是 Redis执行命令还是单线程的
  2. 这样做的⽬的是因为 Redis 的性能瓶颈在于⽹络 IO ⽽⾮ CPU,使⽤多线程能提升 IO 读写的效率,从⽽整体提⾼ Redis 的性能。

Redis6.0多线程

持久化

7.Redis的持久化方式?区别?

  1. Redis 支持两种主要的持久化方式:RDB(Redis DataBase)持久化和 AOF(Append Only File)持久化。

  2. 这两种方式可以单独使用,也可以同时使用。

  3. RDB

    • RDB 持久化通过创建数据集的快照(snapshot) 来工作,在指定的时间间隔内将 Redis 在某一时刻的数据状态保存到磁盘的一个 RDB 文件中。

    • 可通过 save 和 bgsave 命令两个命令来手动触发 RDB 持久化操作:

      • save 命令:会同步地将 Redis 的所有数据保存到磁盘上的一个 RDB 文件中。这个操作会阻塞所有客户端请求,直到 RDB 文件被完全写入磁盘

      • bgsave 命令:会在后台异步地创建 Redis 的数据快照,并将快照保存到磁盘上的 RDB 文件中。这个命令会立即返回,Redis 服务器可以继续处理客户端请求

        • 在 BGSAVE 命令执行期间,Redis 会继续响应客户端的请求,对服务的可用性影响较小。快照的创建过程是由一个子进程完成的,主进程不会被阻塞。是在生产环境中执行 RDB 持久化的推荐方式。
    • 以下场景会自动触发 RDB 持久化

      • 在 Redis 配置文件(通常是 redis.conf)中,可以通过save <seconds> <changes>指令配置自动触发 RDB 持久化的条件。这个指令可以设置多次,每个设置定义了一个时间间隔(秒)和该时间内发生的变更次数阈值
      save 900 1
      save 300 10
      save 60 10000如果至少有 1 个键被修改,900 秒后自动触发一次 RDB 持久化。
      如果至少有 10 个键被修改,300 秒后自动触发一次 RDB 持久化。
      如果至少有 10000 个键被修改,60 秒后自动触发一次 RDB 持久化。
      
      • Redis 服务器通过 SHUTDOWN 命令正常关闭时,如果没有禁用 RDB 持久化,Redis 会自动执行一次 RDB 持久化,以确保数据在下次启动时能够恢复。
      • 在 Redis 复制场景中,当一个 Redis 实例被配置为从节点并且与主节点建立连接时,它可能会根据配置接收主节点的 RDB 文件来初始化数据集。这个过程中,主节点会在后台自动触发 RDB 持久化,然后将生成的 RDB 文件发送给从节点
  4. AOF

    • AOF 持久化通过记录每个写操作命令并将其追加到 AOF 文件中来工作,恢复时通过重新执行这些命令来重建数据集。

    • 简单工作流程:

      • 命令写入 (append)、文件同步(sync)、文件重写(rewrite)、重启加载 (load)

        三分恶面渣逆袭:AOF工作流程

    • 详细工作流程:

      1)当 AOF 持久化功能被启用时,Redis 服务器会将接收到的所有写命令(比如 SET, LPUSH, SADD 等修改数据的命令)追加到 AOF 缓冲区(buffer)的末尾

      2)为了将缓冲区中的命令持久化到磁盘中的 AOF 文件,Redis 提供了几种不同的同步策略:

      • always:每次写命令都会同步到 AOF 文件,这提供了最高的数据安全性,但可能因为磁盘 I/O 的延迟而影响性能。
      • everysec(默认):每秒同步一次,这是一种折衷方案,提供了较好的性能和数据安全性。
      • no:不主动进行同步,交由操作系统决定何时将缓冲区数据写入磁盘,这种方式性能最好,但在系统崩溃时可能会丢失最近一秒的数据。

      3)随着操作的不断执行,AOF 文件会不断增长,为了减小 AOF 文件大小,Redis 可以重写 AOF 文件

      • 重写过程不会解析原始的 AOF 文件,而是将当前内存中的数据库状态转换为一系列写命令,然后保存到一个新的 AOF 文件中。
      • AOF 重写操作由 BGREWRITEAOF 命令触发,它会创建一个子进程来执行重写操作,因此不会阻塞主进程。
      • 重写过程中,新的写命令会继续追加到旧的 AOF 文件中,同时也会被记录到一个缓冲区中。一旦重写完成,Redis 会将这个缓冲区中的命令追加到新的 AOF 文件中,然后切换到新的 AOF 文件上,以确保数据的完整性。

      4)当 Redis 服务器启动时,如果配置为使用 AOF 持久化方式,它会读取 AOF 文件中的所有命令并重新执行它们,以恢复数据库的状态。

8.RDB和AOF的优缺点?

  • RDB

    • 优点:
      1. 适用于全量备份:只有一个紧凑的二进制文件 dump.rdb,非常适合备份、全量复制的场景。
      2. 恢复速度快,RDB 恢复数据的速度远远快于 AOF 的方式
      3. 容灾性好,可以把 RDB 文件拷贝道远程机器或者文件系统张,用于容灾恢复。
    • 缺点:
      1. 实时性低,RDB 是间隔一段时间进行持久化,没法做到实时持久化/秒级持久化。如果在这一间隔事件发生故障,数据会丢失。
      2. 存在兼容问题,Redis 演进过程存在多个格式的 RDB 版本,存在老版本 Redis 无法兼容新版本 RDB 的问题。
  • AOF

    • 优点:
      1. 实时性好,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次命令操作就记录到 aof 文件中一次。
      2. 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
    • 缺点:
      1. AOF 文件比 RDB 文件大,且 恢复速度慢
      2. 数据集大 的时候,比 RDB 启动效率低

9.RDB和AOF如何选择

  1. 一般来说, 如果想达到足以媲美数据库的 数据安全性,应该 同时使用两种持久化功能。在这种情况下,当 Redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整。
  2. 如果 可以接受数分钟以内的数据丢失,那么可以 只使用 RDB 持久化
  3. 有很多用户都只使用 AOF 持久化,但并不推荐这种方式,因为定时生成 RDB 快照(snapshot)非常便于进行数据备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,除此之外,使用 RDB 还可以避免 AOF 程序的 bug。
  4. 如果只需要数据在服务器运行的时候存在,也可以不使用任何持久化方式

10.Redis的数据恢复?

  1. 当 Redis 发生了故障,可以从 RDB 或者 AOF 中恢复数据。
  2. 恢复的过程也很简单,把 RDB 或者 AOF 文件拷贝到 Redis 的数据目录下,如果使用 AOF 恢复,配置文件开启 AOF,然后启动 redis-server 即可。

Redis启动加载数据

Redis 启动时加载数据的流程:

  1. AOF 持久化开启且存在 AOF 文件时,优先加载 AOF 文件
  2. AOF 关闭或者 AOF 文件不存在时,加载 RDB 文件。
  3. 加载 AOF/RDB 文件成功后,Redis 启动成功。
  4. AOF/RDB 文件存在错误时,Redis 启动失败并打印错误信息

11.Redis4.0的混合持久化了解吗?

  1. 重启 Redis 时,我们很少使用 RDB 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。
  2. Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是 自持久化开始到持久化结束 的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小:
  3. 于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

image-20240328091333669

底层数据结构

12.说说Redis的底层数据结构?

  1. Redis 的底层数据结构有
    • 动态字符串(sds)
    • 字典(ht)
    • 双向链表链表(list)
    • 整数集合(intset)
    • 压缩列表(ziplist)
    • 跳跃表(skiplist)

image-20240328091808629

13.跳跃表是如何实现的?原理?

  1. 跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其它节点的指针,从而达到快速访问节点的目的。

image-20240328092218623

  1. ZSet数据结构底层使用跳跃表的原因?

    • 首先,因为 zset 要支持随机的插入和删除,所以它 不宜使用数组来实现,关于排序问题,我们也很容易就想到 红黑树/ 平衡树 这样的树形结构,为什么 Redis 不使用这样一些结构呢?

      • 性能考虑 在高并发的情况下,树形结构需要执行一些类似于 rebalance 这样的可能涉及整棵树的操作,相对来说跳跃表的变化只涉及局部;

      • 实现考虑 在复杂度与红黑树相同的情况下,跳跃表实现起来更简单,看起来也更加直观;

    • 基于以上的一些考虑,Redis 基于 William Pugh 的论文做出一些改进后采用了 跳跃表 这样的结构。

  2. 跳跃表是怎么实现的?

    • Redis的跳跃表由zskiplistNode和skiplist两个结构定义

    • zskiplist结构保存跳跃表节点的相关信息,比如节点的数量,以及指向表头节点和表尾节点的指针等等

    • zskiplistNode结构用于表示跳跃表节点

    • 跳跃表的节点元素类型:

      • 层(level):跳跃表节点的 level 数组可以包含多个元素,每个元素都包含一个指向其它节点的指针,程序可以通过这些层来加快访问其它节点的速度,一般来说,层的数量越多,访问其它节点的速度就越快

      • 前进指针:每个层都有一个指向表尾的前进指针(level[i].forward 属性),用于从表头向表尾方向访问节点。

        我们看一下跳跃表从表头到表尾,遍历所有节点的路径:

        通过前进指针遍历

      • 跨度:层的跨度用于记录两个节点之间的距离。跨度是用来计算排位(rank)的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累计起来,得到的结果就是目标节点在跳跃表中的排位。(例如,箭头连线上的数字就是跨度,即分值

        Redis跳跃表

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/575802.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高效运维|AIRIOT智慧电力运维解决方案

可再生能源的引入带来了能源生产的去中心化和分散化趋势&#xff0c;同时也带来了能源输出的波动性和不确定性。电力运维因此需要更加灵活、智能的解决方案&#xff0c;以适应可再生能源的集成&#xff0c;确保电力系统的稳定运行&#xff0c;传统的电力运维管理方式往往存在如…

大模型 智能体 智能玩具 智能音箱 构建教程 wukong-robot

视频演示 10:27 一、背景 继上文《ChatGPT+小爱音响能擦出什么火花?》可以看出大伙对AI+硬件的结合十分感兴趣,但上文是针对市场智能音响的AI植入,底层是通过轮询拦截,算是hack兼容,虽然官方有提供开发者接口,也免不了有许多局限性(比如得通过特定指令唤醒),不利于我…

DDos系列攻击原理与防御原理

七层防御体系 静态过滤 命中黑名单 对确定是攻击的流量直接加入黑名单&#xff08;源地址命中黑名单直接丢弃&#xff0c;缺乏机动性和扩展性&#xff09; 畸形报文过滤 畸形报文攻击 TCP包含多个标记位&#xff0c;排列组合有规律 • 现象&#xff1a;TCP标记位全为1 …

损坏的RAID5csp

1.解题思路 这道题太抽象了&#xff0c;一开始都没太搞懂在讲啥。。。解决该题需要了解条带、磁盘号的定义。 下图以样例2&#xff0c;输入编号为5的块为例&#xff1a; 请务必加上ios::sync_with_stdio(false),否则会超时只有30分 2.满分代码 #include<iostream> us…

打造高效安全的电池管理 | 基于ACM32 MCU的两轮车充电桩方案

前 言 随着城市化进程的加快、人们生活水平的提高和节能环保理念的普及&#xff0c;越来越多的人选择了电动车作为代步工具&#xff0c;而两轮电动车的出行半径较短&#xff0c;需要频繁充电&#xff0c;因此在城市中设置两轮车充电桩就非常有必要了。城市中的充电桩不仅能解决…

Cocos2dx-lua ScrollView[三]高级篇

一.概述 本文缩写说明&#xff1a;sv ScrollView, cell代表ScrollView的一个子节点 本文介绍sv的一种封装类库&#xff0c;来实现快速创建sv&#xff0c;有如下几个优点&#xff1a; 1.item的位置通过参数控制&#xff0c;提高开发效率 2.免去了调用sv的API&#xff0c;提…

短视频矩阵系统究竟怎么样,如何实现一站式精准获客?

在数字化时代的浩渺海洋中&#xff0c;短视频如同一股汹涌的浪潮&#xff0c;席卷了众多企业的营销战略。如何在这样的背景下&#xff0c;驾驭这股浪潮&#xff0c;将其转化为获客的强大动力&#xff0c;已成为众多企业家们心中的疑问。而蜘蛛短视频矩阵系统的出现&#xff0c;…

主流公链 - Monero

Monero: 加密货币的隐私标杆 1. 简介 Monero&#xff08;XMR&#xff09;&#xff0c;世界语中货币的意思&#xff0c;是一种去中心化的加密货币&#xff0c;旨在提供隐私和匿名性。与比特币等公开区块链不同&#xff0c;Monero专注于隐私保护&#xff0c;使用户的交易记录和余…

车载以太网AVB交换机 gptp透明时钟 5口 全千兆 SW1500

全千兆车载以太网交换机 一、产品简要分析 5端口千兆车载以太网交换机&#xff0c;包含4个通道的1000BASE-T1接口使用罗森博格H-MTD和泰科MATEnet双接口&#xff0c;1个通道1000BASE-T标准以太网(RJ45接口)&#xff0c;可以实现车载以太网多通道交换&#xff0c;千兆和百兆车载…

Unity 学习日记 12.小球撞击冰块游戏

目录 1.准备场景 2.让小球动起来 3.用鼠标把小球甩出去 4.加入鼠标点击小球的判断 5.小球与冰块的碰撞测试 6.撞击后销毁冰块 ​编辑 7.显示游戏计时 8.显示扔球次数 9.显示剩余冰块个数 10.游戏结束 11.完整代码 下载源码 UnityPackage 最终效果&#xff1a; 1.准…

STM32和GD32内部时钟与外部时钟讲解

STM32F103为例: 1. 当 HSI 被用作 PLL 时钟输入时,可以实现的最大系统时钟频率为 64 MHz。 2. 要使 USB 功能可用,必须同时启用 HSE 和 PLL,并使 USBCLK 运行在 48 MHz。 3. 要实现 ADC 转换时间为 1 s,APB2 必须为 14 MHz、28 MHz 或 56 MHz。 ①. HSE = 高速外部时钟信号…

Adobe最近推出了Firefly AI的结构参考以及面向品牌的GenStudio

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…