六、Redis之数据持久化及高频面试题

6.1 数据持久化

官网文档地址:https://redis.io/docs/manual/persistence/

Redis提供了主要提供了 2 种不同形式的持久化方式:

  • RDB(Redis数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照。
  • AOF(Append Only File):AOF 持久化记录服务器接收到的每个写操作,在服务器启动时再次播放,重建原始数据集。 命令使用与 Redis 协议本身相同的格式以仅附加方式记录。 当日志变得太大时,Redis 能够在后台重写日志。

6.1.1 RDB

6.1.1.1 什么是 RDB

在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是Snapshot快照,它恢复时是将快照文件直接读到内存里。

6.1.1.2 如何备份

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束后,再用这个临时文件替换上次持久化好的文件。主进程不进行任何的IO操作,这样就保证了较高的性能。如果需要进行大规模数据的恢复,并且对于数据恢复的不完整性非常敏感,那么RDB方式会比AOF方式更加高效。注意点:最后一次持久化后的数据可能丢失。

6.1.1.3 Fork

Fork的作用是复制一个与当前进程一样的进程,且新进程内的所有数据(变量,环境变量,程序计数器等等)数值都和原进程一直,但它是一个全新的进程,并且作为原进程的子进程。

在 Linux 程序中,fork() 会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,出于效率考虑,Linux 中引入了“写时复制技术”。

一般情况下,父进程和子进程会共用一段物理内存,只有进程空间的各段内容发生变化时,才会将父进程的内容复制一份给子进程。
在这里插入图片描述

6.1.1.4 备份和恢复
#dump.rdb存放在两个位置上
1、root\          目录    =====>通过正常的启动和关闭所保存的地址
2、var\lib\redis\ 目录    =====>通过 systemctl restart redis 命令所生成的
我们如果要进行备份还原的实验的话,确定目标地址,并选择适配的命令去观察变化
#步骤1:清空数据库
FLUSHALL
#步骤2:
客户端退出  exit
服务器关闭  ctrl+c
#步骤3:观察root\ 内的dump.rdb文件大小 发现是 92
#步骤4:正常启动redis并登录客户端
服务器启动  redis-server
客户端登录  redis-cli
#步骤5:保存了六组信息
set k1 v1 
.......
set k6 v6
#步骤7:
客户端退出  exit
服务器关闭  ctrl+c
#步骤8:观察root\ 内的dump.rdb文件大小 发现是 139
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#步骤9 将139大小的dump.rdb复制 命名为 dump.rdb.back
cp dump.rdb dump.rdb.back
#步骤10 删除dump.rdb
rm -f dump.rdb
#步骤11:正常启动redis并登录客户端,查看数据
服务器启动  redis-server
客户端登录  redis-cli
客户端查看  keys *   ======================>  数据没有了
#步骤12
客户端退出  exit
服务器关闭  ctrl+c
#步骤13:观察root\ 内的dump.rdb文件大小 发现是 92
#步骤14:将139大小的dump.rdb.back复制 命名为 dump.rdb
#步骤15:正常启动redis并登录客户端,查看数据
服务器启动  redis-server
客户端登录  redis-cli
客户端查看  keys *   ======================>  数据存在

6.1.2 AOF

6.1.2.1 什么是AOF

以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据。简单说,Redis 重启时会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

在Redis的默认配置中AOF(Append Only File)持久化机制是没有开启的,要想使用AOF持久化需要先开启此功能。AOF持久化会将被执行的写命令写到AOF文件末尾,以此来记录数据发生的变化,因此只要Redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集。

6.1.2.2 持久化流程

在这里插入图片描述

  1. 客户端的请求写命令会被append追加到AOF缓冲器内。

  2. AOF缓冲区根据AOF持久化策略,将sync同步到磁盘的AOF文件中

  3. AOF文件大小超过了重写策略或手动重写时,会对AOF文件进行重写,以压缩AOF文件容量

  4. Redis服务重启时,会重新load加载AOF文件中的写操作,已达到数据恢复的目的。

6.1.2.3 备份和恢复
#步骤1 开启AOF
修改 redis.conf 配置文件:
- 通过修改redis.conf配置中`appendonly yes`来开启AOF持久化
- 通过appendfilename指定日志文件名字(默认为appendonly.aof)
- 通过appendfsync指定日志记录频率
选项同步频率
always每个redis写命令都要同步写入硬盘,严重降低redis速度
everysec每秒执行一次同步显式的将多个写命令同步到磁盘
no由操作系统决定何时同步
#步骤2 重启服务以确保配置文件被重新读过
systemctl restart redis
#步骤3 在var/lib/redis目录内找到了 appendonly.aof
#步骤4:登录客户端并保存数据
客户端登录  redis-cli
#步骤5:保存了六组信息
set k1 v1 
.......
set k6 v6
#步骤6:基于客户端关闭连接和服务
SHUTDOWN
#步骤7:在var/lib/redis目录内找到了 appendonly.aof  (大小由0变成了一组数值)
#步骤8:复制appendonly.aof 
cp appendonly.aof  appendonly.aof.back
#步骤9:重启服务连接客户端
systemctl restart redis
客户端登录  redis-cli
#步骤10:清空数据库并停止服务
FLUSHDB
SHUTDOWN
#步骤11:在var/lib/redis目录内找到了 appendonly.aof  (大小由一组数值变成了另一组数值 后数值>前数值)
#步骤12:复制appendonly.aof.back
cp appendonly.aof.back  appendonly.aof
#步骤13:重启服务连接客户端
systemctl restart redis
客户端登录  redis-cli
#步骤14:检查数据
keys *

6.1.3 如何选择

那么,在开发中是选择 RDB 还是选择 AOF 来持久化呢?

官网建议如下:

Ok, so what should I use?

The general indication you should use both persistence methods is if you want a degree of data safety comparable to what PostgreSQL can provide you.

If you care a lot about your data, but still can live with a few minutes of data loss in case of disasters, you can simply use RDB alone.

There are many users using AOF alone, but we discourage it since to have an RDB snapshot from time to time is a great idea for doing database backups, for faster restarts, and in the event of bugs in the AOF engine.

The following sections will illustrate a few more details about the two persistence models.

  • RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储

  • AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.

  • Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大

  • 只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.

  • 同时开启两种持久化方式

  • 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据, 因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

  • RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?

  • 建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份), 快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。

