【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.mfbz.cn/a/497426.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE】初识线程,线程与进程的区别

文章目录 ✍线程是什么&#xff1f;✍线程和进程的区别✍线程的创建1.继承 Thread 类2.实现Runnable接口3.匿名内部类4.匿名内部类创建 Runnable ⼦类对象5.lambda 表达式创建 Runnable ⼦类对象 ✍线程是什么&#xff1f; ⼀个线程就是⼀个 “执行流”. 每个线程之间都可以按…

Github 2024-03-28Go开源项目日报Top10

根据Github Trendings的统计,今日(2024-03-28统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目9非开发语言项目1Ollama: 本地大型语言模型设置与运行 创建周期:248 天开发语言:Go协议类型:MIT LicenseStar数量:42421 个Fork数量:…

vue组件弹窗窗

import { createApp } from vue; import { Popup } from vant;const app createApp(); app.use(Popup); 有这样的一个效果 在手机上很美观 不错 建议大家使用

HarmonyOS实战开发-实现一个计步器卡片应用

介绍 本篇Codelab基于Stage模型实现带有卡片的计步应用&#xff0c;用于介绍卡片的开发及生命周期实现。需要完成以下功能&#xff1a; 消息通知栏&#xff0c;通知用户今天所行走步数。元服务卡片&#xff0c;在桌面上添加2x2或2x4规格元服务卡片&#xff0c;能看到步数变化…

论文问卷的六类分析思路

很多同学在写论文时&#xff0c;会选择通过收集问卷来获取研究所需的数据。然而&#xff0c;问卷收集完成后&#xff0c;如何对这些数据进行有效的分析&#xff0c;成为了一个重要的问题。这么多的问卷数据摆在面前&#xff0c;该如何进行分析呢&#xff1f; SPSSAU从问卷设计…

docker 部署 gitlab-ce 16.9.1

文章目录 [toc]拉取 gitlab-ce 镜像创建 gitlab-ce 持久化目录启停脚本配置配置 gitlab-ce编辑 gitlab-ce 配置文件重启 gitlab-ce配置 root 密码 设置中文 gitlab/gitlab-ce(需要科学上网) 拉取 gitlab-ce 镜像 docker pull gitlab/gitlab-ce:16.9.1-ce.0查看镜像是不是有 Vo…

图论之路径条数专题

一直忙着金工实习蓝桥杯&#xff0c;好久没有看图论了&#xff0c;今天就小试几题享受下被虐的快感。 1.最短路拓扑 首先来几个结论&#xff1a; 1.最短路图没有环&#xff08;可以用反证法证明&#xff09; 2.dis[u]edge[u,v]dis[v]&#xff0c;那么u,v端点的边一定在最短路…

【已修复】iPhone13 Pro 长焦相机水印(黑斑)修复 洗水印

iPhone13 Pro 长焦相机水印&#xff08;黑斑&#xff09;修复 洗水印 问题描述 iPhone13 Pro 后摄3倍相机有黑色斑点&#xff08;水印&#xff09;&#xff0c;如图所示&#xff0c; 后摄相机布局如图所示&#xff0c; 修复过程 拆机过程有风险&#xff0c;没有把握最好不要…

Git--08--Git分支合并操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Git分支合并操作案例流程客户端&#xff1a;GitExtensions操作步骤&#xff1a;A操作步骤&#xff1a;B操作步骤&#xff1a;C操作步骤&#xff1a;D操作步骤&#…

NanoMQ的安装与部署

本文使用docker进行安装&#xff0c;因此安装之前需要已经安装了docker 拉取镜像 docker pull emqx/nanomq:latest 相关配置及密码认证 创建目录/usr/local/nanomq/conf以及配置文件nanomq.conf、pwd.conf # # # # MQTT Broker # # mqtt {property_size 32max_packet_siz…

每日一题--最长连续序列

洛阳春-岑参 人到洛阳花似锦&#xff0c;偏我来时不逢春。 谁道三冬无春色&#xff0c;冰山高处万里银 目录 题目描述 思路分析 方法及其时间复杂度 法一 暴力枚举&#xff1a; 法二 哈希表遍历&#xff1a; 法三 并查集&#xff1a; 个人总结 题目描述 128. 最长连续序…

【网安小白成长之路】3.MySQL环境配置以及常用命令(增删改查)

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f51e; 《网安小白成长之路(我要变成大佬&#x1f60e;&#xff01;&#xff01;)》真实小白学习历程&#xff0c;手把手带你一起从入门到入狱&#x1f6ad; &…

Day53:WEB攻防-XSS跨站SVGPDFFlashMXSSUXSS配合上传文件添加脚本

目录 MXSS UXSS&#xff1a;Universal Cross-Site Scripting HTML&SVG&PDF&SWF-XSS&上传&反编译(有几率碰到) SVG-XSS PDF-XSS Python生成XSS Flash-XSS 知识点&#xff1a; 1、XSS跨站-MXSS&UXSS 2、XSS跨站-SVG制作&配合上传 3、XSS跨站-…

项目模块—实现抑郁测评(小程序)

script <script setup> import { ref } from "vue";//控制轮播图页码 let current ref(0);//答题逻辑 const add (value) > {if (current.value < 9) {current.value current.value 1;} else {uni.switchTab({url: "/pages/my/my",});} }…

「DevExpress中文教程」如何将DevExtreme JS HTML编辑器集成到WinForms应用

在本文中我们将演示一个混合实现&#xff1a;如何将web UI工具集成到WinForms桌面应用程序中。具体来说&#xff0c;我们将把DevExtreme JavaScript WYSIWYG HTML编辑器(作为DevExtreme UI组件套件的一部分发布的组件)集成到Windows Forms应用程序中。 获取DevExtreme v23.2正式…

Vue3进阶教程-第2学堂小商城实战课程前言

该教程为进阶教程&#xff0c;如果你还不了解Vue3的基础知识&#xff0c;可以先前往Vue3基础教程&#xff0c;从入门到实战。 学习时遇到的任何疑问都欢迎在相应课文页面下方的问答区进行提问哦 我能学到什么&#xff1f; 编程写法千千万&#xff0c;实现需求是第一。 教程中…

阿里云服务器租用价格表-2024最新(附报价单)

2024年阿里云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网aliyunfuwuqi.com整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新…

数据结构——链表(练习题)

大家好&#xff0c;我是小锋我们继续来学习链表。 我们在上一节已经把链表中的单链表讲解完了&#xff0c;大家感觉怎么样我们今天来带大家做一些练习帮助大家巩固所学内容。 1. 删除链表中等于给定值 val 的所有结点 . - 力扣&#xff08;LeetCode&#xff09; 我们大家来分…

登录拦截器

目录 &#x1f388;1.登陆拦截器的使用 &#x1f38a;2.ThreadLocal的简单使用 &#x1f383;3.登录拦截器拦截和放行配置 1.登陆拦截器的使用 创建一个拦截器类&#xff0c;必须让其实现HandlerInterceptor接口 1.获取前端的token 2.判断token是否为空 3.若为空&#xff…

蓝桥杯基础练习详细解析(四)——Fibonacci费伯纳西数列(题目分析、代码实现、Python)

试题 基础练习 Fibonacci数列 提交此题 评测记录 资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 Fibonacci数列的递推公式为&#xff1a;FnFn-1Fn-2&#xff0c;其…