Redis持久化
Redis 提供了不同级别的持久化方式:
- RDB:在指定的时间间隔能对数据进行快照存储.
- AOF:持久化方式记录每次对服务器写的操作,当服务器重启时会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
- 如果希望数据在服务器运行的时候存在,也可以不使用任何持久化方式.
- 也可以同时开启两种持久化方式,,在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
RDB(快照)
优点:
- RDB的文件体量相对小,它保存了某个时间点的数据集(全量),非常适用于数据集的备份
- 恢复速度快,适用于灾难恢复
- RDB在保存RDB文件时父进程唯一需要做的就是fork(系统调用)出一个子进程,写磁盘由子进程来做,fork并不是拷贝出一份数据,而是拷贝指针将指针指向内存同一个映射地址,此时父进程不做其他IO操作,所以RDB持久化方式可以最大化redis的性能
缺点:
- 在save时间点之间万一Redis意外宕机,可能会丢失部分数据
- RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求,如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度
- 不支持拉链,只有一个rdb文件
工作方式
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
- Redis 调用forks. 同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。
配置文件中的相关配置信息:
#持久化规则 多少秒或达到多少数据进行一次持久化
save 900 1
save 300 10
save 60 10000
#持久化生成的rdb文件名
dbfilename dump.rdb
#生成的rdb文件路径
dir /var/lib/redis/6379
AOF(日志)
优点:
- 使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
- AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
- Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
- AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
缺点:
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
AOF 是文件操作,对于变更操作比较密集的 server,那么必将造成磁盘 IO 的负荷加重;此外 linux 对文件操作采取了“延迟写入”手段,即并非每次 write 操作都会触发实际磁盘操作,而是进入了 buffer 中,当 buffer 数据达到阀值时触发实际写入(也有其他时机),这是 linux 对文件系统的优化,但是这却有可能带来隐患,如果 buffer 没有刷新到磁盘,此时物理机器失效(比如断电),那么有可能导致最后一条或者多条 aof 记录的丢失。
工作方式
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:
- Redis 执行 fork() ,现在同时拥有父进程和子进程。
- 子进程开始将新 AOF 文件的内容写入到临时文件。
- 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
- 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
- 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
4.0之前的重写是删除抵消命令,合并重复命令,最终也是一个纯指令的日志文件
4.0以后是混合体,将老的数据RDB到AOF文件中,将增量的以指令的方式追加到AOF中
配置文件中的相关配置信息:
#默认关闭AOF
appendonly no
#AOF文件名称
appendfilename "appendonly.aof"
#fsync同步级别
#always:每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全
#everyec:每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
#no:将数据交给操作系统来处理。更快,也更不安全的选择。
# appendfsync always
appendfsync everysec
# appendfsync no
#yes:子进程在重写aof文件时,主进程的写入操作争抢IO,不丢数据,但是影响性能
#no:子进程在重写aof文件时,主进程不争抢IO,数据只是写入缓冲区,如果redis这时候挂掉容易丢数据
no-appendfsync-on-rewrite no
#是否开启RDB+AOF混合模式,如果开启,则在AOF开头会有一个 "REDIS"标识,说明是一个混合的AOF文件
aof-use-rdb-preamble yes
#当AOF文件达到64M或100%则会自动触发重写,redis会记忆文件大小,当下次再达到64M或100%再次触发重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb