redis两种(rdb和aof)持久化机制

  • PHP
  • Mar 3, 2019
摘要:前一段时间安装和配置了redis扩展。他跟memcache相似,但是数据支持持久化,那么redis的持久化机制是什么呢?

redis 的持久化机制官方文档:https://redis.io/topics/persistence

>>一种是 rdb 持久化,该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘。

>>一种是 aof 持久化,该机制将以日志的形式记录服务器所处理的每一个写操作,在 redis 服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。

>>如果将两种持久化机制都注释掉,那么 redis 就可以视为一个加强版的 memcache 了。

>>但是如果将两种持久化一起打开,在这种情况下,当 redis 重新启动时,会优先于 aof 文件将用于重建原始数据集,因为它保证是最完整的。

我的 redis 是5.0.3版本的。安装的方式就是前一段时间https://www.yanghaihua.com/content/2019-02-15/1024.html这一篇文章,所以默认的是 rdb 持久化,redis.conf 配置文件在 ^/redis/conf/redis.conf 路径下,安装完也翻了翻文档也查阅了些资料,自己也动手测试了下这两种持久化方式,然后就写了篇文章算是一个总结和记录吧。


RDB 持久化

默认 redis 会以 rdb 快照的形式将一段时间内的数据持久化到硬盘,保存成一个 dump.rdb 二进制文件(文件的名称和路径可以修改)。

rdb 基本的工作原理就是:当 redis 要做持久化时 redis 调用 fork() 一个子进程 ,同时拥有父进程和子进程,子进程将数据集写入到一个临时 rdb 文件中,当子进程完成对新 rdb 文件的写入时,redis 用新 rdb 文件替换原来的 rdb 文件,并删除旧的 rdb 文件,这种工作方式使得 redis 可以从写时复制(copy-on-write)机制中获益。

当然我们也可以手动的调用 save 和 bgsave 进行 redis 的数据保存操作,比如:

[root@host redis]# bin/redis-cli   
127.0.0.1:6379> save
OK
127.0.0.1:6379> bgsave
Background saving started

这两种命令的区别就是 save 保存是阻塞主进程,客户端无法连接 redis,等 save 完成后,主进程才开始工作,bgsave 是 fork 一个save 的子进程,在执行 save 过程中,不影响主进程,客户端可以正常链接 redis,等子进程 fork 执行 save 完成后,通知主进程,子进程关闭。

打开 redis.conf 配置文件,然后 reids 的 rdb 持久化默认配置如下:

################################ SNAPSHOTTING  ################################

save 900 1 # 900秒之内,如果超过1个key被修改,则发起快照保存。
save 300 10 # 300秒之内,如果超过10个key被修改,则发起快照保存。
save 60 10000 # 60秒之内,如果1万个key被修改,则发起快照保存。

dbfilename dump.rdb # 默认保存文件名

dir ./ # 默认保存路径

我们也可以对 redis 进行设置,让它在“ N秒内数据集至少有M个改动”这一条件被满足时,自动保存一次数据集,这种持久化方式被称为快照(snapshot)。


AOF 持久化

使用 aof 做持久化,我们只需要将 appendonly 设置成 yes,每次 redis 收到更改数据集的命令(例如set)时,每一个写命令都通过 write 函数默认追加到 appendonly.aof 文件中,在 redis 在启动之初的时候会读取这个文件重新构建数据库,以保证启动后数据是完整的。

打开 redis.conf 配置文件,然后 reids 的 aof 持久化默认配置如下:

############################## APPEND ONLY MODE ###############################

appendonly yes # 开启 aof 持久化,默认此项为no。

appendfilename "appendonly.aof" # 默认的保存文件,可以修改。

你也可以配置 reids 多久将数据 fsync 到磁盘一次,在配置文件中的 appendfsync 有三个选项:alwayseverysecno,默认选择的是 everysec 同步机制,其它两个是注释掉的,这三个选项分别是:

always:每次将新命令附加到 aof 文件中,会极大的削弱性能,但是非常安全。

