广宁住房和城乡建设局网站,北京建设学院网站,网站地图什么时候提交好,丽水城乡建设局网站文章目录 Redis持久化#x1f64e;♂️面试官#xff1a;什么是Redis持久化#xff1f; AOF日志AOF日志原理#x1f64e;♂️面试官#xff1a;AOF日志是怎么工作的/AOF写入磁盘的流程#xff1f;#x1f64e;♂️面试官#xff1a; 刚刚说到了Redis先执行写入的… 文章目录 Redis持久化♂️面试官什么是Redis持久化 AOF日志AOF日志原理♂️面试官AOF日志是怎么工作的/AOF写入磁盘的流程♂️面试官 刚刚说到了Redis先执行写入的命令后写入AOF日志你知道为什么要这样做吗 写回机制♂️面试官其实你上面说到的这些都与AOF写回机制有关你了解AOF的写回机制吗 重写机制♂️面试官其实为了防止AOF日志越来越大导致磁盘I/O缓慢Redis也提供了AOF重写机制可以简单说一说吗♂️面试官说一下重写机制的好处吧♂️面试官你刚刚说到要用一个新的AOF文件思考过为什么要用新AOF文件吗 AOF后台重写♂️面试官重写过程为什么在后台子进程中♂️面试官 子进程的数据副本是怎么来的 AOF重写缓冲区♂️面试官重写 AOF 日志过程中如果主进程修改了已经存在 key-value此时这个 key-value 数据在子进程的内存数据就跟主进程的内存数据不一致了这时要怎么办呢♂️面试官重写AOF使用的是后台进程永远都不会阻塞主进程吗 RDB快照了解RDB♂️面试官说一说什么是RDB快照♂️面试官如何使用RDB♂️面试官RDB快照的缺点♂️面试官执行bgsave时Redis可以修改数据吗 写时复制♂️面试官写时复制技术的流程♂️面试官发生了写时复制RDB如何保存数据 混合持久化♂️面试官 为什么提出混合持久化♂️面试官 混合持久化的流程 大Key♂️面试官 大Key对持久化的影响♂️面试官如何避免大Key的影响♂️面试官大Key的其他影响 Redis持久化
♂️面试官什么是Redis持久化
♂答
Redis的数据都是存储在内存中的当Redis重启后内存中的数据就会丢失但是Redis实现了数据持久化的方式。主要通过AOF日志和RDB日志来实现。
AOF日志
AOF日志Append Only File追加写文件将所有写操作命令记录到日志中。
AOF日志原理
♂️面试官AOF日志是怎么工作的/AOF写入磁盘的流程
♂答
当Redis执行完写入的命令后会将命令追加到server.aof_buf缓冲区中。通过write() 系统调用将 aof_buf 缓冲区的数据写入到 AOF 文件当应用程序向文件中写入数据时内核会先将数据复制在内核缓冲区Page Cache中具体何时写回主要由写回机制来决定。
♂️面试官 刚刚说到了Redis先执行写入的命令后写入AOF日志你知道为什么要这样做吗
♂答
避免额外的检查开销保证记录在 AOF 日志里的命令都是可执行并且正确的。不会阻塞当前写操作命令的执行因为当写操作命令执行成功后才会将命令记录到 AOF 日志。当然也存在风险我的数据还没有写回磁盘服务器挂掉了数据就丢失了。同时因为要写回到磁盘与磁盘进行I/O时有可能会阻塞下一次的写操作。
写回机制
♂️面试官其实你上面说到的这些都与AOF写回机制有关你了解AOF的写回机制吗
♂答
AOF的写回机制定义了内核缓冲区的数据何时刷回到磁盘的问题。Redis提供了三种写回机制。
Always每次执行写操作命令后都将AOF日志同步到硬盘。 Always 策略可以最大程度保证数据不丢失但是影响主进程的性能 Everysec每次执行写操作命令后先将命令写入到 AOF 文件的内核缓冲区然后每隔一秒将缓冲区里的内容写回到硬盘 Everysec 策略如果上一秒的写操作命令日志没有写回到硬盘发生了宕机这一秒内的数据自然也会丢失。 No意味着不由 Redis 控制写回硬盘的时机转交给操作系统控制写回的时机。自身永远不会调用fsync()函数。 如果想要应用程序向文件写入数据后能立马将数据同步到硬盘就可以调用 fsync() 函数这样内核就会将内核缓冲区的数据直接写入到硬盘等到硬盘写操作完成后该函数才会返回。其实这三种写回机制就在控制fsync()函数的调用时机。
重写机制
♂️面试官其实为了防止AOF日志越来越大导致磁盘I/O缓慢Redis也提供了AOF重写机制可以简单说一说吗
♂答
“ 重写 ”其实存在一些歧义重写机制并不是针对原有的AOF文件进行修改而是针对数据库中键的当前值。 当 AOF 文件的大小超过所设定的阈值后Redis 就会启用 AOF 重写机制。AOF 重写机制是在重写时读取当前数据库中的所有键值对然后将每一个键值对用一条命令记录到「新的 AOF 文件」等到全部记录完后就将新的 AOF 文件替换掉现有的 AOF 文件。
♂️面试官说一下重写机制的好处吧
♂答
重写机制记录的是当前键值对的状态即使某个键值对被多条命令修改最终都是一条命令这样就减少了AOF文件中的命令数量。
♂️面试官你刚刚说到要用一个新的AOF文件思考过为什么要用新AOF文件吗
♂答
主要是为了防止重写失败的情况。 如果不使用新的AOF文件重写失败会对原文件造成污染。 如果使用新的AOF文件重写失败直接删除该文件即可。
AOF后台重写
♂️面试官重写过程为什么在后台子进程中
♂答
Redis中AOF重写过程是由后台子进程bgrewriteaofbackground rewrite of Append-Only File来完成的。
好处有两点
其一是使用后台子进程不阻塞主进程其二是子进程带有父进程的数据副本当父子进程任意一方修改了该共享内存就会发生「写时复制」于是父子进程就有了独立的数据副本就不用加锁来保证数据安全并且不会降低效率。
♂️面试官 子进程的数据副本是怎么来的
♂答
主进程在通过 fork() 系统调用生成 bgrewriteaof 子进程时操作系统会把主进程的页表复制一份给子进程这个页表记录着虚拟地址和物理地址映射关系而不会复制物理内存也就是说两者的虚拟空间不同但其对应的物理空间是同一个。
这样一来子进程就共享了父进程的物理内存数据了这样能够节约物理内存资源页表对应的页表项的属性会标记该物理内存的权限为只读。
AOF重写缓冲区
♂️面试官重写 AOF 日志过程中如果主进程修改了已经存在 key-value此时这个 key-value 数据在子进程的内存数据就跟主进程的内存数据不一致了这时要怎么办呢
♂答
为了解决这种数据不一致问题Redis 设置了一个 AOF 重写缓冲区这个缓冲区在创建 bgrewriteaof 子进程之后开始使用。
在重写 AOF 期间当 Redis 执行完一个写命令之后它会同时将这个写命令写入到 「AOF 缓冲区」和 「AOF 重写缓冲区」。
当子进程完成 AOF 重写工作后会向主进程发送一条信号【信号是进程间通讯的一种方式且是异步的】
主进程收到该信号后会调用一个信号处理函数该函数主要做以下工作
将 AOF 重写缓冲区中的所有内容追加到新的 AOF 的文件中使得新旧两个 AOF 文件所保存的数据库状态一致新的 AOF 的文件进行改名覆盖现有的 AOF 文件。
信号函数执行完后主进程就可以继续像往常一样处理命令了。
♂️面试官重写AOF使用的是后台进程永远都不会阻塞主进程吗
♂答
重写AOF中有三个阶段会导致阻塞父进程
后台重写阶段 创建子进程由于要复制父进程的页表等数据结构阻塞的时间跟页表的大小有关页表越大阻塞的时间也越长完成AOF重写后会向主进程发送一条信号主进程调用信号处理函数该信号的信号处理函数阻塞主进程。 后台重写的写时复制阶段 创建完子进程后如果子进程或者父进程修改了共享数据就会发生写时复制这期间会拷贝物理内存如果内存越大自然阻塞的时间也越长 如果这个阶段修改的是一个 bigkey也就是数据量比较大的 key-value 的时候这时复制的物理内存数据的过程就会比较耗时有阻塞主进程的风险。
RDB快照
了解RDB
♂️面试官说一说什么是RDB快照
♂答
RDB快照记录某一瞬间的内存数据记录实际的数据。在恢复数据时比AOF的效率更高。
♂️面试官如何使用RDB
♂答
Redis 提供了两个命令来生成 RDB 文件分别是 save 和 bgsave他们的区别就在于是否在「主线程」里执行
执行了 save 命令就会在主线程生成 RDB 文件由于和执行操作命令在同一个线程所以如果写入 RDB 文件的时间太长会阻塞主线程执行了 bgsave background save命令会创建一个子进程来生成 RDB 文件这样可以避免主线程的阻塞
♂️面试官RDB快照的缺点
♂答
Redis 的快照是全量快照也就是说每次执行快照都是把内存中的「所有数据」都记录到磁盘中所以执行快照是一个比较重的操作意味着不能频繁保存否则可能会对Redis性能产生影响。
不能频繁保存意味着发生故障时丢失的数据会比AOF持久化的方式更多。
♂️面试官执行bgsave时Redis可以修改数据吗
♂答
执行 bgsave 过程中Redis 依然可以继续处理操作命令的也就是数据是能被修改的。
关键的技术就在于写时复制技术Copy-On-Write, COW。
写时复制
♂️面试官写时复制技术的流程
♂答
执行 bgsave 命令的时候会通过 fork() 创建子进程此时子进程和父进程是共享同一片内存数据的因为创建子进程的时候会复制父进程的页表但是页表指向的物理内存还是一个。
如果主线程父进程要修改共享数据里的某一块数据比如键值对 A时就会发生写时复制于是这块数据的物理内存就会被复制一份键值对 A然后主线程在这个数据副本键值对 A进行修改操作。与此同时bgsave 子进程可以继续把原来的数据键值对 A写入到 RDB 文件。
这样因为只复制了页表可以加快子进程的创建速度避免阻塞主进程。
♂️面试官发生了写时复制RDB如何保存数据
♂答
bgsave 快照过程中如果主线程修改了共享数据发生了写时复制后RDB 快照保存的是原本的内存数据而主线程刚修改的数据是没办法在这一时间写入 RDB 文件的只能交由下一次的 bgsave 快照。
所以 Redis 在使用 bgsave 快照过程中如果主线程修改了内存数据不管是否是共享的内存数据RDB 快照都无法写入主线程刚修改的数据因为此时主线程父进程的内存数据和子进程的内存数据已经分离了子进程写入到 RDB 文件的内存数据只能是原本的内存数据。
如果系统恰好在 RDB 快照文件创建完毕后崩溃了那么 Redis 将会丢失主线程在快照期间修改的数据。
有一种极端情况就是所有的共享内存都被修改则此时的内存占用是原先的 2 倍。
所以针对写操作多的场景我们要留意下快照过程中内存的变化防止内存被占满了。
混合持久化
♂️面试官 为什么提出混合持久化
♂答
尽管 RDB 比 AOF 的数据恢复速度快但是快照的频率不好把握
如果频率太低两次快照间一旦服务器发生宕机就可能会比较多的数据丢失如果频率太高频繁写入磁盘和创建子进程会带来额外的性能开销。
可以将 RDB 和 AOF 合体使用这个方法是在 Redis 4.0 提出的该方法叫混合使用 AOF 日志和内存快照也叫混合持久化。
♂️面试官 混合持久化的流程
♂答
混合持久化工作在 AOF 日志重写过程。 fork()出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件。 后台子进程重写AOF期间主线程执行的写操作命令以AOF格式写入到AOF文件中。 写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。
也就是说使用了混合持久化AOF 文件的前半部分是 RDB 格式的全量数据后半部分是 AOF 格式的增量数据。
这样的好处在于重启 Redis 加载数据的时候由于前半部分是 RDB 内容这样加载的时候速度会很快。【RDB快照的优点】
加载完 RDB 的内容后才会加载后半部分的 AOF 内容这里的内容是 Redis 后台子进程重写 AOF 期间主线程处理的操作命令可以使得数据更少的丢失。【AOF的优点】
大Key
♂️面试官 大Key对持久化的影响
♂答
对于AOF写回策略的影响
当使用 Always 策略的时候如果写入是一个大 Key主线程在执行 fsync() 函数的时候阻塞的时间会比较久因为当写入的数据量很大的时候数据同步到硬盘这个过程是很耗时的。
对于AOF重写机制的影响
当 AOF 日志写入了很多的大 KeyAOF 日志文件的大小会很大那么很快就会触发 AOF 重写机制。AOF重写机制和RDB快照中在通过 fork() 函数创建子进程的时候虽然不会复制父进程的物理内存但是内核会把父进程的页表复制一份给子进程如果页表很大那么这个复制过程是会很耗时的那么在执行 fork 函数的时候就会发生阻塞现象。
对于写时复制机制的影响
如果创建完子进程后父进程对共享内存中的大 Key 进行了修改那么内核就会发生写时复制会把物理内存复制一份由于大 Key 占用的物理内存是比较大的那么在复制物理内存这一过程中也是比较耗时的于是父进程主线程就会发生阻塞。
♂️面试官如何避免大Key的影响
♂答
最好在设计阶段就把大 key 拆分成一个一个小 key。
或者定时检查 Redis 是否存在大 key 如果该大 key 是可以删除的不要使用 DEL 命令删除因为该命令删除过程会阻塞主线程而是用 unlink 命令Redis 4.0删除大 key因为该命令的删除过程是异步的不会阻塞主线程。
♂️面试官大Key的其他影响
♂答 客户端超时阻塞。 由于 Redis 执行命令是单线程处理然后在操作大 key 时会比较耗时那么就会阻塞 Redis从客户端这一视角看就是很久很久都没有响应。 引发网络阻塞。 每次获取大 key 产生的网络流量较大如果一个 key 的大小是 1 MB每秒访问量为 1000那么每秒会产生 1000MB 的流量这对于普通千兆网卡的服务器来说是灾难性的。 阻塞工作线程。 如果使用 del 删除大 key 时会阻塞工作线程这样就没办法处理后续的命令。 内存分布不均。 集群模型在 slot 分片均匀情况下会出现数据和查询倾斜情况部分有大 key 的 Redis 节点占用内存多QPS 也会比较大。
完。 参考来源Redis设计与实现、小林Coding等博客。