Redis支持两种持久化手段,下面分别进行总结
- RDB(Redis DataBase):将当前Redis数据库中的所有数据以二进制的形式存储在.rbd文件中,也就是状态备份。
- AOF(Append Only File):将写操作持久化在AOF文件中,也就是状态机备份。
RDB
RDB机制将当前Redis存储的所有KV对存储在二进制文件中,持久化的触发时机有两个:
显式调用
save
或bgsave
满足配置文件中的持久化条件
- 在过去的xxx秒内,若写入操作超过xx个,则进行RDB持久化
为了避免写入RDB阻塞Redis响应客户端的写入请求,Redis通过fork()
生成子进程负责执行RDB生成操作。
Linux中的fork()
操作基于copy-on-write(COW)
机制,将子进程的内存复制推迟到了父进程执行写入操作。
- 无
COW
机制的fork()
:创建子进程时,子进程与父进程共享正文段,开辟新空间复制父进程的数据段,队,栈。 - Linux中的
fork()
:创建子进程时,只为子进程创建虚拟空间,与父进程共享物理空间,当父进程修改对应物理空间数据库,再为子进程开辟空间复制数据。
Redis的后台RDB机制基于Linux中的fork()
的copy-on-write(COW)
,因此其生成的RDB文件保存的是发起RDB持久化时刻的Rdis数据库状态。
AOF
AOF(Apeend Only File)通过记录变更
持久化数据库状态,变更
包括set
,hset
,del
等数据库写入操作,其实实现机制类似于Mysql中的redo log
每次写入操作执行后,写入到位于内存的AOF缓冲区
aof_buf
中刷新时机由配置文件参数
appendfsync
控制(和Mysql一毛一样)no
:只写入文件,但是不调用文件系统刷新接口fsync()
everysec
:写入文件,若距离上次调用fsync()
超过一秒,则调用always
:每次写入后调用fsync()
由于AOF采用了记录操作的思路实现持久化,相较于RDB,带来了两个新问题
- 重启无法像RDB文件一样,直接加载到内容中即可
- Redis采取“伪客户端”逐个执行操作的方式,实现启动时的状态还原
- 随着Redis执行的操作越来越多,AOF文件大小也会越来越大,重启重新执行的时间也会过长
- Redis使用异步AOF重写机制,实现AOF文件的缩小
- AOF重写机制:基于当前状态构建生成当前数据库状态的操作,生成新的AOF文件(根据结果反推过程替代真正的过程),例如
sadd a,sadd b,s add c->sadd a b c
- 对应命令为
BGREWRITEAOF
除主动调用外,当AOF
文件大于配置文件中设置大小时,后台自动启动AOF重写操作。
RDB vs AOF
RDB和AOF都是Redis提供的实现持久化的手段,两者的区别主要在于:
- RDB是对Redis状态的持久化,AOF是对Redis操作的持久化,因此AOF的粒度更细
- RDB以二进制形式存储,AOF存储的是一个一个修改操作,因为RDB文件更小
- 在Redis重新启动时,RDB形式的备份只需要加载,AOF则需要逐个操作读取执行
上述区别导致了AOF更适合数据持久性要求更高的应用场景,RDB更适合做数据备份以及持久性要求较低的应用场景。
参考
- Redis persistence
- Redis设计与实现
- [详细讲解Linux内核写时复制技术COW机制](