everysec:最多一秒调用一次 fsync,足够快(可能与快照一样快),如果发生灾难,可能会丢失1秒的数据。

no:不会主动调用 fsync 同步,只需将数据放在操作系统的中。更快,更不安全的方法。通常情况下,linux 将使用此配置每30秒刷新一次数据,但这取决于内核的精确调整。

比如我执行了 set 和 del 命令操作:

[root@host redis]# bin/redis-cli       
127.0.0.1:6379> set test_name_key "hello redis!"
OK
127.0.0.1:6379> del test_name_key
(integer) 1
127.0.0.1:6379> exit

接下来我们查看下 appendonly.aof 文件,appendonly.aof 文件存储格式如下:

[root@host redis]# less appendonly.aof 
*2
$6
SELECT
$1
0
*3
$3
set
$13
test_name_key
$12
hello redis!
*2
$3
del
$13
test_name_key

可以看到每次的命令操作都会追加到这个 aof 文件中,由于 redis 客户端使用 RESP:https://redis.io/topics/protocol(redis 序列化协议)的协议与 redis 服务器通信,由于 RESP 协议中包含了换行符,所以上面展示的 aof 文件遇到换行符时进行了换行。在 aof 文件里面,除了用于指定数据库的 SELECT 命令是自动添加的之外,其他都是我们通过客户端发送的命令。aof 文件中保存的命令会在 redis 下次重启的来还原 redis 数据库。

因为 aof 方式是每次都将命令以追加写的方式追加到 aof 文件中,所以随着 redis 不断的运行,这个文件体积会原来越大,这样文件越来越大,数据还原的时间也会越来越长,那么这个问题怎么解决呢?

为了解决 aof 文件越来越大的问题,用户可以向 redis 发送 bgrewriteaof 命令,这个命令会保存 key 的最后状态,消除冗余的命令来重写 aof 文件,使 aof 文件的体积变得尽可能地小。即使 bgrewriteaof 命令执行失败,也不有任何的数据丢失,因为旧的 aof 文件在 bgrewriteaof 成功之前不会被修改。

[root@host redis]# bin/redis-cli 
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started

aof 文件在重写之前是有可读性的,但是重写之后就会变成一个二进制文件,比如刚刚的 appendonly.aof 文件重写之后如下:

[root@host redis]# less appendonly.aof 
"appendonly.aof" may be a binary file.  See it anyway? 
REDIS0009<FA>   redis-ver^E5.0.3<FA>
redis-bits<C0>@<FA>^Ectime<C2><ɩ\<FA>^Hused-mem<C2>^X^D^M^@<FA>^Laof-preamble<C0>^A<FF><AF>O<A5><FA>HQiESC

bgrewriteaof 的工作原理和 rdb 的 bgsave 的工作原理类似,redis 会创建一个子进程来负责对 aof 文件进行重写。值得注意的是,进行 aof 文件重写时,如果原来的 aof 文件体积已经非常大,那么重写 aof 并删除旧 aof 文件的过程将会对 redis 的性能造成较大的影响。

不过需要注意的是:从 redis 2.4 开始, aof 重写由 redis 自行触发, bgrewriteaof 仅仅用于手动触发重写操作。为此官网提供了两个配置 auto-aof-rewrite-percentageauto-aof-rewrite-min-size 两个配置对 aof 文件进行重写,我们先打开 reids.conf 查看下这两个的默认配置:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

auto-aof-rewrite-percentage:当前写入的 aof 文件大小超过上次重写之后文件大小的百分之100时,也就是二倍时触发重写,设置为0表示不自动重写 aof 日志。

auto-aof-rewrite-min-size:当前 aof 文件大小超过了指定值才会重写,这样就避免了达到百分比但是没有达到文件大小仍然要重写。即使满足了auto-aof-rewrite-percentage 配置,没有瞒足 auto-aof-rewrite-min-size 的配置也不会重写,必须两者都满足才会触发重写。

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top