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来实现这一点。这个信号以特殊方式处理:它像其他信号一样终止子进程,但父进程不会将此检测为关键错误,并会继续处理写请求。

RATE THIS PAGE
Back to top ↑