【Redis】3. Redis持久化方案

您所在的位置:网站首页 redis持久化的作用 【Redis】3. Redis持久化方案

【Redis】3. Redis持久化方案

2023-06-26 17:26| 来源: 网络整理| 查看: 265

持久化

Redis持久化就是将内存中的数据存储到硬盘中。

持久化的目的就是为了保障数据不丢失,因为内存只要一断电就会清空数据。

Redis官方提供了两种持久化机制:

Snapshot(快照RDB) AOF(Append Only File只追加日志文件)

当Snapshot和AOF同时开启时,Redis会采用AOF持久化方案。

Snapshot 1. 原理

20210919092918.png

该种方式是Redis中默认的持久化方式。

在拍摄快照时将当时Redis中的数据状态记录下来,构建成 dump.rdb 快照文件存储在硬盘中。在数据恢复时执行 dump.rdb ,就可以将当时Redis中的所有数据重新装载入Redis。

2. 生成方式 客户端命令(BGSAVE和SAVE指令)手动生成快照。 修改配置,达到某条件后自动触发生成快照。

BGSAVE和SAVE指令都可以生成快照,但二者有所不同。

3. BGSAVE

20210919095942.png

官方推荐使用BGSAVE指令生成快照。

使用BGSAVE生成快照时,Redis不会阻塞。因为Redis是用主进程来处理客户端请求的,当客户端使用BGSAVE指令让Redis生成快照时,Redis会调用fork创建一个子进程,然后子进程负责将快照写入磁盘中,主进程则继续处理客户端的命令请求。

fork是类Unix系统上创建进程的函数。

当一个进程使用fork创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类Unix系统中创建子进程的操作会进行优化。在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写操作之后,对被写入的内存的共享才会结束服务。

使用fork的好处在于:因为使用fork创建的子进程会和主进程共享内存,所以当Redis使用fork创建子进程去生成快照时,主进程只要接收的都是读操作(Redis绝大部分操作都是读操作),那么父子进程就会持续共享内存,大大提高了子进程生成快照的速度。

4. SAVE

20210919100004.png

使用SAVE生成快照,Redis会阻塞。Redis服务在快照创建完毕之前,不再响应任何其他命令,因为Redis会直接使用主进程来生成快照。

5. 配置自动触发

如果用户在 redis.conf 中设置了save配置选项,Redis会在save选项条件满足之后自动触发一次BGSAVE命令。如果设置多个save配置选项,当任意一个save配置选项条件满足,Redis也会触发一次BGSAVE命令。

Redis默认配置了3个save配置选项

20210919101127.png

save配置选项的格式为:

save seconds change 复制代码

例如:

save 900 1 复制代码

如上命令表示,如果900s以内,只要有一个Key发生改变,就自动触发BGSAVE指令。

6. shutdown指令

当Redis服务接收到客户端的shutdown指令关闭服务时,也会自动生成快照。该生成快照底层使用的是SAVE指令,因此会阻塞Redis服务,不再执行客户端发送的任何命令,在SAVE指令执行完毕之后关闭服务器。

之所以这样设计,是因为shutdown就是明确让Redis服务关闭了,此时Redis服务就应该处于阻塞状态,不再处理任何请求了。

CTRL + C底层调用的就是shutdown指令。

7. dump.rdb文件

dump.rdb 中持久化的数据都是以二进制的格式保存,不会显示明文内容。

dump.rdb 名称可以在 redis.conf 中修改,但是后缀必须是 .rdb 。

20210919102406.png

dump.rdb 生成位置也可以在 redis.conf 中修改,但是必须指定一个绝对或者相对路径,不能是个文件名。

默认生成位置是 redis-server 脚本启动的当前目录。

20210919102617.png

8. Snapshot缺陷

当Redis刚生成了快照之后,紧接着又响应了若干次写操作修改了部分数据,但是该写操作并没有达到触发自动生成快照的条件。如果在此时Redis忽然断电,那么此时的 dump.rdb 并没有保存由于执行了若干次写操作更新的数据,因此Redis会丢失不定量的数据,恢复也只能恢复在执行写操作之前的数据。

AOF 1. 原理

20210919213809.png

AOF持久化机制是通过将被执行的所有写命令追加到AOF文件的末尾,以此来记录全部数据生成的过程和发生的变化。在数据恢复时让Redis从头到尾执行一次AOF中记录的所有写命令,就可以恢复原来的数据。

2. 配置

AOF默认是没有开启,需要在 redis.conf 中进行配置。

20210919165955.png

AOF文件默认名称为 appendonly.aof,存储位置和 dump.rdb 一致。

20210919165858.png

3. appendonly.aof文件

