Redis 信号处理
Redis 如何处理常见的 Unix 信号
Redis Open Source |
---|
本文档提供了关于 Redis 如何响应不同 POSIX 信号(例如 SIGTERM
和 SIGSEGV
)的信息。
本文档中的信息仅适用于 Redis 2.6 或更高版本。
SIGTERM 和 SIGINT
SIGTERM
和 SIGINT
信号指示 Redis 优雅地关闭。当服务器收到这些信号时,它不会立即退出。相反,它会安排一次关机,这类似于通过 SHUTDOWN
命令执行的关机。安排的关机尽快开始,具体来说,只要当前正在执行的命令(如果有)终止,就会开始,可能会有额外的 0.1 秒或更短的延迟。
如果服务器被长时间运行的 Lua 脚本阻塞,如果可能,使用 SCRIPT KILL
终止该脚本。安排的关机将在脚本被终止或自发终止后立即运行。
此关机过程包括以下操作
- 如果有副本在复制方面落后
- 使用
CLIENT PAUSE
和WRITE
选项暂停尝试写入的客户端。 - 等待副本赶上主节点的复制偏移量,最多等待配置的
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 文件会被删除。
- 最后,服务器会注销自身对收到的信号的信号处理程序,并向自身重新发送相同的信号,以确保执行默认操作,例如在文件系统上转储核心文件。
子进程被杀死时会发生什么
当执行仅追加文件 (AOF) 重写的子进程被信号杀死时,Redis 会将其视为错误并丢弃(可能部分或已损坏的)AOF 文件。稍后会再次尝试重写。
当执行 RDB 保存的子进程被杀死时,Redis 将此情况视为更严重的错误。虽然 AOF 文件重写失败可能导致 AOF 文件增大,但 RDB 文件创建失败会降低持久性。
由于生成 RDB 文件的子进程被信号杀死,或者子进程以错误(非零退出码)退出,Redis 将进入特殊错误状态,不再接受任何写入命令。
- Redis 将继续响应读取命令。
- Redis 将以
MISCONFIG
错误回复所有写入命令。
此错误状态将持续存在,直到能够成功创建 RDB 文件为止。
无错误地终止 RDB 保存进程
有时用户可能希望终止 RDB 保存子进程而不产生错误。自 Redis 2.6.10 版本起,可以使用信号 SIGUSR1
来实现这一点。此信号以特殊方式处理:它像任何其他信号一样终止子进程,但父进程不会将其检测为关键错误,并会继续处理写入请求。