这也太吊了吧,大神详解Redis——持久化原理探究

简介redis的操作在内存中 , 读写速度极快 , QPS高达10w,常用来作为缓存服务器以减缓数据库的压力 。 我们知道内存中的数据极易丢失 , 比如在机器宕机时会丢失 , 所以需要一种持久化的机制来保护redis的数据不会因为故障而丢失 。 这种机制就是Redis的持久化机制:

  • 快照
  • AOF日志
快照快照原理前面redis基础篇中提到 , redis是单线程的 , 这个线程需要同时处理客户端的请求和内存数据结构的逻辑读写 , 显然难以在保持高性能的前提下完成这些工作 。所以redis使用操作系统的多进程COW(copy on write)写时复制机制来完成快照持久化 。copy on write原理看这篇Linux写入复制的文章 。
fork(多线程)Redis在持久化的时候会调用glibc的函数fork()产生一个子进程 , 快照持久化工作全部交给子进程处理 , 父进程则继续处理客户端请求 。 子进程在产生时完全共享父进程共享内存里面的代码段和数据段 。子进程做数据持久化时不会修改现有的内存数据结构 , 它只是遍历内存中的数据然后序列化写入磁盘中 。 与此同时 , 父进程还在接受客户端的数据交互请求 , 然后对内存中的数据进行不断的修改 。当客户端请求对某个数据进行修改时 , 就会使用操作系统的COW机制来进行数据段页面的分离 。 简单来说就是数据段由多个数据页组成 , 找到这个数据所在的数据页 , 系统会将这个数据页复制一份 , 在这个复制页上进行数据修改 。子进程的数据没有变化 , 因此它看到的内存里的数据在进程产生的一瞬间就凝固了 , 就像拍照的快照一样 。
AOF 日志AOF原理AOF日志存储的是redis的顺序指令序列 , 按照执行顺序存储 , AOF只记录对内存进行修改的指令记录 , 有点像MySQL的Binlog 。AOF写入流程:
这也太吊了吧,大神详解Redis——持久化原理探究文章插图
【这也太吊了吧,大神详解Redis——持久化原理探究】Redis 在收到客户端的修改指令时会先进行参数校验 , 如果没有问题就立即将指令存储到AOF日志 , 也就是写入到磁盘中 。 指令存储到AOF日志后 , 即使宕机 , 内存中的数据丢失了 , 也可以通过 回放AOF日志对数据进行重现 , 使得redis恢复到宕机前的状态 。
在redis长期运行的过程中 , 会接收到很多的指令 , 这将导致AOF日志越来越大 。 而AOF日志中很多命令是重复覆盖的 , 我们只需保留最新的数据即可 , 比如某个 key = aaa 的数据初始值value = http://kandian.youth.cn/index/1 , 在redis运行的过程中该数据进行过1000次修改 , 并且最新value = 111。此时AOF中有1000个关于key=aaa的指令记录 , 而实际上我们只需要记录其最新的 value=111 即可保证数据持久化 。所以我们需要对AOF进行瘦身 。
AOF 重写顾名思义就是对AOF的命令进行重写 , 达到瘦身的目的 。redis中提供bgrewriteaof命令来对AOF日志进行重写 , 重写原理:
  • 创建一个子进程对内存进行遍历转换成一系列redis操作指令 , 序列化一个新的AOF日志文件中 , 序列化完毕后再将操作期间发生的增量AOF日志追加到新的AOF日志中 , 追加完毕马上用新的AOF日志替换旧AOF日志
持久化小结
  • 快照是通过fork一个子进程的方式进行的 , 很耗费资源的操作 , 并且会遍历整个内存 , 大块写磁盘将加重系统负载
  • AOF的fsync是一个耗时的IO操作 , 会降低redis的性能 , 同时增加了系统的IO负担 。
所以redis一般是从节点进行数据持久化 , 而主节点与客户端交互
混合持久化方案rdb + 增量AOF日志的形式:当重启一个redis时 , 先使用rdb恢复再用增量的AOF日志进行指令重放 , 达到快速启动恢复数据的效果 。
这也太吊了吧,大神详解Redis——持久化原理探究文章插图
作者:山鸡1链接:来源:掘金著作权归作者所有 。 商业转载请联系作者获得授权 , 非商业转载请注明出处 。