《面试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重写的基本流程是:
- 子进程创建:主进程fork一个子进程,负责重写工作。
- 子进程载入当前数据库快照,并开始解析AOF文件。
- 子进程构建新的AOF,仅记录数据库里面和快照不同的键。
- 子进程完成后,将新构建的AOF发送给主进程。
- 主进程加载新AOF,替换旧AOF。如果AOF加载失败,继续使用旧AOF。
- 子进程退出。
该机制可以保证主进程始终可用,不会阻塞客户端请求。新旧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》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!
《面试1v1》 连载中...
标签:AOF,持久,Redis,面试,RDB,进程,重写,1v1 From: https://blog.51cto.com/wangshiyu/6509120