文档:信号处理

本文档提供了关于 Valkey 如何响应各种 POSIX 信号(如 SIGTERMSIGSEGV)的信息。

SIGTERM 和 SIGINT

SIGTERMSIGINT 信号指示 Valkey 优雅地关闭。当服务器收到这些信号时,它不会立即退出。相反,它会安排一次与 SHUTDOWN 命令执行的关闭类似的关闭。计划的关闭会尽快开始,具体来说,只要当前正在执行的命令终止(如果有),就会开始,并可能额外延迟 0.1 秒或更少。

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

此关闭过程包括以下操作

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

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

自 Redis OSS 7.0 起,服务器在关闭前会等待滞后的副本,最长可达可配置的 shutdown-timeout(默认为 10 秒)。这提供了最大努力来最小化在没有配置保存点且 AOF 未激活的情况下数据丢失的风险。在 7.0 版本之前,在无盘设置中关闭一个负载沉重的主节点更容易导致数据丢失。为了最小化此类设置中的数据丢失风险,请在关闭主节点之前,触发手动 FAILOVER(或 CLUSTER FAILOVER)将主节点降级为副本,并将其中一个副本提升为新的主节点。

SIGSEGV, SIGBUS, SIGFPE 和 SIGILL

以下信号被视为 Valkey 崩溃处理

  • SIGSEGV
  • SIGBUS
  • SIGFPE
  • SIGILL

一旦捕获到这些信号之一,Valkey 会停止任何当前操作并执行以下动作

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

当子进程被终止时会发生什么

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

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

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

  • Valkey 将继续响应读取命令。
  • Valkey 将以 MISCONFIG 错误响应所有写入命令。

此错误状态将持续存在,直到可以成功创建 RDB 文件。

无错误地终止 RDB 文件保存进程

有时用户可能希望在不生成错误的情况下终止 RDB 保存子进程。这可以通过使用 SIGUSR1 信号来完成。该信号以特殊方式处理:它像其他任何信号一样终止子进程,但父进程不会将其检测为严重错误,并将继续服务写入请求。