Redis:只刷面试题,怎可能进大厂,多理解原理(RDB 持久化、AOF持久化)

aas 因为Redis 是内存数据库,它将自己的数据库状态储存在内存里面,所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。为了解决这个问题, Redis 提供了RDB 持久化功能这个功能可以将Redis 在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。
asdsadasdasdasdsadasdasdasdsadassdasdsasdsadsdasdasdsadasdasdsadasdsadassadasdas————《Redis设计与实现》


RDB持久化:

asdasa RDB 待久化既可以手动执行,也可以根据服务器配置选项定期执行。

asdasa 功能:将某个时间点上的数据库状态保存到一个RDB 文件。

asdasaRDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件通过该文件可以还原生成RDB 文件时的数据库状态。
在这里插入图片描述


RDB 文件的创建与载入:

aa ⒈有两个 Redis 命令可以用于生成 RDB文件:

adsa ① SAVE: SAVE 命令会阻塞 Redis 服务器进程, 直到RDB 文件创建完毕为止(在服务器进程阻塞期间,服务器不能处理任何命令请求,即客户端发送的所有命令请求都会被拒绝。)。

sdssa② BGSAVE: BGSAVE 命令会派生出一个子进程,然后由子进程负责创建RDB 文件,服务器进程(父进程)继续处理命令请求。

aa ⒉RDB 文件的 载入工作是在 服务器启动时自动执行的。 只要Redis 服务器在启动时检测到RDB 文件存在,它就会自动载入RDB 文件。

aa ⒊启用流程:因为AOF文件的更新频率通常比RDB 文件的更新频率高,所以:

adsa ①、如果服务器开启了AOF 持久化功能,那么服务器会优先使用AOF 文件来还原数据库状态。

adsa ②、只有在AOF 持久化功能处于关闭状态时, 服务器才会使用RDB 文件来还原数据库状态。
在这里插入图片描述
aa ⒋BGSAVE 命令执行时的服务器状态:

aadsad因为BGSA VE 命令的保存工作是由子进程执行的,所以在子进程创建RDB 文件的过程中,Redis 服务器仍然可以继续处理客户端的命令请求。但是要注意:SAVE 、BGSAVE 、BGREWRITEAOF 这三个命令。

aadsdas①、服务器禁止 SAVE 命令和 BGSAVE 命令同时执行是为了避免父进程( 服务器进程)和子进程同时执行两个rdbSave 调用,防止产生竞争条件。
aadsdas②、在BGSAVE 命令执行期间,客户端发送的BGSAVE 命令会被服务器拒绝因为同时执行两个BGSAVE 命令也会产生竞争条件。
aadsdas③、BGREWRITEAOF 和BGSAVE 两个命令不能同时执行:因为 BGREWRITEAOF 和 BGSAVE 两个命令的实际工作都由子进程执行,所以这两个命令在操作方面并没有什么冲突的地方,不能同时执行它们只是一个 性能方面的考虑 一并发出两个子进程,并且这两个子进程都同时执行 大量的磁盘写入操作,这怎么想都不会是一个好主意。

aa ⒌自动 间隔性 保存

aadsad因为 BGSAVE 命令可以在不阻塞服务器进程的情况下执行,所以 Redis让服务器每隔一段时间自动执行一次BGSAVE 命令。 (用户可以通过save 选项设置多个保存条件,但只要其中任意一个条件被满足, 服务器就会执行BGSAVE 命令)

aadsdas①、服务器在900 秒之内,对数据库进行了至少1 次修改。

aadsdas②、服务器在300 秒之内,对数据库进行了至少10 次修改。

aadsdas③、服务器在6 0 秒之内,对数据库进行了至少10000 次修改。

aadsad这些条件保存到了 redisServer结构的saveparams 数组属性中:
在这里插入图片描述
aa ⒍dirty 计数器和lastsave 属性

aadsad除了 savepararns 数组之外,服务器状态还维持着一个 dirty 计数器,以及一个 lastsave 属性:

aadsdas①、dirty 计数器:记录距离上一次成功执行SAVE 命令或者 BGSAVE 命令之后,服务器对数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、删除、更新等操作)。
aadsdas②、lastsave 属性:是一个UNIX 时间戳,记录了服务器 上一次成功执行SAVE 命令或者BGSAVE 命令的时间
在这里插入图片描述
aa ⒎检查保存条件是否满足:Redis 的服务器 周期性操作函数serverCron 默认每隔100 毫秒就会执行一次该函数用于对正在运行的服务器进行维护,它的其中一项工作就是检查save 选项所设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE命令。


ROB 文件结构:

aaRDB文件结构:
在这里插入图片描述

adsadsa 大写单词:标示常量。全小写单词:标示变量和数据。

adsadsaREDIS : 长度为 5 字节,保存着" REDIS " 五个字符。程序可以在载入文件时,快速检查所载入的文件是否RDB 文件。(因为RDB保存的是二进制文件,而不是C 宇符串,所以尾部不用加’\0’ )。

adsadsadb_version属性: 长度为 4 字节,记录了版本号,比如" 000 6" 就代表RDB 文件的 版本,为第六版。

adsadsadatabases 属性: 部分包含着零个或任意多个数据库,以及各个数据库中的键值对数据。

adsadsaEOF: 常量的长度为 1 字节,这个常扯标志着 RDB 文件 正文内容的结束

adsadsacheck_sum: 是一个 8 字节长的无符号整数,保存着一个 校验和,这个校验和是程序通过对前四个部分的内容进行计算得出。

aa ⒉databases 部分:

adsadsa一个RDB 文件的databases 部分 可以保存任意多个非空数据库

adsadsaeg:
在这里插入图片描述

adsadsaSELECTDB 属性: 长度为 1 字节,表示 接下来要读入的是一个数据库号码

adsadsadb_number属性: 保存着一个数据库号码,根据号码的大小不同,这个部分的长度可以是 1 字节、2 字节或者5 字节。(服务器会调用SELECT命令,根据读入的数据库号码进行数据库切换)

adsadsakey_value_pairs属性: 部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起。
在这里插入图片描述在这里插入图片描述
aa ⒊key_value_pairs 部分:

adsadsaRDB 文件中的每个key_value_pairs 部分都保存了一个或以上数量的键值对,如果键值对带有过期时间的话,那么键值对的过期时间也会被保存在内。
adsadsaeg:
adsdsaadsa①、不带过期时间的键值对 在RDB 文件中由三部分组成:
在这里插入图片描述
adsdsdsadasaadsaTYPE属性:记录了value 的类型。(REDIS_ROB_TYPE_STRING…)
adsdsaadsa②、带过期时间的键值对 在RDB 文件中由四部分组成:
在这里插入图片描述
adsdsdsadasaadsaEXPIRETIME_MS 属性: 长度为1 字节,是一个以毫秒为单位的过期时间

adsdsdsadasaadsams属性: 是一个8 字节长的带符号整数,记录着一个以毫秒为单位的UNIX 时间戳,这个时间戳就是键值对的过期时间。


RDB持久化总结:

addsa①、RDB 文件用于保存和还原Redis 服务器所有数据库中的所有键值对数据。

addsa②、SAVE 命令由服务器进程直接执行保存操作,所以该命令会阻塞服务器。BGSAVE 令由子进程执行保存操作,所以该命令不会阻塞服务器。

addsa③、服务器状态中会保存所有用save 选项设置的保存条件,当任意一个保存条件被满足时,服务器会自动执行BGSAVE 命令。

addsa④、RDB 文件是一个 经过压缩的二进制文件,由多个部分组成。

addsa⑤、对于不同类型的键值对, RDB 文件会使用不同的方式来保存它们。

💖💗💗💗💗💗💗💗💗💗💖💖💖💖💖💖💖💖-💖💗💗💗💗💗💗💗💗💗💖💖💖💖💖💖💖💖-💖💗💗💗

AOF持久化:

addsa除了RDB 持久化功能之外, Redis 还提供了AOF持久化功能。与RDB 持久化通过保存数据库中的键值对来记录数据库状态不同, AOF 持久化是通过保存Redis 服务器所执行的写命令来记录数据库状态的。
在这里插入图片描述
addsa被写入AOF 文件的所有命令都是以Redis 的命令请求协议格式保存的,因为Redis 的命令请求协议是纯文本格式,所以我们 可以直接查看AOF文件

aa ⒈AOF 持久化的实现:

addsaAOF 持久化功能的实现可以分为 命令追加、文件写入、文件同步 三个步骤。

adsddsa①、命令追加: 当AOF 持久化功能处于打开状态时,服务器在执行完一个写命令之后, 会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区 的末尾:
在这里插入图片描述
adsddsa②、AOF 文件的写入与同步: 当AOF 持久化功能处于打开状态时,服务器在执行完一个写命令之后, 会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区 的末尾。Redis 的服务器进程就是一个事件循环,在服务器每次结束一个事件循环之前,它都会调用 flushAppendOnlyFile 函数考虑是否需要将aof_buf 缓冲区中的内容写入和保存到AOF 文件里面。

adsdddssa【注】:flushAppendOnlyFile 函数行为由服务器配置的appendfsync 选项的值来决定。如果用户没有主动为 appendfsync 选项设置值,那么appendfsync 选项的默认值为everysec
在这里插入图片描述
adsddsaddssa 服务器配置 appendfsync 选项的值直接决定 AOF 持久化功能的 效率和安全性。always 的效率是 appendfsync 选项三个值当中最慢的一个, no 模式下的AOF 文件写入速度总是最快的,单次同步时长通常是三种模式中时间最长的。

adsddsa⑴ 文件写入: 为了提高文件的写入效率,在现代操作系统中,当用户调用 write 函数,将一些数据写入到文件的时候,操作系统通常会将写入数据暂时保存在一个内存缓冲区里面,等到缓冲区的空间被填满、或者超过了指定的时限之后,才真正地将缓冲区中的数据写入到磁盘里面。

