Redis持久化之RDB


引子

今天遇到一个面试题,若是机器内存是4G,redis已经占用了2G内存,这里redis执行RDB持久化,可否持久化成功? 上一秒还在说本身熟悉redis,下一秒就被光速打脸了,发现本身竟然没有深刻了解过redis的RDB持久化的机制。面试

1、Redis持久化的方式

redis持久化方式分为两种,分别是RDB和AOF。redis

  • RDB(Redis DataBase):将某一时刻内存的数据以二进制的形式保存到磁盘中,RDB的数据完整性比不上AOF,可是对redis的QPS不会有太大的影响。
  • AOF(Append Only File):将redis执行的命令按顺序不断追加到文件中,相似于MySQL的binlog日志。 其中,RDB持久化又涉及到两个操做命令,save和bgsave。
  • save:通常是手动操做,会阻塞redis主进行执行。
  • bgsave:经过配置文件来完成的RDB,执行的是bgsave命令,redis会fork一个子进程来执行持久化,只有在fork子进程的过程当中会短暂阻塞redis主进程,持久化的过程不会对主进行有影响。

2、fork和copyonwrite

Redis执行RDB持久化,主要依赖的是fork和copyonwrite技术。
fork函数是操做系统的API,用于从一个进程中建立一个子进程,这个子进程和父进程共享全部的内存信息、上下文、代码区、引用的资源等。可是,这样在子进程执行持久化的过程当中,主进程把内存中的数据修改了会怎么办呢?这里就会使用到copyonwrite技术。ide

  1. 当主进程fork一个子进程出来后,内核会把主进程全部的内存页都设置成read-only,此时,主进程和子进程都指向一样的内存地址。 两个进程共享内存
  2. 当主进程须要对内存进行修改时,发现须要修改的内存页是read-only状态,此时会触发一页异常中断(page-fault)。内核会把须要修改的数据页复制一份,把主进程的地址指向新的复制数据页。 复制新内存数据后
  3. 最后主进程再在新的内存数据页上进行修改操做。

3、总结

根据上面的技术,redis在执行RDB持久化的时候,持久化的内存数据就只会是fork子进程那一刻的内存数据,后续新的请求对持久化不会有影响。回到上面的面试题,redis是能够执行持久化成功的。函数

4、其它问题

  1. RDB的过程当中,每次更新数据都须要复制一份原有的数据,对redis的性能是否会有影响? 由于redis的使用场景大部分是读多写少的场景,所以更新数据时须要先对原数据复制对redis带来的性能影响是能够接受的。
相关文章
相关标签/搜索