Redis持久化
我是 javapub,一名 Markdown
程序员从👨💻,八股文种子选手。
: Redis是内存数据库,数据存放在内存中,当Redis服务重启数据会丢失,那么Redis如何保证数据的持久化?
Redis 提供两种持久化方案: RDB(Redis DataBase) 和 AOF(Append Only File)。
: 说说RDB吧,它的工作原理是什么?
RDB 的工作原理很简单,就是在指定的时间间隔内将内存中的数据集快照写入磁盘,恢复时是将快照文件直接读入内存。(简单来说就是快照保存,核心思路是Copy-on-Write。)
触发 RDB 又分为两种, save 和 bgsave
save
当 Redis 实例收到 save
命令后,此时会阻塞当前 Redis 服务器,在 RDB 文件创建完成之前是不能处理其他客户端发送的任何命令请求,如果数据量太大会造成长时间阻塞,期间 redis 无法处理其他请求,线上环境不建议使用。
bgsave
当 Redis 实例收到 bgsave
命令后,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追更!
🎁目录合集:
Gitee:https://gitee.com/rodert/JavaPub
GitHub:https://github.com/Rodert/JavaPub