书接上回,上回我们详细讲解了Redis的RDB机制,RDB解决了redis数据持久化一部分的问题,为什么说一部分?因为rdb是redis中某一时刻的快照,那么在这次快照后如果数据有新的变更,它是不会被持久化下来的,必须得等到下次rdb备份。然而,生成rdb是和消耗性能的,所以它就不适合很频繁生成。Redis为了弥补这一不足提供了AOF。
AOF的全称是AppendOnlyFile,源码在aof.c。其实关键就是Append(追加),核心原理很简单,就是如果执行完命令(set,del,expire……)后,发现有数据变动,就将这次操作作为一条日志记录到aof文件里,如果有宕机就重新加载aof文件,重放所有的改动命令就可以恢复数据了。只要日志被完整刷到了磁盘上,数据就不会丢失。
配置
AOF的配置比较简单,只有如下几项。
源码
AOF的触发
aof如何实现,又是怎么被触发的,让我们详细看下源码。
server.c中的void call(client *c, int flags)
是redis接受到client请求后处理请求的入口,其中会检测Redis中的数据有没有发生变化。如果有变化就会执行propagate()函数。
propagate函数的作用就是将带来数据改动的命令传播给slave和AOF,这里我们只关注AOF,我们来详细看下feedAppendOnlyFile()函数。
AOF数据生成
这里没有啥太复杂的逻辑,就是将命令转化为RESP协议格式的字符串(RESP协议后续会详解),然后追加到server.aof_buf中,这时候AOF数据还都在缓冲区中,并没有写入到磁盘中,那buf中的数据何时写入磁盘呢?
刷数据
刷数据的核心代码在flushAppendOnlyFile()
中,flushAppendOnlyFile在serverCron、beforeSleep和prepareForShutdown中都有被调用,它的作用就是将缓冲区的数据写到磁盘中,代码比较长且复杂,但大部分都是异常处理和性能监控,忽略掉这部分后代码也比较容易理解,这里就不再罗列了,详见aof.c。
RDB vs AOF
最后,我们来对比下RDB和AOF,他们各自都有啥优缺点,该如何选用。
RDB的优势
- RDB是压缩的后紧凑数据格式,比较很适合备份,
- 同样的数据量下,rdb的文件大小会很小,比较适合传输和数据恢复。
- RDB对Redis的读写性能影响小,生成RDB的时redis主进程会fork出一个子进程,不会影响到主进程的读写。
- RDB数据加载更快,恢复起来更快。
RDB的缺点
- RDB是定期备份,如果备份前发生宕机,数据可能会丢失。
- RDB的生成依赖于linux的fork,如果数据量比较大的话,很影响服务器性能。
AOF的优势
- AOF是持续性备份,可以尽可能保证数据不丢失。
- Redis太大时,Redis可以在后台自动重写AOF。重写是完全安全的,因为Redis继续追加到旧文件时,会生成一个全新的文件,其中包含创建当前数据集所需的最少操作集,一旦准备好第二个文件,Redis会切换这两个文件并开始追加到新的那一个。
- AOF文件格式简单,易于解析。
AOF的缺点
- 对于同一数据集,AOF文件大小通常大于等效的RDB文件。
- 如果使用fsync策略,AOF可能比RDB慢。
RDB和AOF该如何选
如果是要求极致的性能,但对数据恢复不敏感,二者可以都不要,如果是关注性能且关注数据可用性,但不要求数据完整性,可以选用RDB。如果说非常关注数据完整性和宕机恢复的能力,可以RDB+AOF同时开启。
参考资料
本文是Redis源码剖析系列博文,同时也有与之对应的Redis中文注释版,有想深入学习Redis的同学,欢迎star和关注。
Redis中文注解版仓库:https://github.com/xindoo/Redis Redis源码剖析专栏:https://zxs.io/s/1h 如果觉得本文对你有用,欢迎一键三连。