Redis 信号处理

Redis 如何处理常见的 Unix 信号

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

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

SIGTERM 和 SIGINT

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

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

此关闭过程包括以下操作

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

如果无法保存 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 文件会被删除。
  • 最后,服务器会取消注册自己对接收到的信号的信号处理程序,并将相同的信号重新发送给自己,以确保执行默认操作,例如将核心转储到文件系统。

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

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

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

由于生成 RDB 文件的子进程被信号杀死,或者子进程以错误退出(非零退出代码)退出,Redis 会进入一个特殊错误状态,在此状态下不再接受任何写入命令。

  • Redis 将继续响应读取命令。
  • Redis 将对所有写入命令返回 MISCONFIG 错误。

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

杀死 RDB 文件,不产生错误

有时用户可能希望杀死正在保存 RDB 的子进程,而不产生错误。从 Redis 2.6.10 版本开始,可以使用信号 SIGUSR1 来实现这一点。此信号的处理方式特殊:它像其他信号一样杀死子进程,但父进程不会将其检测为严重错误,并继续为写入请求提供服务。

RATE THIS PAGE
Back to top ↑