前言
Redis 是内存数据库,即数据存储在内存。
如果不将内存中的数据保存到磁盘,一旦服务器进程退出,服务器中的数据也会消失。
这样会造成巨大的损失,所以 Redis 提供了持久化功能。
一、RDB
1.介绍
RDB,即 Redis DataBase
- 在指定的时间间隔内将内存中的数据集快照写入磁盘。也就是 Snapshot 快照,恢复时是将快照文件直接读到内存里。
- Redis会单独创建(fork)一个子进程来进行持久化。
- Fork 的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量,环境变量,程序计数器等)数值都和原进程一致。这是一个全新的进程,并作为原进程的子进程。
- 会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。
- 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
- 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。
- RDB 的缺点是最后一次持久化后的数据可能丢失。
- Redis默认是RDB,一般情况下不需要修改这个配置。
- rdb保存的文件是dump.rdb:
dbfilename dump.rdb
图解
2.redis.conf有关配置
# save 3600 1 # save 300 100 # save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb rdb-del-sync-files no dir ./
上诉配置的含义我在Redis之redis.config配置文件中已详细讲解过。
stop-writes-on-bgsave-error
如果配置为 no,表示你不在乎数据不一致或者有其他的手段发现和控制,默认为 yes。
rdbchecksum
在存储快照后,还可以让 redis 使用 CRC64 算法来进行数据校验。
但是这样做会增加大约 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
默认为 yes。
3.触发
配置文件中默认的快照配置,建议多用一台机子作为备份,复制一份 dump.rdb。
保存配置:
- save:只管保存,其他不管,全部阻塞。
- bgsave:Redis 会在后台异步进行快照操作,快照同时还可以响应客户端请求。
- lastsave:获取最后一次成功执行快照的时间。
- save的规则满足的情况下,会自动触发rdb规则
- 执行flushall命令,也会触发rdb规则
- 退出redis,也会产生rdb文件
4.恢复
- 只需要将rdb文件放在我们redis启动目录就可以,redis启动的时候自动检查dump.rdb恢复其中的数据。
- 查看文件需要存在的位置(如果在这个目录下存在dump.rdb文件,启动时自动恢复其中数据)
5.优缺点
优点:
- 适合大规模的数据恢复。
- 对数据完整性和一致性要求不高时适用。
缺点:
- 在一定间隔时间做一次备份,所以如果 redis 意外 宕机 的话,就会丢失最后一次快照后的所有修改。
- fork进程时,会占用一定的内容空间(Fork 的时候,内存中的数据被克隆了一份,大致 2 倍的膨胀性需要考虑)。
二、AOF
1.介绍
AOF,即 Append Only File
- 以日志的形式来记录每个写操作,将 Redis 执行过的所有指令记录下来(读操作不记录)。
- 只许追加文件,但不可以改写文件,Redis 启动之初会读取该文件重新构建数据。
- 换言之,Redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
- 默认是不开启的,我们需要手动进行配置:将appendonly的值改为yes就开启了aof,然后重启redis就可以生效。
2.redis.conf配置
AOF 保存的是 appendonly.aof 文件
# 是否以append only模式作为持久化方式,默认使用的是rdb方式持久化,这种方式在许多应用中已经足够用了 appendonly no # appendfilename AOF 文件名称 appendfilename "appendonly.aof" # appendfsync aof持久化策略的配置: # no:不执行fsync,由操作系统保证数据同步到磁盘,速度最快。 # always:每次写入都执行fsync,以保证数据同步到磁盘。 # everysec:每秒执行一次fsync,可能会导致丢失这1s数据。 appendfsync everysec # 重写时是否可以运用Appendfsync,用默认no即可,保证数据安全性 No-appendfsync-on-rewrite # 设置重写的基准值 Auto-aof-rewrite-min-size # 设置重写的基准值 Auto-aof-rewrite-percentage
3.启动
默认是不开启的,我们需要手动进行配置:将appendonly的值改为yes就开启了aof,然后重启redis就可以生效。
4.恢复
正常恢复
将有数据的 aof 文件复制一份保存到对应目录(config get dir)
异常恢复
命令redis-check-aof --fix appendonly.aof
进行修复。
重启 redis 然后重新加载。
5.重写
AOF 采用文件追加方式,文件会越来越大,为避免出现此种情况,新增了重写机制。
当AOF文件的大小超过所设定的阈值时,Redis 就会启动 AOF 文件的内容压缩。
只保留可以恢复数据的最小指令集,可以使用命令 bgrewriteaof
。
重写原理
AOF 文件持续增长而过大时,会 Fork 出一条新进程来将文件重写(也是先写临时文件最后再 rename)。
遍历新进程的内存中数据,每条记录有一条的 set 语句。
重写 aof 文件的操作,并没有读取旧的 aof 文件,这点和快照有点类似。
触发机制
Redis 会记录上次重写时的 AOF 大小,默认配置是当 AOF 文件大小是上次 rewrite 后大小的 1 倍且文件大于 64M 时触发。
6.优缺点
- 优点
- appendfsync always:每次修改同步。同步持久化,每次发生数据变更会被立即记录到磁盘。性能较差,但数据完整性比较好。
- appendfsync everysec:每秒同步。异步操作,每秒记录 ,如果一秒内宕机,有数据丢失。
- appendfsync no:不同步。从不同步。
- 缺点
- 相同数据集的数据而言,AOF 文件要远大于 RDB 文件,恢复速度慢于 RDB。
- AOF 运行效率要慢于 RDB,每秒同步策略效率较好,不同步效率和 RDB 相同。
总结
- RDB 持久化方式能够在指定的时间间隔内对你的数据进行快照存储。
- AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以 Redis 协议追加保存每次写的操作到文件末尾,Redis 还能对 AOF 文件进行后台重写,使得 AOF 文件的体积不至于过大。
- 只做缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化。
- 同时开启两种持久化方式:
- 在这种情况下,当 redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整。
- RDB 的数据不实时,同时使用两者时服务器重启也只会找 AOF 文件,那要不要只使用AOF呢?作者建议不要,因为 RDB 更适合用于备份数据库(AOF 在不断变化不好备份),快速重启,而且不会有 AOF 可能潜在的 Bug,留着作为一个万一的手段。
- 性能建议:
- 因为 RDB 文件只用作后备用途,建议只在 Slave(从节点) 上持久化 RDB 文件,而且只要 15 分钟备份一次就够了,只保留 save 900 1 这条规则。
- 如果开启 AOF ,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只 load 自己的AOF文件就可以了,代价一是带来了持续的 IO,二是AOF rewrite 的最后将 rewrite 过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少 AOF rewrite 的频率,AOF重写的基础大小默认值 64M 太小了,可以设到 5G 以上,默认超过原大小 100% 大小重写可以改到适当的数值。
- 如果不开启 AOF ,仅靠 Master-Slave Repllcation(主从复制) 实现高可用性也可以,能省掉一大笔IO,也减少了 rewrite 时带来的系统波动。代价是如果 Master/Slave 同时挂掉,会丢失十几分钟的数据,启动脚本也要比较两个 Master/Slave 中的 RDB 文件,载入较新的那个(微博就是这种架构)。