appendonly.aof中不仅仅记录所有写命令,其实还会在写命令之间添加一些特殊符号,例如 "$" 、"*"。实际上这些符号的作用是为了充实写命令的内容,比如将该数据恢复到哪一个库中等。但是appendonly.aof中的主体还是所有写命令。

4. 日志追加频率

AOF提供了三种日志追加频率

always:每一个写命令都要实时同步 everysec:每秒同步一次 no:由操作系统决定何时同步

默认是everysec,也就是说,每过一秒都会将前一秒的写命令追加进到 appendonly.aof 中。

假设该一秒中有1000个客户端执行了写操作,那么在该秒结束后,Redis会将这1000条指令一次性追加到 appendonly.aof 中。

日志追加频率可以在 redis.conf 中进行配置

20210919172138.png

5. always

不建议配置always,因为always的同步策略会严重降低Redis的速度。

如果用户使用了always选项,那么每个Redis写命令都会被实时写入硬盘,虽然可以将发生系统崩溃时出现的数据丢失减到最少,但是这种同步策略需要对硬盘进行大量的写入操作,会导致Redis处理命令的速度受到硬盘性能的限制。

这里涉及到 "写入放大" 的知识,就是如果在某一时刻,往硬盘中不断写入小文件,会极大影响硬盘的处理速度,并且会严重影响磁盘寿命。

如果电脑使用的是磁盘当作硬盘,磁盘一般可以追加200个命令/s,如果设置了always,而每秒持续追加的命令多达200+,那么长时间硬盘就会积累越来越多的命令无法处理,最终就会将硬盘拖垮,而导致Redis服务阻塞。

如果电脑使用的是SSD当作硬盘,固态硬盘可以追加几百万个命令/s,但是也慎用always,因为 "写入放大" 的问题也会严重减少SSD的寿命。

6. everysec

为了兼顾数据安全和写入性能,推荐用户配置everysec,让Redis每秒一次的频率对AOF文件进行同步。

Redis每秒同步一次AOF文件时,性能和不使用任何持久化特性时的性能相差无几。而通过每秒同步一次AOF文件,Redis可以保证,即使系统崩溃,Redis也最多丢失一秒之内产生的数据。

7. no

no不是不同步,只是将同步的权限由Redis交给了操作系统,同样不推荐使用。

no有两个明显弊端,都是由于操作系统控制同步导致的。一个是当服务器崩溃时,会丢失不等量的数据,甚至全部数据。另一个就是因为如果Redis积攒了很长时间的写命令在操作系统的控制下进行一次性同步,此时如果硬盘处理速度还不过快,缓冲区就会被等待写入的数据填满,Redis就会处于阻塞状态。

8. AOF缺陷

AOF会使持久化文件会变的越来越大。

例如我们调用 incr test 命令100次,AOF文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实只需要保存一条 set test 100 就够了。

为了压缩AOF的持久化文件,Redis提供了AOF重写机制。

AOF重写机制 1. 作用

AOF重写机制的作用就是一定程度上减小AOF文件的体积。

2. 触发前提

必须开启AOF持久化方案,且 appendonly.aof 文件已经生成。

3. 触发方式 执行BGREWRITEAOF指令手动重写AOF文件。 修改配置,达到某条件后自动触发重写AOF文件。 4. BGREWRITEAOF

BGREWRITEAOF指令执行不会阻塞Redis,类似于BGSAVE指令。

自动触发的底层调用的也是BGREWRITEAOF指令。

5. 配置自动触发

在 redis.conf 中进行配置。

20210919201740.png

auto-aof-rewrite-percentage 100 复制代码

表示当AOF文件的体积比原体积或上一次重写后的体积原来大了100%(1倍)时,触发重写。

auto-aof-rewrite-min-size 64mb 复制代码

表示当AOF文件体积大于64mb时,触发重写。

这两个配置结合,当AOF文件越小,重写的次数越频繁,最终会让AOF文件始终保持一个比较小的状态。

6. 重写原理

重写并不是对原AOF文件进行压缩,而是生成一个体积更小的AOF文件对原AOF文件进行替换。

20210919211733.png

具体流程如下:

Redis接收到BGREWRITEAOF指令后,fork出一个子进程,对当前缓存中的所有数据进行snapshot。 同时主进程继续处理其他请求,将新的写操作指令一方面追加到原AOF文件,一方面自己缓存一份。(追加到原AOF文件中是防止在重写的过程中忽然断电从而丢失数据,自己缓存的原因是为了后续将新的写操作指令写入临时文件) 当子进程snapshot成功后,发出信号通知主进程,然后主进程将缓存中存储的新的写操作指令追加到临时文件。 主进程将临时文件替换掉原AOF文件,之后收到的写操作指令直接追加到新的AOF文件中。

如果原AOF文件过于庞大,那么在删除原AOF文件时,也会占用系统资源,极端情况下也可能会导致Redis阻塞。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3