Redis的持久化问题
aof
aof不会记录读请求。aof只有执行成功的命令才会记录。
看看 AOF 日志的内 容。其中,“*3”表示当前命令有三个部分,每部分都是由“$+数字”开头,后面紧跟着 具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例 如,“$3 set”表示这部分有 3 个字节,也就是“set”命令

落盘策略
AOF 日志也是在主线程中执行的!!
Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
Everysec,每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲 区,每隔一秒把缓冲区中的内容写入磁盘;建议优先使用。
No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓 冲区,由操作系统决定何时将缓冲区内容写回磁盘。
一般而言,只要你采用的不是 always 的持久 化策略,就不会对性能造成太大影响。
aof重写
Redis 根据数据库的现状创建一个新的 AOF 文 件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写 入。不是对原aof文件进行什么命令合并操作!!
和 AOF 日志由主线程写回不同,重写过程是由后台线程 bgrewriteaof 来完成的,这也是 为了避免阻塞主线程
执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此 时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的 最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数 据写成操作,记入重写日志。

fork子进程时,子进程是会拷贝父进程的页表,即虚 实映射关系,而不会拷贝物理内存。子进程复制了父进程页表,也能共享访问父进程的内存数据 了,此时,类似于有了父进程的所有内存数据。
开启:AOF 重写由两个参数共同控制,auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,同时满足这两个条件,则触发 AOF 后台重写 BGREWRITEAOF。
1 | // 当前AOF文件比上次重写后的AOF文件大小的增长比例超过100 |
Huge page的问题
Huge page。这个特性大家在使用Redis也要注意。Huge page对提升TLB命 中率比较友好,因为在相同的内存容量下,使用huge page可以减少页表项,TLB就可以缓存更 多的页表项,能减少TLB miss的开销。 但是,这个机制对于Redis这种喜欢用fork的系统来说,的确不太友好,尤其是在Redis的写入请 求比较多的情况下。因为fork后,父进程修改数据采用写时复制,复制的粒度为一个内存页。如 果只是修改一个256B的数据,父进程需要读原来的内存页,然后再映射到新的物理地址写入。一 读一写会造成读写放大。如果内存页越大(例如2MB的大页),那么读写放大也就越严重,对Re dis性能造成影响。 Huge page在实际使用Redis时是建议关掉的。
rdb
用 AOF 方法进行故障恢复 的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓 慢,影响到正常使用
Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。
save:在主线程中执行,会导致阻塞;
bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置
这里我就要说到一个常见的误区了,避免阻 塞和正常处理写操作并不是一回事。此时,主线程的确没有阻塞,可以正常接收请求,但 是,为了保证快照完整性,它只能处理读操作,因为不能修改正在执行快照的数据
为了快照而暂停写操作,肯定是不能接受的。所以这个时候,Redis 就会借助操作系统提 供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。

如果主线程对这些数据也都是读操作(例如图中的键值对 A),那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据(例如图中的键值对 C), 那么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本 数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。
fork 这个创建过程本身会阻塞主线程,而且主线程的内存越 大,阻塞时间越长。
混合持久化
执行快照的频率不好把握。
Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一 定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。
混合持久化只发生于 AOF 重写过程。使用了混合持久化,重写后的新 AOF 文件前半段是 RDB 格式的全量数据,后半段是 AOF 格式的增量数据。
开启:混合持久化的配置参数为 aof-use-rdb-preamble,配置为 yes 时开启混合持久化,在 redis 4 刚引入时,默认是关闭混合持久化的,但是在 redis 5 中默认已经打开了。
关闭:使用 aof-use-rdb-preamble no 配置即可关闭混合持久化。
混合持久化本质是通过 AOF 后台重写(bgrewriteaof 命令)完成的,不同的是当开启混合持久化时,fork 出的子进程先将当前全量数据以 RDB 方式写入新的 AOF 文件,然后再将 AOF 重写缓冲区(aof_rewrite_buf_blocks)的增量命令以 AOF 方式写入到文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。