解密Redis持久化

本文主要是对antirez博客的翻译。其实nosqlfan已经有一篇译文,但不知道为什么省略了很多重要的细节,因此完整翻译了本篇。

首先antirez感觉到,他看到的所有针对Redis的文章和讨论中,对Redis持久化的误解是最大的。因此在这篇文章中,他将尝试真正的公正一些:不做Redis的广告,不尝试跳过任何细节以避免使Redis模糊不清。作者想做的仅是提供一个清晰易懂的描绘,介绍Redis持久化的工作原理,Redis的持久化如何可靠,以及与其它数据库的对比。

操作系统和磁盘

写操作的流程

我们应该考虑的第一件事是对于数据库的持久化,我们的期望是什么。因此我们将一个简单的写操作中发生的事情可视化:

  1. 客户端发送写命令到数据库(数据库在客户端内存中)
  2. 数据库接收到写操作(数据在服务器内存中)
  3. 数据库调用系统调用,将数据写入磁盘(数据在内核缓冲区中)
  4. 操作系统将写缓冲区的数据转移到磁盘控制器上(数据在磁盘缓存中)
  5. 磁盘控制器真正将数据写入到物理介质(数据真正落在磁盘上)

    注意:以上是一个各方面简单化的版本,因为实际有更多的cache和buffer。
    步骤2经常被实现为数据库内部的一个复杂缓存系统。写操作也经常被不同的线程或进程处理。然而数据库或早或晚要将数据写入磁盘,而这就是我们关心的。也就是说,内存中的数据在某个节点必须要被传输到内核(步骤3)。
    另外一个大的细节省略在步骤3.现实要更复杂,因为大多数高级操作系统内核实现了不同级别的缓存,其中通常包含文件系统级别的chache和一个略小一些的buffer cache。

故障分析

在这个流程中什么时候我们的写操作才是安全的呢?

如果我们考虑一个仅涉及数据库软件的失效(例如进程被管理员杀掉或崩溃),而不涉及操作系统内核,那成功执行完成步骤3的写操作就被认为是安全的。也就是在write这个系统调用(或其它用于将数据转移到内核的系统调用)返回成功后。在此步骤之后,即使数据库进程崩溃,内核仍然会负责将数据转移到磁盘控制器。

如果我们考虑一个更灾难性的事件,如电力中断,只有在步骤5执行完成后我们才是安全的。也就是在数据真正被转移到物理设备中时。

我们可以总结为,数据安全的重要阶段位于步骤3、4、5:

POSIX API

我们无法控制的部分

数据损坏

Redis持久化实现

RDB快照

AOF文件

AOF重写

AOF持久化

appendfsync no
appendfsync everysec
appendfsync always
为什么pipeline不同
AOF和Redis事务

与PostgreSQL和MySQL的对比

总结

Credits

附录:关于重启阶段的笔记