跳转到主要内容

信号处理

本文档提供有关 KeyDB 如何响应不同 POSIX 信号(如 SIGTERMSIGSEGV 等)接收的信息。

SIGTERM 的处理#

SIGTERM 信号通知 KeyDB 优雅地关闭。当收到此信号时,服务器实际上并不会立即退出,而是会安排一个关闭过程,这与执行 SHUTDOWN 命令时的关闭过程非常相似。计划的关闭会尽快开始,具体来说,是在当前执行的命令(如果有的话)终止后,可能会有 0.1 秒或更短的额外延迟。

如果服务器被一个耗时过长的 Lua 脚本阻塞,且该脚本可以用 SCRIPT KILL 终止,则计划的关闭将在脚本被终止后或其自发终止后立即执行。

在这种情况下执行的关闭包括以下操作:

  • 如果有一个后台子进程正在保存 RDB 文件或执行 AOF 重写,该子进程将被终止。
  • 如果 AOF 已激活,KeyDB 会在 AOF 文件描述符上调用 fsync 系统调用,以将缓冲区刷新到磁盘。
  • 如果 KeyDB 配置为使用 RDB 文件进行磁盘持久化,将执行一次同步(阻塞式)保存。由于保存是以同步方式执行的,因此不会使用额外的内存。
  • 如果服务器以守护进程方式运行,pid 文件将被删除。
  • 如果启用了 Unix 域套接字,它将被删除。
  • 服务器以零退出码退出。

如果 RDB 文件无法保存,关闭将失败,服务器会继续运行以确保数据不丢失。除非收到新的 SIGTERM 信号或发出 SHUTDOWN 命令,否则不会再尝试关闭。

SIGSEGV、SIGBUS、SIGFPE 和 SIGILL 的处理#

以下信号被处理为 KeyDB 崩溃:

  • SIGSEGV
  • SIGBUS
  • SIGFPE
  • SIGILL

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

  • 在日志文件中生成一份错误报告。这包括堆栈跟踪、寄存器转储以及有关客户端状态的信息。
  • 执行快速内存测试,作为对崩溃系统可靠性的初步检查。
  • 如果服务器以守护进程方式运行,pid 文件将被删除。
  • 最后,服务器会注销其自身对收到的信号的处理程序,并再次向自身发送相同的信号,以确保执行默认操作,例如将核心转储到文件系统。

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

当执行“仅追加文件”(AOF)重写的子进程被信号终止时,KeyDB 会将其视为一个错误,并丢弃(可能不完整或已损坏的)AOF 文件。重写将在稍后重新触发。

当执行 RDB 保存的子进程被终止时,KeyDB 会将此情况视为更严重的错误,因为缺少 AOF 文件重写的影响是 AOF 文件变大,而 RDB 文件创建失败的影响是缺乏持久性。

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

  • KeyDB 将继续响应读命令。
  • KeyDB 将对所有写命令回复一个 MISCONFIG 错误。

只有当能够成功创建 RDB 文件时,此错误状态才会被清除。

终止 RDB 文件而不触发错误条件#

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