Redis提供了两种不同的持久化策略:RDB和AOF。在4.0之后的版本,Redis提供了由RDB和AOF结合的混合持久化。
一、RDB持久化
1.1 什么是RDB持久化
RDB持久化是通过快照完成的,当符合规则时,Redis会对内存中的所有数据进行遍历并且以二进制文件的形式存在磁盘上。当实例重启时,Redis会读取此二进制文件进行数据恢复。
1.2 相关参数
127.0.0.1:6379> config get dir #RDB快照文件存储目录
127.0.0.1:6379> config get dbfilename #RDB快照文件名
127.0.0.1:6379> config get rdbchecksum #在读写rdb文件时是否进行检查
127.0.0.1:6379> config get rdbcompression #是否对RDB文件进行压缩
127.0.0.1:6379> config get stop-write-on-bgsave-error #当持久化错误时是否停止写文件
127.0.0.1:6379> config get save #持久化规则
1.3 RDB触发条件
RDB生成快照文件有两种方式:自动触发和手动触发。
1、手动触发
save:Redis立即执行快照,这个时候Redis会被阻塞,直到快照完成;
bgsave:bgsave通过fork子进程完成快照备份,Redis在fork子进程的时候需要拷贝父进程的空间内存页表的,所以在fork子进程的时候Redis是阻塞的,阻塞时间由拷贝父进程空间内存页表决定。
2、自动触发
在配置文件中配置save m n:save m n代表着在m秒内,Redis发生n次变化,则触发bgsave执行持久化。在配置文件中可以配置多个save,实现长时间少变化的持久化和短时间多变化的持久化策略。
在关闭Redis的时候,Redis会调用bgsave持久化。
在Redis主备复制的时候,备节点执行全量复制,主节点会调用bgsave持久化之后再将rdb文件发送给备节点。
flushall:执行flushall命令会清空数据库,Redis会调用bgsave执行持久化。
1.4 RDB文件格式
#REDIS
52 45 44 49 53
#版本号
30 30 30 36
#FE表示数据库编号
FE 00
# FD 表示过期时间
FD $length-encoding
#用于表示value的类型
$value-type
# Key 值
$string-encoded-key
# Value值
$encoded-value
# FC 表示毫秒级的过期时间
FC $length-encoding
#用于表示value的类型
$value-type
# Key 值
$string-encoded-key
# Value值
$encoded-value
#用于表示未过期value的类型
$value-type
$string-encoded-key
$encoded-value
# 下一个库编号
FE $length-encoding
# FF:RDB文件结束的标志
FF
1.5 RDB的优点
1、RDB对Redis对外提供的读写服务影响非常小,可以让Redis保持高性能;
2、使用RDB数据文件来恢复Redis数据,十分快速;
1.6 RDB的缺点
1、使用RDB进行数据持久化,如果Redis宕机,会导致Redis丢失最后一次RDB持久化之后的所有数据;
2、RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件很大,会导致服务暂停时间较长;
二、AOF持久化
2.1 什么是AOF持久化
Redis为了解决RDB存在数据丢失的问题,提供了AOF持久化。AOF会将Redis执行的写命令追加到AOF磁盘文件中,在Redis启动时会优先选择从AOF文件恢复数据。由于每一次的写操作,Redis都会写入到文件中,所以开启AOF持久化会对性能有一定的影响。
2.2 相关参数
auto-aof-rewrite-min-size 64mb
#AOF文件最小重写大小,当AOF文件大小大于该值时候才可能重写,4.0默认配置64mb。
auto-aof-rewrite-percentage 100
#当前AOF文件大小和上一次重写时文件大小的对比,如100代表当前AOF文件是上次重写的两倍时候才重写。
appendfsync everysec
#Redis在执行完一个命令后,会以协议格式将命令追加到服务器状态的 aof_buf 缓冲区的末尾,之后按照规则刷新到磁盘
#no:不使用fsync方法同步,而是交给操作系统write函数去执行同步操作。性能最高,安全性最低。
#always:表示每次有写操作都调用fsync将数据写入到AOF文件。性能最差,安全性最高。
#everysec:调用操作系统write写入文件,然后fsync每秒一次从内核刷新到磁盘。兼顾性能和数据安全,所以Redis默认推荐使用该配置。Redis的处理策略:主线程每次进行AOF会对比上次fsync成功的时间;如果距上次不到2s,主线程直接返回;如果超过2s,则主线程阻塞直到fsync同步完成。因此,如果系统硬盘负载过大导致fsync速度太慢,会导致Redis主线程的阻塞;此外,使用everysec配置,AOF最多可能丢失2s的数据,而不是1s。
aof-load-truncated yes
#当Redis突然运行崩溃时,会出现AOF文件被截断的情况,Redis可以在发生这种情况时退出并加载错误,以下选项控制此行为。
#yes:加载截断的AOF文件,Redis服务器启动发出日志以通知用户该事件。
#no:服务将中止并显示错误并停止启动。Redis在重启之前需使用Redis-check-aof工具修复AOF文件再启动。
appendonly no
#yes开启AOF持久化,no关闭AOF持久化
appendfilename appendonly.aof
#指定AOF文件名,无法通过config set 设置,只能通过修改配置文件设置。
dir /usr/local/Redis
#AOF文件存放目录
2.3 AOF重写机制
在Redis运行过程中,会不断往AOF文件中追加写命令,这样就会导致AOF文件十分臃肿。所以需要对AOF文件进行压缩。
AOF重写是通过遍历所有数据库的所有键,如果键过期或者重复无效将跳过。Redis重写通过子进程执行以保证主进程的正常工作。在重写期间,原AOF文件会继续对写命令进行记录,同时还会写到重写缓存中,待重写完成后追加写入到新的AOF文件中,然后再将原AOF文件覆盖。其中新AOF文件替换原AOF文件的过程会阻塞。
2.3.1 触发条件
AOF重写可以手动触发和自动触发:
手动触发:
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started
自动触发:
auto-aof-rewrite-min-size: AOF文件最小重写大小,只有当AOF文件大小大于该值时候才可能重写,4.0默认配置64mb。
auto-aof-rewrite-percentage:当前AOF文件大小和最后一次重写后的大小之间的比率等于或者等于指定的增长百分比,如100代表当前AOF文件是上次重写的两倍时候才重写。
当没有bgsave、bgrewriteaof进行且符合上述两个参数时,AOF就会进行重写。
2.4 AOF文件格式
(+) 表示一个正确的状态信息,具体信息是当前行+后面的字符。
(-) 表示一个错误信息,具体信息是当前行-后面的字符。
(*) 表示消息体总共有多少行,不包括当前行,*后面是具体的行数。
($) 表示下一行数据长度,不包括换行符长度\r\n,$后面则是对应的长度的数据。
(:) 表示返回一个数值,:后面是相应的数字节符。
2.5 AOF的优点
1、AOF相对于RDB讲以更好的保证数据不丢失,一般来讲AOF会设置为每隔1秒通过后台线程去执行一次fsync操作,如果Redis进程挂掉,最多丢失1秒的数据。
2、AOF文件是追加写入,写入性能非常高。
3、AOF日志文件相对于RDB文件更易读,当存在误操作的时候可以在AOF文件重写前修改文件以用来做紧急的数据恢复。
2.6 AOF的缺点
1、AOF文件相对于RDB文件来说要更大;
2、AOF持久化开启后对性能影响比RDB大;
3、数据恢复慢。
三、混合持久化
3.1 混合持久化过程
Redis在4.0版本加入混合持久化,以结合两种持久化方式的优点。混合持久化通过AOF重写机制创建一个综合RDB和AOF格式的新AOF文件。在重写时,会将重写之前的数据保存为RDB格式,重写之后继续以AOF格式追加。
开启混合持久化后,Redis创建的子进程首先将内存副本的全量以RDB方式写入AOF文件,然后再将缓冲区的增量命令追加到文件中,完成后替换原AOF文件。也就是说这个AOF文件的上半部分时RDB格式,后半部分时AOF格式。这样Redis重新读取时恢复的更快,且数据一致性更强。
3.2 相关参数
aof-use-rdb-preamble #yes则代表开启
四、总结
Redis对数据持久化提供了良好的支持,可以根据实际需求选择持久化策略。另外一定要对Redis的持久化文件进行备份,根据实际情况调整备份策略,防止数据丢失!