Redis 信号处理

Redis 如何处理常见 Unix 信号

本文档提供了有关 Redis 如何对不同 POSIX 信号(如 SIGTERMSIGSEGV)做出反应的信息。

本文档中的信息仅适用于 Redis 2.6 或更高版本

SIGTERM 和 SIGINT

SIGTERMSIGINT 信号告诉 Redis 正常关闭。当服务器收到此信号时,它不会立即退出。相反,它会安排一个类似于 SHUTDOWN 命令执行的关闭。计划的关闭会尽快开始,具体来说,只要正在执行的当前命令终止(如果有),可能会额外延迟 0.1 秒或更短时间。

如果服务器被一个长时间运行的 Lua 脚本阻塞,请使用 SCRIPT KILL 杀死脚本(如果可能)。计划的关闭将在脚本被杀死或自发终止后立即运行。

此关闭过程包括以下操作

  • 如果任何副本在复制中落后
    • 暂停尝试使用 CLIENT PAUSEWRITE 选项写入的客户端。
    • 等待最多已配置的 shutdown-timeout(默认 10 秒)以使副本赶上主服务器的复制偏移量。
  • 如果后台子进程正在保存 RDB 文件或执行 AOF 重写,则会终止子进程。
  • 如果 AOF 处于活动状态,Redis 会在 AOF 文件描述符上调用 fsync 系统调用以刷新磁盘上的缓冲区。
  • 如果 Redis 配置为使用 RDB 文件在磁盘上持久保存,则会执行同步(阻塞)保存。由于保存是同步的,因此不会使用任何其他内存。
  • 如果服务器已守护进程化,则会删除 PID 文件。
  • 如果启用了 Unix 域套接字,则会将其删除。
  • 服务器退出,退出代码为零。

如果无法保存 RDB 文件,则关闭失败,并且服务器继续运行以确保不会丢失数据。同样,如果用户刚刚打开 AOF,并且服务器触发了第一个 AOF 重写以创建初始 AOF 文件,但无法保存此文件,则关闭失败,并且服务器继续运行。自 Redis 2.6.11 以来,除非收到新的 SIGTERM 或发出 SHUTDOWN 命令,否则不会再尝试关闭。

自 Redis 7.0 以来,服务器在关闭之前最多等待落后的副本达到可配置的 shutdown-timeout,默认值为 10 秒。这提供了最大努力来最小化在未配置保存点且 AOF 已停用的情况下数据丢失的风险。在 7.0 版本之前,在无磁盘设置中关闭负载较重的主节点更有可能导致数据丢失。为了最大程度地降低此类设置中的数据丢失风险,请触发手动 FAILOVER(或 CLUSTER FAILOVER)以将主服务器降级为副本,并在关闭主服务器之前将其中一个副本提升为新主服务器。

SIGSEGV、SIGBUS、SIGFPE 和 SIGILL

以下信号被视为 Redis 崩溃

  • SIGSEGV
  • SIGBUS
  • SIGFPE
  • SIGILL

一旦捕获到其中一个信号,Redis 就会停止任何当前操作并执行以下操作

  • 向日志文件添加错误报告。这包括堆栈跟踪、寄存器转储以及有关客户端状态的信息。
  • 自 Redis 2.8 起,会执行快速内存测试,作为崩溃系统可靠性的首次检查。
  • 如果服务器是守护进程,则会删除 PID 文件。
  • 最后,服务器取消注册其自身对接收信号的信号处理程序,并向自身重新发送相同信号,以确保执行默认操作,例如将核心转储到文件系统上。

子进程被杀死时会发生什么

当执行仅附加文件重写的子进程被信号杀死时,Redis 将此视为错误,并丢弃(可能是部分或损坏的)AOF 文件。它将稍后再次尝试重写。

当执行 RDB 保存的子进程被杀死时,Redis 将此条件视为更严重的错误。虽然 AOF 文件重写失败可能导致 AOF 文件扩大,但 RDB 文件创建失败会降低持久性。

由于生成 RDB 文件的子进程被信号杀死,或当子进程退出时出现错误(非零退出代码),Redis 进入特殊错误条件,不再接受进一步的写入命令。

  • Redis 将继续响应读取命令。
  • Redis 将使用 MISCONFIG 错误响应所有写入命令。

此错误条件将持续存在,直到成功创建 RDB 文件为止。

无错误地终止 RDB 文件

有时,用户可能希望终止 RDB 保存子进程,而不会生成错误。自 Redis 2.6.10 版本起,可以使用信号 SIGUSR1 来执行此操作。此信号以特殊方式处理:它像任何其他信号一样终止子进程,但父进程不会将其检测为严重错误,并将继续处理写入请求。

对本页进行评分