RDB
和 AOF
区别在于: 前者保存数据库快照,持久化全部键值对,后者经过保存 写命令 保证数据库的状态.mysql
AOF
持久化经过保存服务器执行的写命令实现,进行恢复时经过重放 AOF
文件中的写命令,来保证数据安全.就像 mysql
的 binlog
同样.git
经过在 redis.conf
中将 appendonly
设为 yes
便可github
# redis.conf
appendonly yes
# 设置 aof 文件名字
appendfilename "appendonly.aof"
# Redis支持三种不一样的刷写模式:
# appendfsync always #每次收到写命令就当即强制写入磁盘,是最有保证的彻底的持久化,但速度也是最慢的,通常不推荐使用。
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面作了很好的折中,是受推荐的方式。
# appendfsync no #彻底依赖OS的写入,通常为30秒左右一次,性能最好可是持久化最没有保证,不被推荐。
复制代码
AOF
文件格式以 redis
命令请求协议为标准的,*.aof
文件能够直接打开.redis
redis
执行完客户端的写命令后,会将该命令以协议的格式写入到 aof_buf
中.该属性为 redisServer
中的一个.sql
#src/server.h
struct redisServer {
....
sds aof_buf; /* AOF buffer, written before entering the event loop */
}
复制代码
redis
的服务进程是一个 事件循环 - event loop
, 每次循环大概会作三件事.数据库
serverCron
), 完成渐进 rehash
扩容之类的操做aof_buf
中的内容写入文件中# 伪代码
def eventloop():
while true:
processFileEvents() # 处理命令
processTimeEvents() # 处理定时任务
flushAppendOnlyFile() # 处理 aof 写入
复制代码
flushAppendOnlyFile
中的动做是否执行是根据一个配置决定的.缓存
该配置有几个值可选,默认是 everysec
.安全
aof_buf
中命令协议写入到文件aof_buf
后由操做系统决定什么时候同步到文件fsync: 现代操做系统为了提升文件读写的效率,一般会将
write
函数写入的数据缓存在内存中,等到缓存空间填满或者超过必定时限,再将其写入磁盘.这样的问题在于宕机时缓存中的数据就没法恢复.因此操做系统提供了 fsync/fdatasync 两个函数,强制操做系统将数据当即写入磁盘,保证数据安全.两函数区别在于: 前者会更新文件的属性,后者只更新数据.bash
三种模式在性能和数据上都有相对的优缺点. always
模式数据安全性更强,毕竟每次都是直接写入,可是就会影响性能.磁盘读写是比较慢的. everysec
模式性能较好,但会丢失一秒内的缓存数据. no
模式就彻底取决于操做系统了.服务器
AOF
重写的意思其实就是对单个命令的多个操做进行整理,留下最终态的执行命令来减小 aof
文件的大小.你能够想象一下执行 1w 次 incr
操做,写入 aof
1w 次的场景.
AOF
重写能够自动触发.经过配置 auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
,知足条件就会自动重写.具体能够查看官方的 redis.conf
aof
,保存到temp
文件aof
文件中,并保存在server.aof_rewrite_buf_blocks
中,经过管道发送给子进程存在server.aof_child_diff
中,最后追加到temp
文件结尾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
操做是原子的,也是惟一会形成主进程阻塞的操做.