一、AOF 持久化
redis 日志为写后日志,redis 先执行命令将数据写入内存数据库后,再将执行后的命令写入日志中。
- 为什么AOF执行的是写后日志?
redis 在进行AOF日志记录时,并不会检查redis 操作命令的语法,如果在写前记录可能在发生故障实用AOF日志恢复时发现语法错误,造成恢复中断。写后日志可保证写入AOF日志指令的正确性,避免错误指令记录到AOF 日志。
- AOF写后日志,可能会造成的问题?
redis 执行命令后数据写入内存完成,但是在写入AOF日志时发生故障导致写入AOF日志失败。在redis 进行数据恢复时,导致数据丢失。
为了尽可能的减少数据丢失,redis 提供三种回写策略,即AOF 配置选项appendsync 三个选项值:
选项 | 意义 |
---|---|
always | 同步写回:每个写命令执行完,立马同步地将日志写回磁盘; |
everysec | 每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘; |
no | 操作系统控制写回,先将日志写入到AOF文件的内存缓冲区,由操作系统控制决定何时写入磁盘 |
always:同步写回,阻塞线程影响主线程的性能,但是保证数据不丢失。
everysec:每秒写回,优化always同步写回的性能,但是有可能发生故障时候丢失上一秒数据。
no:由操作系统控制写回,提高redis性能,但是可能造成大量数据丢失。
3. AOF使用时文件追加记录,会导致AOF过大,在故障后恢复数据造成效率低下,该怎么办?
redis 提供了AOF 重写机制。
redis 配置中提供两个配置用来控制redis AOF重写机制:
auto-aof-rewrite-percentage 100 :AOF文件文的大小超过基准百分之多少后触发bgrewriteaof。默认这个值设置为100,意味着当前aof是基准大小的两倍的时候触发bgrewriteaof。把它设置为0可以禁用自动触发的功能。
auto-aof-rewrite-min-size 64mb:AOF文件重写最小的文件大小,即最开始AOF文件必须达到该文件大小时才会触发重写。
redis 配置默认appendonly no 即:AOF日志记录关闭。
4.AOF日志解析和AOF日志重写
当执行 set “hello” “redis” 时redis 收到指令,在AOF中生成对应的记录如下图:*3 表示该执行有三部分组成,每部分“
+
数
字
”
开
头
,
后
面
紧
跟
指
令
或
键
、
值
。
"
+数字”开头,后面紧跟指令或键、值。"
+数字”开头,后面紧跟指令或键、值。""后面的数字代表键、值得字节数。
AOF避免对当前命令的阻塞,但是AOF是在主线程中执行,在写盘很慢时,可能导致下一条命令阻塞。
AOF记录每次redis 操作的命令可能导致日志文件越来越大,在遇到故障恢复时需要更多是时间。AOF记录时候可能redis 对一个键进行多次重复操作,AOF记录多条操作命令,为了减少日志大小,AOF提供日志重写功能,将多条命令合并记录:如下图操作,对list进入多次插入移出操作后,AOF日志重写只用一条记录来记录redis 操作。
5. AOF重写会阻塞主线程吗?
AOF日志写入是由主线程完成,但是AOF重写是由bgrewriteaof 子线程完成。因此不会阻塞主线程,影响redis性能。
二、RDB日志快照持久化
AOF故障恢复时需执行一条条指令记录,如果AOF 很大会影响Redis 性能。RDB内存快照可以帮助redis快速恢复数据。RDB内存快照就是记录某一时刻内存状态。
Redis 提供两种命令生成RDB快照文件:save和bgsave。
save:主线程中执行,阻塞主线程。
bgsave:redis 默认设置,创建一个子线程专门来生成RDB文件,避免阻塞主线程。
bgsave避免主线程阻塞,如果主线程接受到一个写操作时避免redis 阻塞,redis 使用操作系统的“写时复制”(COW)技术:在主线程是读操作时,主线程和bgsave共用一块内存空间。如果主线程收到写操作时,对应数据块将被复制出一份供bgsave线程使用。bgsave会把副本写入RDB文件,主线程会修改对应数据块内容。
在创建快照时如果间隔时间t过大可能造成大量数据丢失,但是如果t过小又会造成频繁的创建bgsave创建快照,在fork创建bgsave子线程时主线程内存过大会造成线程阻塞从何影响redis 性能。在Redis4.0时提出AOF和内存快照混合记录来减少数据丢失,避免频繁进行快照影响redis 性能。Redis4.0 在两次快照中间增加AOF日志增量记录两次快照之前数据修改。