《面试1v1》 连载中...


面试官: Redis是内存数据库,数据存放在内存中,当Redis服务重启数据会丢失,那么Redis如何保证数据的持久化?

候选人: Redis 提供两种持久化方案:RDB(Redis DataBase)和AOF(Append Only File)。

面试官: 说说RDB吧,它的工作原理是什么?

候选人: RDB的工作原理很简单,就是在指定的时间间隔内将内存中的数据集快照写入磁盘,恢复时是将快照文件直接读入内存。

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程仍然处理客户端请求,这样可以保证RDB过程不影响服务。 RDB的优点是轻量,适合大规模的数据恢复;缺点是数据有一定的丢失风险,持久化的工作并不实时。

面试官: 那AOF又是什么?

候选人: AOF的全称是Append Only File,它的工作原理是:

将每次执行会改变数据库的命令记录下来,并追加到AOF文件中。AOF文件就是一个命令的记录,Redis重启时会重新执行AOF文件中的命令来恢复数据。

AOF的优点是每次修改都会同步到磁盘,有效防止数据丢失;缺点是AOF rewrite的时候会阻塞客户端查询,并且文件会变得越来越大。

Redis提供了AOF重写机制,可以彻底压缩AOF文件体积,用一条等价的命令代替多条之前的命令。AOF重写也采用fork方式进行,不会影响应用的访问。

面试官: AOF重写的机制原理能详细说下么?

候选人: AOF重写的基本流程是:

  1. 子进程创建:主进程fork一个子进程,负责重写工作。
  2. 子进程载入当前数据库快照,并开始解析AOF文件。
  3. 子进程构建新的AOF,仅记录数据库里面和快照不同的键。
  4. 子进程完成后,将新构建的AOF发送给主进程。
  5. 主进程加载新AOF,替换旧AOF。如果AOF加载失败,继续使用旧AOF。
  6. 子进程退出。

该机制可以保证主进程始终可用,不会阻塞客户端请求。新旧AOF文件替换采用原子性rename操作,防止重启时只部分加载新AOF的情况发生。 主要的源码在rewriteAppendOnlyFile方法中:

void rewriteAppendOnlyFile(void) {
    int fd;
    char tmpfile[256];
    redisDb *db = server.db;

    /* 创建子进程 */
    if (server.child_type == REDIS_CHILD_TYPE_AOF) {
        ...
    }  

    /* 载入当前数据库 */
    emptyDb(-1);
    if (rdbSave(tmpfile) != REDIS_OK) {
        ...
    }  

    /* 构建新AOF */
    fd = open(tmpfile,O_WRONLY|O_APPEND|O_CREAT,0644);
    /* 将新AOF发送给主进程 */ 
    atomicReplaceFile(server.aof_filename,tmpfile);  
}

面试官: 讲的很透彻,AOF重写机制我现在全明白了,Redis的持久化方案用的真的很巧妙!

候选人: 是的,Redis的RDB和AOF双持久化方案,既保证了数据的持久性,也兼顾了效率。

《面试1v1》Redis持久化_持久化

最近我在更新《面试1v1》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!


《面试1v1》 连载中...


🎁目录合集:

Gitee:https://gitee.com/rodert/JavaPub

GitHub:https://github.com/Rodert/JavaPub

javapub.net.cn