Featured image of post Redis 持久化

Redis 持久化

保障数据不丢失

Redis 的读写操作都是在内存中,为了保证内存中的数据不会丢失,Redis 实现了数据持久化的机制,把数据存储到磁盘,这样在 Redis 重启就能够从磁盘中恢复原有的数据。

  • RDB 快照
  • AOF 日志
  • 混合持久化(4.0+)

📷 RDB 快照

RDB 快照就是记录某一个瞬间的内存数据,记录的是实际数据。(全量备份)

快照,就是记录某一个瞬间东西,比如当我们给风景拍照时,那一个瞬间的画面和信息就记录到了一张照片。

触发条件

手动触发

  • save(阻塞主线程)
  • bgsave

被动触发

  • 根据配置文件选项每隔一段时间触发一次 bgsave
1
2
# 300 秒之内,对数据库至少执行了 10 次操作
save 300 10
  • 从节点执行全量复制操作,主节点会自动执行 bgsave 文件发送给从节点

  • 默认情况下,执行 shutdown 命令,没有开启 AOF 持久化功能会自动执行 bgsave

实现方式

执行 bgsave 命令的时候,会通过 fork() 创建子进程,复制父进程的页表,此时子进程和父进程共享同一片内存数据,bgsave 子进程会把该副本数据写入 RDB 文件。

在这个过程中,Redis 依然可以继续处理操作命令,如果父进程执行写操作,关键的技术就在于写时复制技术(Copy-On-Write, COW),被修改的数据会复制一份副本。(RDB 快照保存的是原本的内存数据)

📃 AOF 日志

Redis 在执行完一条命令后,会把该命令以追加的方式写入到文件中(会先写到缓冲区,选择合适的刷盘时间才会到磁盘中)。

当 Redis 重启时,会读取 AOF 日志的内容,然后逐一执行进行数据恢复。

后写日志

Reids 是先执行写操作命令后,才将该命令记录到 AOF 日志里。

  • 优点
    • 避免额外的检查命令的开销
    • 写日志的操作不会阻塞当前命令的执行
  • 缺点
    • 数据可能会丢失。在没有写到内存中时,发生宕机,有丢失数据的风险
    • 可能阻塞后续的操作。执行命令和写 AOF 日志都是在主线程中执行,当把日志写入到磁盘时,会阻塞后续的操作

写回策略

Redis 执行完写操作命令后,会将命令追加到 server.aof_buf 缓冲区,什么时候写回到磁盘,由配置决定。

Redis.conf 可配置参数 appendfsync

  • Always

    • 每次都写回
    • 可靠性高,最大程度会保证数据不丢失
    • 每个命令都要写回硬盘,性能开销大
  • Everysec

    • 每秒写回
    • 宕机时会丢失 1s 内的数据
  • No

    • 由操作系统决定写回时机
    • 宕机时可能会丢失很多数据

AOF 重写

AOF 日志是一个文件,随着执行的写操作命令越来越多,文件的大小会越来越大。 如果当 AOF 日志文件过大就会带来性能问题,比如重启 Redis 后,需要读 AOF 文件的内容以恢复数据,如果文件过大,整个恢复的过程就会很慢。

为了避免 AOF 文件越写越大,提供了 AOF 重写机制,当 AOF 文件的大小超过所设定的阈值后,Redis 就会启用 AOF 重写机制,来压缩 AOF 文件。

AOF 重写时,会读取数据库中所有的键值对,然后将每一个键值对用一条写命令记录到 新的 AOF 文件中,等到全部记录完之后,就将新的文件替换掉旧的文件。

实现方式

通过 fork 后台子进程完成。使用 COW 技术,共享物理内存。

在重写期间,依旧可以执行命令,写命令会同时保存在(1)AOF 缓存区 和 (2)AOF 重写缓存区。

执行完成之后,将 AOF 重写缓存区的内容追加到文件中,并替换旧的文件。

🗃️ 混合持久化

混合持久化工作在 AOF 日志重写过程。

当开启了混合持久化时,在 AOF 重写日志时,

  • fork 出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件,
  • 主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件,
  • 写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据。

Licensed under CC BY-NC-SA 4.0