Redis持久化

Redis Persistance 记录 Redis 数据的持久化方式

RDB(Redis DataBase,默认持久化方式)模式

以快照的方式把数据写入文件,几十 G 可以保存为几 KB 的快照。

  • 流程:

      1. fork 出一个子进程,以copy on write策略与父进程共享内存,将内存数据快找保存到硬盘的一个临时文件
      1. 临时文件保存完毕,替换原有的dump.rdb文件
      1. 更新LASTSAVE全局变量值,该变量表示最后一次执行 SAVE 开始时的 UNIX 时间戳
    • copy on write(写时复制)技术,新 fork 出的子进程是一个独立进程,与父进程共享内存。 当父进程对某段执行写入时,会复制并更新到新的内存中,所以不会影响子进程的读取过程。 这就意味着:执行 BGSAVE时,新的操作造成的数据变更不会写入 RDB 文件
    • 注意文件保存位置默认是 redis 启动文件夹,可以通过dir配置设定 redis 工作文件夹
  • 优点:

    • 保存数据快、还原数据快
    • 适用于灾难备份
    • 文件以二进制保存,容量很小
  • 缺点:

    • 此过程可能占用大量内存,小内存机器不适合、过于频繁将导致内存占用严重
    • 如果在快照间隔内发生了宕机,(内存中的)缓存数据将丢失
    • 大量数据写入硬盘时,即使是后台写入,仍然会造成磁盘 IO 阻塞
  • 快照条件:

    • 服务器正常关闭时shutdown命令,同SAVE效果。
    • 满足一定间隔时间和一定据量变化后
    • 执行客户端SAVEBGSAVE命令时
      • 如果是SAVE命令,直接用主进程保存,会整体卡住
      • 如果是BGSAVE则会启动子进程,但是大量数据写硬盘,会造成磁盘阻塞
      • 一般都使用BGSAVE
    • 如果有正在执行的 RDB 子进程,则命令会直接返回 OK
    • flushall(全部删除内存数据)命令执行后会触发 rdb,避免重启后数据又回来
  • 恢复条件:

    • 启动时,如果有已持久化后的文件则自动加载到内存

AOF(Append-only file)模式

每次写命令,都会把命令追加写入appendonly.aof 文件。在 Redis 重启时或手动执行命令,通过命令重建整个数据库内容。

  • 流程:
      1. 主进程把每条命令写入 AOF 缓冲区
      1. 有定时任务线程,把缓冲区内容写入磁盘文件
    • 实际上.aof文件中不是直接的命令,而是经过协议优化的
      • 往往库也可以利用这种协议发送命令
    • 缓冲区默认 1MB
  • 优点:
    • 不会造成 IO 阻塞
    • 增量写入,一般不用担心丢失,写入速度快
  • 缺点:
    • 存储所有命令,文件容量较大
    • 由于文件大,加载速度慢
    • 在特定情况下(2 秒内)也可能丢少量数据
      • 具体丢多少数据可以参考”dirty page”配置项,设定了最大缓冲比例
  • 触发条件: 触发需要在 config 打开开关,关键是何时写到磁盘
    • everysec(默认、推荐)每秒触发一次刷盘,综合性能较好
    • always每条数据变化都刷盘,效率低、但安全
    • no不主动刷盘,等待操作系统将缓存写入磁盘,批量操作效率高,但容易丢数据
  • 恢复条件:

AOF 重写机制:

为了防止 aof 文件一直增大撑爆磁盘,可以根据当前内存数据生成新的 aof 文件。 比如,执行 incr 命令 1000 次,可以用一条 set x 1000 替代。

  • 过程:

      1. 类似BGSAVEfork 子进程,共享内存,根据内存生成新的临时 aof 文件
      1. 生成结束时,替换原有 aof 文件
  • 触发机制:

    • 重写过程会大量占用内存,所以不能过于频繁。
    • auto-aof-rewrite-min-size aof 文件增长到多大后开启重写功能。 默认 64MB 太小了,我们可以改成比如 50 GB,根据内存、磁盘容量设置为合理值
    • auto-aof-rewrite-percentage 每次触发 aof 重写的文件容量比例。 比如默认值100,表示当前容量超过上次 100%。即上一次重写后是 10MB,当前已经到 20MB 了,就开始重写。
    • 手动执行bgrewriteaof命令
  • redis4.0 后提供了”混合持久化机制” 对 aof 重写进行了优化,aof 文件在重写时保存的格式会变为 rdb 二进制格式,容量更小。 之后再进程 aof 时,会继续以 aof 协议写入,两种格式就会混在一起,直到下次重写变为 rdb 格式。 这样大大增加了 aof 的实用性,rdb 可以不用了。

混合模式

一般以混合模式开启持久化,利用两者各自优点。

  • AOF 优先级更高,一般会用 AOF
  • 同时开启后,RDB 的触发频率设置应该修改为低频,避免浪费资源

其他

  • 有时机器宕机时最后写磁盘动作会导致磁盘文件损坏,redis 提供了 rdb 和 aof 的文件修复工具

磁盘写入 IO 模式知识

  • 磁盘 IO/NIO
    • 一般使用 IO 调用 flush 后,其实并没有写盘,只是将数据放入内核 buffer 中,有可能丢数据,综合速度快
    • NIO 调用fsync系统调用才会进行刷盘,但是这样操作虽然本次速度快,但综合下来写盘次数多,性能反而差