Redis持久化存储详解


文章目录

  • Redis持久化存储详解
  • 1、前言
  • 2、RDB 数据快照
  • 2.1 什么是RDB持久化
  • 2.2 RDB 持久化配置
  • 2.3 持久化方式
  • 2.4 bgsave持久化存储实现原理
  • 3、AOF 日志追加
  • 3.1 什么是AOF持久化
  • 3.2 AOF的持久化配置
  • 3.3 AOF的原理
  • 4、总结


1、前言

持久化存储是将 Redis 存储在内存中的数据存储在硬盘中,实现数据的永久保存。我们都知道 Redis 是一个基于内存的 nosql 数据库,内存存储很容易造成数据的丢失,因为当服务器关机等一些异常情况都会导致存储在内存中的数据丢失。

在 Redis 中,持久化存储分为两种。一种是 aof 日志追加的方式,另外一种是 rdb 数据快照的方式。

2、RDB 数据快照

2.1 什么是RDB持久化

RDB在指定的时间间隔能对你的数据进行快照存储把整个内存数据映射到硬盘中,保存一份到硬盘,因此恢复数据起来比较快,把数据映射回去即可,不像AOF,一条条的执行操作命令。

2.2 RDB 持久化配置

主要的配置

# 时间策略
save 900 1     //900s内至少有1个键被修改则进行快照
save 300 10    //300s内至少有10个键被修改则进行快照
save 60 10000  //60s内至少有10000个键被修改则进行快照

# 文件名称
dbfilename dump.rdb

# 文件保存路径
dir /home/redis/data/

# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes

# 是否压缩
rdbcompression yes

# 导入时是否检查
rdbchecksum yes

2.3 持久化方式

1、手动触发

(1)执行save命令:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。

(2)执行bgsave命令:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。

2、自动触发

(1)修改配置项 save m n即表示在 m 秒内执行了 n 次命令则进行备份;

(2)当Redis 从服务器项主服务器发送复制请求时,主服务器则会使用 bgsave命令生成 rbd 文件,然后传输给从服务器;

(3)当执行 debug reload 命令时也会使用 save 命令生成rdb文件;

(4)当使用 shutdown 命令关掉服务时,如果没有启用 aof方式实现持久化则会采用bgsave的方式做持久化.同时shutdown后面可以加备份参数[nosave|save]。

2.4 bgsave持久化存储实现原理

go redis 永久保存_数据


过程:

(1)执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如果存在则直接返回.

(2)如果不存在子进程,父进程fork一个子进程(fork的过程中会造成阻塞的情况),这个过程可以使用info stats命令查看latest_fork_usec选项,查看最近一次fork操作小号的时间,单位是微妙.

(3)父进程fork完之后,则会返回Background saving started信息提示,此时fork阻塞解除.

(4)fork出的子进程开始根据父进程内存数据生成临时的快照文件,然后替换原文件.使用lastsave命令可以查看最后一次生成rdb的时间,对应info的rdb_last_savetime选项.

(5)当备份完毕之后向父进程发送完成信息,具体可以见info Persistence下的rbd*选项.

3、AOF 日志追加

3.1 什么是AOF持久化

AOF持久化存储便是以日志的形式将redis存储在aof_buf缓冲区中的数据写入到磁盘中。简而言之,就是记录redis的操作日志,将redis执行过的命令记录下载,当我们需要数据恢复时,redis去重新执行一次日志文件中的命令

3.2 AOF的持久化配置

# 是否开启aof
appendonly yes

# 文件名称
appendfilename "appendonly.aof"

# 同步方式
appendfsync everysec

# aof重写期间是否同步
no-appendfsync-on-rewrite no

# 重写触发配置
auto-aof-rewrite-percentage 100   
auto-aof-rewrite-min-size 64mb

# 加载aof时如果有错如何处理
aof-load-truncated yes

# 文件重写策略
aof-rewrite-incremental-fsync yes

还是重点解释一些关键的配置:

appendfsync everysec 它其实有三种模式:

(1)always:把每个写命令都立即同步到aof,很慢,但是很安全
(2)everysec:每秒同步一次,是折中方案
(3)no:redis不处理交给OS来处理,非常快,但是也最不安全
一般情况下都采用 everysec 配置,这样可以兼顾速度与安全,最多损失1s的数据。

aof-load-truncated yes 如果该配置启用,在加载时发现aof尾部不正确是,会向客户端写入一个log,但是会继续执行,如果设置为 no ,发现错误就会停止,必须修复后才能重新加载。

3.3 AOF的原理

1、AOF的整个流程大体来看可以分为两步:

(1)命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗)
(2)是对aof文件的重写

对于增量追加到文件这一步主要的流程是:
命令写入->追加到aof_buf->同步到aof磁盘。
那么这里为什么要先写入buf在同步到磁盘呢?如果实时写入磁盘会带来非常高的磁盘IO,影响整体性能。

aof重写是为了减少aof文件的大小,可以手动或者自动触发,关于自动触发的规则请看上面配置部分。fork的操作也是发生在重写这一步,也是这里会对主进程产生阻塞。

手动触发: bgrewriteaof,
自动触发: 就是根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系。

2、重写时的流程图

go redis 永久保存_redis_02


对于上图有四个关键点补充一下:

(1)在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依然会写入旧的AOF file中,如果重写失败,能够保证数据不丢失。
(2)为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个buf,防止新写的file丢失数据。
(3)重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并
(4)AOF文件直接采用的文本协议,主要是兼容性好、追加方便、可读性高可认为修改修复

注意:
不管是RDB还是AOF都是先写入一个临时文件,然后通过 rename 完成文件的替换工作。

4、总结

1、redis 持久化的流程图

go redis 永久保存_持久化_03


启动时会先检查AOF文件是否存在,如果不存在就尝试加载RDB。那么为什么会优先加载AOF呢?因为AOF保存的数据更完整,通过上面的分析我们知道AOF基本上最多损失1s的数据。

2、RDB持久化的优势与劣势

(1)优点:

1、文件实现的数据快照,全量备份,便于数据的传输。比如我们需要把A服务器上的备份文件传输到B服务器上面,直接将rdb文件拷贝即可。

2、文件采用压缩的二进制文件,当重启服务时加载数据文件,比aof方式更快。

(2)缺点:

1、rbd采用加密的二进制格式存储文件,由于Redis各个版本之间的兼容性问题也导致rdb由版本兼容问题导致无法再其他的Redis版本中使用。

2、时效性差,容易造成数据的不完整性。因为rdb并不是实时备份,当某个时间段Redis服务出现异常,内存数据丢失,这段时间的数据是无法恢复的,因此易导致数据的丢失。

3、AOF的优缺点

(1)优点

1、多种文件写入(fsync)策略。

2、数据实时保存,数据完整性强.即使丢失某些数据,制定好策略最多也是一秒内的数据丢失.

3、可读性强,由于使用的是文本协议格式来存储的数据,可有直接查看操作的命令,同时也可以手动改写命令.

(2)缺点

1、文件体积过大,加载速度比rbd慢。由于aof记录的是redis操作的日志,一些无效的,可简化的操作也会被记录下来,造成aof文件过大.但该方式可以通过文件重写策略进行优化。

4、如何选择

(1)针对不同的情况来选择,建议使用两种方式相结合.
(2)针对数据安全性、完整性要求高的采用aof方式.
(3)针对不太重要的数据可以使用rdb方式.
(4)对于数据进行全量备份,便于数据备份的可以采用rdb方式。




参考: [https://blog.51cto.com/10992108/2360947?source=dra](https://blog.51cto.com/10992108/2360947?source=dra) []()