adsddsa⑵ 文件写入带来的问题: 虽然 提高了效率,但也为写入数据带来了安全问题,因为如果计算机发生停机,那么保存在内存缓冲区里面的写入数据将会丢失。

adsddsa⑶ 解决方法: 系统提供了 fsyncfdatasync 两个 同步函数,它们可以强制让操作系统立即将缓冲区中的数据写入到硬盘里面,从而确保写入数据的安全性。

aa ⒉AOF 文件的载入与数据还原:

addsa AOF文件 的载入过程:在这里插入图片描述
addssa 创建一个不带网络连接的伪客户端的理由: 因为Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所使用的命令直接来源于 AOF 文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行 AOF 文件保存的写命令。

aa ⒊AOF 文件重写的实现:

addsa 虽然 Redis 将生成新AOF 文件替换旧AOF 文件的功能命名为"AOF 文件重写“,但实际上, AOF 文件重写并不需要对现有的AOF 文件进行任何读取、分析或者写入操作,这个功能是通过读取服务器当前的数据库状态来实现的。

addsaAOF文件重写的实现原理 首先从数据库中读取键现在的值, 然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。

addsa因为 aof_rewrite 函数生成的 新 AOF 文件 只包含还原当前数据库状态所必须的命令,所以新AOF 文件不会浪费任何硬盘空间。

addsa 在实际中,为了避免在执行命令时造成客户端输入缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这四种可能会带有多个元素的键时,会先检查键所包含的元素数量,如果元素的数量 redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD 常量的值,那么重写程序将使用多条命令来记录键的值,而不单单使用一条命令。
addsa在目前版本中, REDIS_AOF_REWRIT E_IT EMS _PER_CMD 常量的值为64,也就是说单条指令的元素数量最多64个。

aa ⒊AOF 后台重写:

addsa 因为 Redis 不希望 AOF 重写造成服务器无法处理请求,所以 Redis 决定将 AOF 重写程序放到 子进程(不是子线程) 里执行(因为Redis 服务器使用 单个线程 来处理命令请求,会造成阻塞)

addsa AOF 重写程序放到 子进程 里执行的 目的

adddsaasa①、子进程进行 AOF 重写期间,服务器进程(父进程)可以继续处理命令请求。

adddsaasa②、子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

addsa AOF 重写使用子进程带来的问题:

adddsaasa因为子进程在进行 AOF 重写期间,服务器进程还需要继续处理命令请求,而新的命令可能会对现有的数据库状态进行修改,从而使得服务器当前的数据库状态和重写后的 AOF 文件所保存的 数据库状态不一致。

adddssa 问题解决:

adddsaasa为了解决这种数据不一致问题, Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,Redis 服务器执行完一个写命令之后,它会同时将这个写命令发送给 AOF 缓冲区 和AOF 重写缓冲区。
在这里插入图片描述
addsa AOF 重写缓冲区的作用:

adddsaasa①、AOF 缓冲区的内容会 定期 被写入和同步到 AOF 文件,对现有 AOF 文件的处理工作会如常进行。

adddsaasa②、从创建子进程开始,服务器执行的所有写命令都会被记录到 AOF 重写缓冲区里面。

addsa AOF 重写完成后 信号处理函数 的作用:

adddsaasa当子进程完成 AOF 重写工作之后,它会向父进程发送一个信号,父进程在接到该信号之后,会调用一个 信号处理函数,并执行以下工作:

adddsaasa①、写入:将 AOF 重写缓冲区中的所有内容写入到新 AOF 文件中,这时新 AOF 文件所保存的数据库状态将和服务器当前的数据库状态一致。
adddsaasa②、改名:对新的 AOF 文件进行改名,原子地 覆盖现有的 AOF 文件,完成新旧两个 AOF 文件的替换。

adddsaasa在整个 AOF 后台重写过程中,只有信号处理函数执行时会对服务器进程(父进程)造成阻塞,在其他时候, AOF 后台重写都不会阻塞父进程,这将AOF 重写对服务器性能造成的影响降到了最低。


AOF持久化总结:

addsa①、AOF 文件 通过保存所有修改数据库的写命令 请求来记录服务器的数据库状态。

addsa②、AOF 文件中的所有命令都以 Redis 命令请求协议的格式保存。

addsa③、命令请求会先保存到 AOF 缓冲区里面,之后再定期写入并同步到 AOF 文件。

addsa④、appendfsync 选项的不同值对 AOF 持久化功能的安全性以及 Redis 服务器的性能有很大的影响。

addsa⑤、服务器只要载入并重新执行保存在 AOF 文件中的命令, 就可以还原数据库本来的状态。

addsa⑥、AOF 重写可以产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
addsa⑦、AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的, 程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。

addsa⑧、在执行 BGREWRITEAOF 命令时, Redis 服务器会维护一个AOF 重写缓冲区,该缓冲区会在子进程创建新AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。

💖感谢各位的暴击三连💖

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值