6.2 高频面试题

6.2.1 缓存穿透

6.2.1.1 描述

用户想要查询某个数据,在 Redis 中查询不到,即没有缓存命中,这时就会直接访问数据库进行查询。当请求量超出数据库最大承载量时,就会导致数据库崩溃。这种情况一般发生在非正常 URL 访问,目的不是为了获取数据,而是进行恶意攻击。

在这里插入图片描述

6.2.1.2 现象
  1. 应用服务器压力变大

  2. Redis缓存命中率降低

  3. 一直查询数据库

6.2.1.3 原因

一个不存在缓存及查询不到的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。

6.2.1.4 解决

① 对空值缓存:如果一个查询数据为空(不管数据是否存在),都对该空结果进行缓存,其过期时间会设置非常短。

② 设置可以访问名单:使用bitmaps类型定义一个可以访问名单,名单id作为bitmaps的偏移量,每次访问时与bitmaps中的id进行比较,如果访问id不在bitmaps中,则进行拦截,不允许访问。

③ 采用布隆过滤器:布隆过滤器可以判断元素是否存在集合中,他的优点是空间效率和查询时间都比一般算法快,缺点是有一定的误识别率和删除困难。

④ 进行实时监控:当发现 Redis 缓存命中率急速下降时,迅速排查访问对象和访问数据,将其设置为黑名单。

6.2.2 缓存击穿

6.2.2.1 描述

key中对应数据存在,当key中对应的数据在缓存中过期,而此时又有大量请求访问该数据,由于缓存中过期了,请求会直接访问数据库并回设到缓存中,高并发访问数据库会导致数据库崩溃。

在这里插入图片描述

6.2.2.2 现象
  1. 数据库访问压力瞬时增加

  2. Redis中没有出现大量 Key 过期

  3. Redis正常运行

  4. 数据库崩溃

6.2.2.3 原因

由于 Redis 中某个 Key 过期,而正好有大量访问使用这个 Key,此时缓存无法命中,因此就会直接访问数据层,导致数据库崩溃。

最常见的就是非常“热点”的数据访问。

6.2.2.4 解决

① 预先设置热门数据:在redis高峰访问时期,提前设置热门数据到缓存中,或适当延长缓存中key过期时间。

② 实时调整:实时监控哪些数据热门,实时调整key过期时间。

③ 对于热点key设置永不过期。

6.2.3 缓存雪崩

6.2.3.1 描述

key中对应数据存在,在某一时刻,缓存中大量key过期,而此时大量高并发请求访问,会直接访问后端数据库,导致数据库崩溃。

注意:缓存击穿是指一个key对应缓存数据过期,缓存雪崩是大部分key对应缓存数据过期。

正常情况下:

在这里插入图片描述

缓存失效瞬间:

在这里插入图片描述

6.2.3.2 现象
  • 数据库压力变大导致数据库和 Redis 服务崩溃
6.2.3.3 原因

在极短时间内,查询大量 key 的集中过期数据。

6.2.3.4 解决

① 构建多级缓存机制:nginx缓存 + redis缓存 + 其他缓存。

