您的位置:首页 > 数据库 > Redis

【学习笔记】Redis(6)-持久化

2016-07-24 13:44 459 查看
因为 Redis 是内存数据库,它将自己的数据库状态存储在内存里面,所以如果不把储存在内存中的数据保存到磁盘上的话,那么一旦服务器进程退出,服务器中的数据也会消失不见。为了把数据保存到磁盘上,Redis 提供了两种持久化的功能,避免了数据意外丢失。

1. RDB 持久化

RDB 方式的持久化是通过快照来完成的,当符合一定条件时,Redis 会自动将内存中的所有数据生成一个副本并存储在硬盘上,这个过程即为“快照”。Redis 默认会将快照文件存储在 Redis 当前进程的工作目录中的 dump.rdb 文件中,可以通过配置 dir 和 dbfilename 参数分别制定快照文件的存储路径和文件名。

RDB 持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能将数据库状态保存到一个 RDB 文件中。RDB 文件是一个压缩过的二进制文件,通过该文件,可以还原生成 RDB 文件时的数据库状态。在启动 Redis 服务器的时候,Redis 会打印启动日志,其中的 "DB loaded from disk: 0.035 seconds" 日志信息就是在服务器成功载入 RDB 文件后打印的。

Redis 有两个命令可以生成 RDB 文件,一个是 SAVE,另一个是 BGSAVE。SAVE 命令会阻塞 Redis 服务器进程,直到 RDB 文件创建完毕为止;而 BGSAVE 命令则会派生出一个子进程,然后由子进程负责创建 RDB 文件,服务器进程不会被阻塞。

在 Redis 的配置文件中,我们可以找到类似如下的信息:

save 900 1
save 300 10
save 60 10000
这表示了只要满足以下三个条件之一,BGSAVE 命令就会被执行:

服务器在 900 秒内,对数据库进行了至少 1 次修改
服务器在 300 秒内,对数据库进行了至少 10 次修改
服务器在 60 秒内,对数据库进行了至少 10000 次修改
通过 RDB 方式实现持久化,一旦 Redis 异常退出,就会丢失最后一次快照以后更新的所有数据。这就需要开发者根据具体的应用场合,通过组合设置自动快照条件的方式来将数据损失控制在能够接受的范围内,如果数据非常重要,希望将损失降到最小,则可以通过 AOF 方式进行持久化。

2. AOF 持久化

与 RDB 持久化通过保存数据库中的键值对来记录数据库状态不同,AOF 持久化是通过保存 Redis 服务器所执行的写命令来记录数据库状态的。因为 AOF 文件里包含了重建数据库状态所需要的所有写命令,所以服务器只需要读入并重新执行一遍 AOF 文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。

当 AOF 持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区中。服务器每次结束一个事件循环之前,都会调用 flushAppendOnlyFile 函数,考虑是否需要将 aof_buf 缓冲区中的内容写入和保存到 AOF 文件里。flushAppendOnlyFile 函数的行为由服务器配置的 appendfsync 选项的值(always、everysec、no)来决定。服务器配置的 appendfsync 选项的值决定了 AOF
持久化功能的效率和安全性:

当 appendfsync 的值为 always 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的所有内容写入到 AOF 文件,并且同步 AOF 文件,所以 always 的效率是最低的,但是安全性是最高的。因为即使出现故障停机,AOF 持久化也只会丢失一个事件循环中所产生的命令数据。
当 appendfsync 的值为 everysec 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的所有内容写入到 AOF 文件,并且每隔一秒就要在子线程中对 AOF 文件进行一次同步。从效率上来讲,everysec 模式足够快,并且就算出现故障停机,最多也只丢失一秒钟的命令数据。
当 appendfsync 的值为 no 时,服务器在每个时间循环都要将 aof_buf 缓冲区中的所有内容写入到 AOF 文件,至于何时对 AOF 文件进行同步,则由操作系统来决定。

因为 AOF 文件的更新频率通常比 RDB 文件的更新频率高,所以如果服务器开启了 AOF 持久化功能,那么服务器会优先使用 AOF 文件来还原数据库状态;只有在 AOF 持久化功能处于关闭状态时,服务器才会使用 RDB 文件来还原数据库状态。

此外,为了避免 AOF 文件因为一些过期或冗余的命令导致文件体积过大,Redis 提供了对 AOF 文件进行重写的功能,重写功能会根据当前数据库的状态,记录下还原当前数据库状态所必须的命令,所以并不会造成空间的浪费。举个例子,如果服务器对 list 键执行了以下的命令:

redis > RPUSH list "A" "B"  ["A", "B"]
(integer) 2
redis > RPUSH list "C"      ["A", "B", "C"]
(integer) 3
redis > LPOP list           ["B", "C"]
"A"
redis > RPUSH list "D" "E"  {"B", "C", "D", "E"]
(integer) 4

那么服务器为了保存当前 list 键的状态,必须在 AOF 文件中写入 4 条命令。而重写功能会读取当前 list 键的状态,然后通过一条命令:

RPUSH list "B" "C" "D" "E"


来替代上面的 4 条命令,这样就将保存 list 键所需要的命令从 4 条减少为 1 条了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: