Redis-AOF持久化

RDBAOF 区别在于: 前者保存数据库快照,持久化全部键值对,后者经过保存 写命令 保证数据库的状态.mysql

什么是 AOF ?

AOF 持久化经过保存服务器执行的写命令实现,进行恢复时经过重放 AOF 文件中的写命令,来保证数据安全.就像 mysqlbinlog 同样.git

开启 AOF

经过在 redis.conf 中将 appendonly 设为 yes 便可github

# redis.conf
appendonly yes
# 设置 aof 文件名字
appendfilename "appendonly.aof"
# Redis支持三种不一样的刷写模式:
# appendfsync always #每次收到写命令就当即强制写入磁盘,是最有保证的彻底的持久化,但速度也是最慢的,通常不推荐使用。
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面作了很好的折中,是受推荐的方式。
# appendfsync no #彻底依赖OS的写入,通常为30秒左右一次,性能最好可是持久化最没有保证,不被推荐。
复制代码

AOF 文件格式

AOF 文件格式以 redis 命令请求协议为标准的,*.aof 文件能够直接打开.redis

redis设计与实现-aof格式

AOF 持久化过程

命令追加 append

redis 执行完客户端的写命令后,会将该命令以协议的格式写入到 aof_buf 中.该属性为 redisServer 中的一个.sql

#src/server.h
struct redisServer {
 ....
 sds aof_buf;      /* AOF buffer, written before entering the event loop */
}
复制代码

AOF 写入同步

redis 的服务进程是一个 事件循环 - event loop , 每次循环大概会作三件事.数据库

  1. 文件事件: 接收客户端的命令,返回结果
  2. 时间事件: 执行系统的定时任务(serverCron), 完成渐进 rehash 扩容之类的操做
  3. aof flush: 是否将 aof_buf 中的内容写入文件中
# 伪代码
def eventloop():
 while true:
 	processFileEvents() # 处理命令
 	processTimeEvents() # 处理定时任务
 	flushAppendOnlyFile() # 处理 aof 写入
 	
复制代码

flushAppendOnlyFile 中的动做是否执行是根据一个配置决定的.缓存

appendfsync

该配置有几个值可选,默认是 everysec.安全

  1. always: 老是写入.只要程序执行到这一步了,就将 aof_buf 中命令协议写入到文件
  2. everysec: 每秒写入. 每次执行前会先判断是否与上次写入间隔一秒,再次同步时经过 一个线程 专门执行
  3. no: 不写入. 命令写入 aof_buf 后由操做系统决定什么时候同步到文件

fsync: 现代操做系统为了提升文件读写的效率,一般会将 write 函数写入的数据缓存在内存中,等到缓存空间填满或者超过必定时限,再将其写入磁盘.这样的问题在于宕机时缓存中的数据就没法恢复.因此操做系统提供了 fsync/fdatasync 两个函数,强制操做系统将数据当即写入磁盘,保证数据安全.两函数区别在于: 前者会更新文件的属性,后者只更新数据.bash

三种模式在性能和数据上都有相对的优缺点. always 模式数据安全性更强,毕竟每次都是直接写入,可是就会影响性能.磁盘读写是比较慢的. everysec 模式性能较好,但会丢失一秒内的缓存数据. no 模式就彻底取决于操做系统了.服务器

AOF 还原数据

redis设计与实现-aof还原数据

AOF 重写

AOF 重写的意思其实就是对单个命令的多个操做进行整理,留下最终态的执行命令来减小 aof 文件的大小.你能够想象一下执行 1w 次 incr 操做,写入 aof 1w 次的场景.

触发条件

AOF 重写能够自动触发.经过配置 auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage,知足条件就会自动重写.具体能够查看官方的 redis.conf

重写过程

  1. 建立子进程,根据内存里的数据重写aof,保存到temp文件
  2. 此时主进程还会接收命令,会将写操做追加到旧的aof文件中,并保存在server.aof_rewrite_buf_blocks中,经过管道发送给子进程存在server.aof_child_diff中,最后追加到temp文件结尾
  3. 子进程重写完成后退出,主进程根据子进程退出状态,判断成功与否。成功就将剩余的server.aof_rewrite_buf_blocks追加到temp file中,而后rename()覆盖原aof文件

重写的过程当中主进程仍是会一直接受客户端的命令,因此重写子进程与主进程确定会存在数据不一致的状况.redis针对这种状况做出了解决方案: 新增一个 aof_rewrite_buf_blocks, aof 写入命令时,不只写入到 aof_buf, 若是正在重写,那么也写入到 aof_rewrite_buf_blocks 中,这样在子进程重写完毕后,能够将 aof_rewrite_buf_blocks 的命令追加到新文件中,保证数据不丢失.

rename 操做是原子的,也是惟一会形成主进程阻塞的操做.

参考

  1. redis.io/topics/pers…
  2. youjiali1995.github.io/redis/persi…
相关文章
相关标签/搜索