概述
Redis支持数据持久化,主要有两种方式:RDB(Redis Database)和AOF(Append Only File),可以单独使用,也可以两者相结合。
RDB
RDB是基于snapshot(快照)的方式进行持久化,会将某个时间点的所有数据保存到磁盘中,可以将快照复制到其他服务器上从而创建具有相同数据的服务器副本。
优点:
- RDB文件是经过压缩的单个文件,保存了Redis在某个时间点的完整数据集,非常适合备份(backup)与灾难恢复(disaster recovery)。
- 生成RDB文件的时候,Redis主进程会fork()一个子进程来处理所有保存工作,父进程仍然可以处理客户端请求,不需要进行任何磁盘IO操作。
- 对于大数据集恢复,RDB比AOF更快。
缺点:
- 如果系统发生故障,将会丢失最后一次创建快照之后的数据。
- 如果数据量很大,保存快照的时间会很长。
流程
Redis默认会将数据集快照保存到磁盘上的dump.rdb文件中,可以设置每隔多长时间、至少多少次变更进行一次快照,或者手动执行 SAVE
和 BGSAVE
命令进行快照。
save 60 1000
//每隔60秒检查一次,如果满足1000次数据变更,则进行快照
Redis进行快照的大致流程为:
- Redis调用系统函数fork() ,创建一个子进程
- 子进程开始写数据集到一个临时的RDB文件中
- 当子进程完成对临时RDB文件的写入时,Redis 用新的临时RDB 文件替换原来的RDB 文件
Redis创建子进程时,会执行写复制(copy-on-write)策略,即父子进程会共享同一内存区域,当父进程写数据时,会先复制一份给子进程,保证子进程的数据复制不受影响。
AOF
AOF(Append Only File)会记录每次写操作,把命令简单追加到日志文件的末尾,AOF文件可以看做是一个日志文件,如同MySQL中 bin.log 文件。
优点:
- 相比于RDB,数据更完整,安全;
- AOF 日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof 工具也可以很轻易的修复;
- AOF 文件里面包含一个接一个的操作,以易于理解和解析的格式存储,可以轻易的导出一个 AOF 文件,出现问题时也更容易进行数据恢复,尽可能的降低损失。
缺点:
- 同样的数据集,AOF 文件通常要大于等价的 RDB 文件;
- 取决于AOF的同步策略,可能会慢于RDB;
- 极少数情况下,特定的命令(如
BRPOPLPUSH
)可能会带来bug。
启动
Redis默认没有开启AOF模式,可以在配置文件redis.conf中设置开启。
appendonly yes
appendfilename来指定AOF文件名,默认为appendonly.aof。
appendfilename "appendonly.aof"
重写
随着服务器写请求的增多,AOF 文件会越来越大,可能出现很多冗余命令,如:
set test hello
set test world
#实际上只需要保留第二条命令即可
Redis 提供了一种将 AOF 重写的特性,能够去除 AOF 文件中的冗余写命令。Redis重写(或者说优化)策略是:只处理当前仍驻留在内存中的数据(未在内存的数据命令直接删除),只保留最后一次写操作。
AOF重写大致流程为:
- Redis调用系统函数fork() ,创建一个子进程。
- 子进程开始重写旧AOF文件内容到一个临时的AOF文件。
- 父进程继续写入此后新更改内容到旧AOF文件(防止AOF重写失败,部分更改内容丢失),同时会把所有新更改内容保存到内存缓存区。
- 子进程完成AOF文件重写后,父进程会把此时处于内存缓存区中的更改内容追加到新AOF文件。
- Redis自动把新AOF文件重命名,删除旧AOF文件。自此,AOF文件重写完成。
Redis 2.4 版本以前,需要手动执行 BGREWRITEAOF
命令来触发AOF重写,现在已经可以通过配置自动触发。
auto-aof-rewrite-percentage 100
#当前的aof文件超过上一次重写时大小的百分之多少时进行重写
auto-aof-rewrite-min-size 64mb
#限制允许重写aof文件的最小的大小
同步
AOF文件中保存的只是Redis的操作命令,最终仍需要将数据同步到磁盘中,但磁盘为提高读写速度通常设有缓冲区,也就是说写入的数据不会立即同步到磁盘中,而是由操作系统决定什么时候将数据同步到磁盘。
用户可以手动调用 fsync()
方法请求操作系统尽快将缓冲区中的数据同步到磁盘中,Redis提供了AOF数据同步时间的选项,可以在配置文件中进行配置。
appendfsync everysec
# appendfsync always
# appendfsync no
共有三个配置可选项:
- always:每个写命令都会同步,数据很安全,但是同步非常慢,严重影响服务器性能;
- everysec:每秒钟同步一次,可以保证系统奔溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;
- no:让操作系统决定何时同步,速度最快,但是系统崩溃时会丢失较多数据。
默认使用 everysec 的方式,同时也是推荐使用的方式。
小结
Redis默认使用RDB的方式,AOF需要手动开启,两者同时使用数据最安全。如果很关注数据,但是仍然可以容忍少量数据的丢失,可以简单的使用RDB模式。