likes
comments
collection
share

redis 持久化对比(RDB与AOF)

作者站长头像
站长
· 阅读数 23

redis两种持久化方式:

  • RDB(Redis Database):将内存中的数据作为一份快照保存到硬盘中
  • AOF(Append Only File):每次执行命令都会都会尝试触发刷盘操作,实时性好,数据丢的少,但有性能损耗

RDB

概念

将redis的内存数据,保存一份到二进制文件中

触发方式

  • 主动save:整个redis server会阻塞,直至完成
  • bgsave:通过异步流程完成快照备份
  • 自动触发:根据规则设置触发时机,m秒内发生n次修改(save m n)

bgsave流程

  1. fork出一个子进程
  2. 子进程和主进程共享内存(写时复制),子进程直接读取数据,并写到二进制文件中
  3. 替换原有的RDB

写时复制(cow)

父、子进程共享一块内存数据,当父进程要修改数据时,子进程才会将数据copy到自己的物理空间中

通过这种方式,这样能避免数据的大量copy,减少内存消耗

总结

优点

  • 机制简单:简单的快照原理
  • 写入损耗低:与aof不同,不用在每次写入后,还需要额外的写入aof_buf中
  • 文件小:备份数据时压缩后的二进制文件,空间占用小
  • 恢复速度快:基于二进制直接恢复

缺点

  • 丢失数据:备份间隔宕机时,会丢失数据
  • 备份时性能吃紧:虽然在一般的写入时无需额外的性能开销,但是在备份时会造成大量的io,消耗性能

AOF

概念

  1. redis每执行一次写命令,将数据追加到aof_buf中
  2. 根据appendfysnc设定的刷盘时机,将aof_buf中数据刷到磁盘上

刷新磁盘的时机(appendfysnc)

  • always:每次都会落盘,性能极差,但不会丢数据
  • no:不主动刷盘,交给操作系统刷盘,性能最好,但是丢失数据风险较大
  • everysec:每秒定时刷一次,折衷方案

文件重写

aof文件需要定期重写,以免文件无限膨胀,减少故障时恢复的时间

通过直接读取redis,构造aof文件,可以有效的减少存储空间,主要表现在:

  1. 跳过过期、无效的key
  2. 将若干命令压缩成一条
  3. 有效的减少重复命令

重写的伪代码如下所示:

f:=createFile(path)
# 遍历 db
for db range redis.DB():
    # 遍历 key
    for key range db:
        # 跳过过期 key
        if key.isExpired():
            continue
        # 压缩 key
        f.write(compressCmd(key))
        # 设置超时时间
        if key.hasExpireTime():
            f.write(expiredCmd(key))
f.close()

压缩的方案主要讲若干条对同一个key的重复、散落的命令,压缩成一条命令,for example:

Lpush queue r1

Lpush queue r2

Lpush queue r2

可以被压缩成一条

Lpush queue r1 r2

子进程的后台重写

由于需要遍历线上的redis,直接同步处理的话,会阻塞主进程,从而拒绝访问,相当于停机copy数据(但是不用考虑重写过程中的写入问题,因为新的写入被阻塞了)

为了解决这一问题,诞生了基于子进程的后台重写:子进程通过使用主进程的数据副本,实现copy数据

在这种情况下,主进程仍在服务,无可避免会有新的写入产生。为了保证一致性,在文件重写时,会开辟一块新的buffer,用于存储重写过程中发生的变动,如下图所示:

redis 持久化对比(RDB与AOF)

在完成重写后,会进行收尾工作:

  1. 将aof文件重写buffer中的数据写到刚刚重写后的aof文件中
  2. 用重写后的aof文件替换现有的aof文件

注意为了保证数据一致性,这两个操作会阻塞主进程

恢复

相对简单,就是创建一个本地的伪客户端,读取aof文件,一次写入server的redis即可

总结

优点

  • 容错性较好:跳过某条失败的命令后,可以继续恢复
  • 易读:每条命令都是一条写入语句,可读性强
  • 支持后台重写:避免文件无限膨胀

缺点

  • 恢复速度较慢:一条一条插入语句,执行耗时
  • 占用空间大:是完整的命令,所用空间当然也多

参考

详解Redis持久化(RDB和AOF)

RDF和AOF的区别

Redis之AOF重写及其实现原理

linux 同步IO: sync、fsync与fdatasync

写时复制技术(详解版)

Linux写时拷贝技术(copy-on-write)