② 设置过期标志更新缓存:记录缓存数据是否过期,如果过期会触发另外一个线程去在后台更新实时key的缓存。

③ 将缓存可以时间分散:如在原有缓存时间基础上增加一个随机值,这个值可以在1-5分钟随机,这样过期时间重复率就会降低,防止大量key同时过期。

④ 使用锁或队列机制:使用锁或队列保证不会有大量线程一次性对数据库进行读写,从而避免大量并发请求访问数据库,该方法不适用于高并发情况。

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

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

相关文章

有限合伙协议书(模板)下

第六章 合伙事务的执行 第十七条 有限合伙人不执行合伙事务,对外不具有代表权。有限合伙企业由普通合伙人执行合伙事务。 第十八条 经全体合伙人一致同意可以委托一个普通合伙人(也可以委托数个普通合伙人)对外代表合伙企业,执…

华为机考入门python3--(14)牛客14-字符串排序

分类:列表、排序 知识点: 字典序排序 sorted(my_list) 题目来自【牛客】 def sort_strings_by_lex_order(strings): # 使用内置的sorted函数进行排序,默认是按照字典序排序 sorted_strings sorted(strings) # 返回排序后的字符串列…

Leetcode 236.二叉树的最近公共祖先

题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的…

原子变量和原子操作

一、什么是原子操作 通常某一个变量的操作对应的CPU指令是大于一个的,在多线程环境下,为了确保对共享变量的操作在执行时不会被干扰,从而避免竞态条件和死锁等问题,使用原子变量。 原子变量可以看作是一种特殊的类型&#xff0c…

C++ 动态规划 计数类DP 整数划分

一个正整数 n 可以表示成若干个正整数之和,形如:nn1n2…nk ,其中 n1≥n2≥…≥nk,k≥1 。 我们将这样的一种表示称为正整数 n 的一种划分。 现在给定一个正整数 n ,请你求出 n 共有多少种不同的划分方法。 输入格式 共一行&…

Linux入门(1)Linux介绍

目录 1. 认识 Linux, 了解 Linux 的相关背景 1.发展史 2. 学会如何使用云服务器 3. 掌握使用远程终端工具 xshell 登陆 Linux 服务器 1. 认识 Linux, 了解 Linux 的相关背景 1.发展史 学习Linux系统编程,你可能要问Linux从哪里来?它是怎么发展的&am…

小游戏和GUI编程(7) | SimpleNN 界面源码解析

小游戏和GUI编程(7) | SimpleNN 界面源码解析 0. 简介 SimpleNN 是 AdamYuan 在高中一年级时用 1 天时间写出来的简易 CNN, 使用 SFML 做 UI, 用于交互式输入手写数字,这个数字被训练好的 CNN 网络执行推理得到识别结果, 它的运行效果如下: 这一篇我们…

【项目】高并发内存池

高并发内存池 【项目】高并发内存池项目介绍这个项目做的是什么? 内存池相关知识池化技术内存池malloc 定长内存池的实现高并发内存池整体框架设计ThreadCache对齐规则封装FreeList类封装thread cache类TLS无锁访问 CenctralCache整体设计页号规定span结构SpanList结…

2.8:Maefile、计算单词个数、判断文件类型、单词逆置

1.有main.c,test.c,test1.c,创建Makefile 程序代码: Makefile: 1 CCgcc2 EXEhello3 OBJS$(patsubst %.c,%.o,$(wildcard *.c))4 CFLAGS-c -o5 all:$(EXE)6 7 #hello依赖test.o main.o8 $(EXE):$(OBJS)9 $(CC) $^ -o $10 …

浅析Linux追踪技术之ftrace:Tracepoint

文章目录 概述Tracepoint使用定义Tracepoint添加Tracepoint调用 Tracepoint数据结构TRACE_EVENT实现DECLARE_TRACE__DECLARE_TRACE trace_xxx函数相关参考 概述 Tracepoint(跟踪点)是添加到代码流程中的调用点,并且允许开发者注册自定义的回…

TCP高频知识点

本篇文章主要讲述一下在面试过程中TCP的高频知识点 1.TCP三次握手流程图: 客户端发送一个SYN(同步)报文段给服务器,选择一个初始序列号,并设置SYN标志位为1。服务器接收到客户端的SYN报文段后,回复一个ACK&#xff08…

webgis后端安卓系统部署攻略,超详细Termux攻略

目录 前言 一、将后端项目编译ARM64 二、安卓手机安装termux 1.更换为国内源 2.安装ssh远程访问 3.安装文件远程访问 三、安装postgis数据库 1.安装数据库 2.数据库配置 3.数据导入 四、后端项目部署 五、自启动设置 总结 前言 因为之前一直做的H5APP开发&#xf…