Redis持久化机制
- AOF append on file
- RDB 快照
AOF实现原理
- 写后日志
- 先写内存数据,再记录日志
- 命令执行后才记录日志,不会阻塞当前的写操作。
记录内容
- AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。
- 以 “set testkey testvalue”命令后记录的日志为例,“*3”表示当前命令有三个部分,每部分都是由“$+数字”开头,后面紧跟着具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例如,“$3 set”表示这部分有 3 个字节,也就是“set”命令
AOF缺陷
- AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险
- AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行
AOF写回策略
- Always:同步写回,每个写命令执行完,马上日志同步的写到磁盘
- Everysec:每秒写回,每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘
- No:操作系统控制的写回,每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。
AOF文件过大问题
- 文件系统本身对文件大小有限制,无法保存过大的文件
- 文件太大,之后再往里面追加命令记录的话,效率也会变低
- 发生宕机,AOF 中记录的命令要一个个被重新执行,用于故障恢复,日志文件太大,整个恢复过程非常缓慢,影响Redis 的正常使用
AOF重写机制
- 读取数据库所有键值对,然后完成键值设定语句的写入,将记录重写到aof文件
- 旧日志文件中的多条命令,在重写后的新日志中变成了一条命令
AOF重写过程
- 重写过程是由后台子进程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程,导致数据库性能下降
- 每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的页表拷贝一份给 bgrewriteaof 子进程,形成虚实映射关系,这样子进程也就能访问父进程的内存数据了。然后bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把内存的数据写成操作,记入重写日志
- 主线程如果有写操作,会先操作记录到缓冲区
- 子进程完成记录重写操作后,重写日志记录的新操作也会合入到新的AOF文件
AOF重写过程风险
- Redis主进程fork创建bgrewriteaof子进程时,内核会把主进程pcb拷贝给子进程,创建和拷贝的过程由内核执行,会阻塞主线程。拷贝时,redis实例越大,主线程的页表就越大,fork阻塞的时间就会越长
- bgrewriteaof子进程和主线程共享内存,主线程如果写大key会去申请新内存,操作系统会为其分配大空间,有查找和锁的开销,导致阻塞
AOF重写为什么不共享现有AOF文件
- 主进程写,子进程也要写,就会产生锁,对主线程造成影响