Node 进程被 SIGKILL 时的数据保护:优雅退出实战

线上服务最怕的不是 bug,而是进程被操作系统突然杀掉时导致的数据不一致。本文记录我围绕 SIGTERM 与 SIGKILL 设计的一套数据保护方案,包括信号处理、systemd 兜底、快照自愈与压测验证。

1. SIGTERM vs SIGKILL 的本质区别

SIGTERM 是「请优雅退出」,进程可以监听它并在有限时间内保存状态、关闭连接;SIGKILL 是「立即终止」,进程没有任何反应机会,所有未落盘的数据都会丢失。因此我们的目标不是阻止 SIGKILL,而是让数据在多数情况下已经安全。

2. process.on('SIGTERM') 里能做什么

我在 server.js 里注册了对 SIGTERM 和 SIGINT 的监听。收到信号后,先停止接收新连接,等待已有请求处理完成,再把内存中的写队列刷到磁盘,最后调用 process.exit(0)。注意:Node.js 在 Windows 上对 SIGTERM 支持有限,所以 Linux 生产环境才是这套方案的主战场。

3. systemd Restart=always 兜底

systemd 的 unit 文件里配置了 Restart=always 和 RestartSec=2。即使进程因为 OOM 被系统 SIGKILL,systemd 也会在两秒后自动拉起新实例。配合上面的原子写入策略,重启后最多丢失最近一个快照间隔内的数据。

4. 快照 + 校验的自愈方案

我实现了一个定时快照任务,每 60 秒把内存状态写一份临时 JSON,校验通过后再替换为主数据文件。启动时会自动校验主数据文件,如果解析失败就回滚到上一个快照。这样即使发生最坏情况,也能快速自愈,而不是直接报错退出。

5. 压测验证方法

为了验证这套机制,我写了一个压测脚本:持续向接口发送写请求,同时随机执行 kill -9。跑了一小时后统计启动恢复成功率与数据丢失量。结果显示成功率接近 100%,丢失数据量严格控制在两次快照间隔以内,满足早期项目的可用性要求。

← 返回首页