实战篇:Redis 异常重启故障复盘
Redis 异常重启故障复盘故障时间2026-04-22 06:09影响范围游戏测试服 Redis 连接报错复盘时间2026-04-22一、问题现象早上上班发现监控告警查看 LogViewer 发现凌晨 06:09 集中爆发一批 Redis 连接错误Redis connection refused / Connection reset by peer错误日志显示大量服务实例同时失去 Redis 连接且持续时间很短几十秒内恢复这不符合正常的网络抖动或 Redis 自身崩溃的特征。二、初步排查2.1 查看 Redis 服务状态journalctl-uredis-server--since2026-04-22 06:00:00--until2026-04-22 06:15:00输出关键日志Apr 22 06:09:24 game systemd[1]: Stopping redis-server.service - Advanced key-value store... Apr 22 06:09:25 game systemd[1]: redis-server.service: Deactivated successfully. Apr 22 06:09:25 game systemd[1]: Stopped redis-server.service - Advanced key-value store. Apr 22 06:09:25 game systemd[1]: Starting redis-server.service - Advanced key-value store... Apr 22 06:09:36 game systemd[1]: Started redis-server.service - Advanced key-value store.分析Redis 经历了stop → start的完整生命周期停止和启动间隔仅11 秒说明是被外部信号触发的正常关闭如果是 Redis 自身崩溃日志会显示Segmentation fault或Aborted如果是 OOM日志会显示OOM killed结论Redis 不是「崩溃」而是「被关闭后重启」。需要找出是谁发的停止信号。三、定位根因3.1 第一步Redis 自己想停吗确认了 Redis 是被关闭而非崩溃后第一反应是Redis 自己想停的吗检查 Redis 服务自身状态systemctl status redis-server预期结果如果是 Redis 自身崩溃Active:会显示failed或最近一次启动时间异常如果是 OOM 被 killdmesg | grep -i redis或journalctl -b | grep -i oom应该能看到Out of memory相关日志实际情况Redis 服务状态正常最近一次启动时间在凌晨 06:09:36说明Redis 自己没有「想」停是被叫停的。3.2 第二步是不是系统层面的操作既然不是 Redis 自身问题接下来怀疑几个方向定时任务cron有人写了凌晨重启 Redis 的脚本系统服务systemd其他 service 的依赖导致的系统更新apt自动更新动了 Redis 的包先检查cron 定时任务# 查看所有用户的 crontabcrontab-lsudocat/etc/crontabsudols-la/etc/cron.d/结果没有发现任何重启 Redis 的 cron 任务。3.3 第三步检查 systemd 定时器继续排查systemd timer——这是最容易被忽略的「定时搞事情」选手# 列出所有活跃的 timersystemctl list-timers--all输出内容发现可疑点apt-daily-upgrade.timer上次触发时间是06:09:10而 Redis 停止时间是06:09:24——只差了 14 秒这时间吻合度太巧了强烈怀疑是它干的。3.4 第四步直接验证 apt-daily-upgrade.timer为了不靠「感觉」下结论直接用数据说话systemctl show apt-daily-upgrade.timer-pLastTriggerUSec-pNextElapseUSecRealtime-pTriggers输出NextElapseUSecRealtimeThu 2026-04-23 06:16:35 CST LastTriggerUSecWed 2026-04-22 06:09:10 CST Triggersapt-daily-upgrade.service理论依据systemctl show unit是查看 systemd 单元属性的一手工具比systemctl status更底层返回的是运行时状态而非解析后的格式。关键字段含义字段含义LastTriggerUSec上一次触发时间UTC 时间戳可转换为本地时间NextElapseUSecRealtime下一次触发时间日历时间Triggers该 timer 触发后会启动哪个 service时间吻合度分析事件时间apt-daily-upgrade.timer 触发06:09:10Redis 收到停止信号06:09:24时间差14 秒14 秒的间隔非常合理——apt-daily-upgrade.timer 触发后systemd 启动 apt-daily-upgrade.service该服务执行apt-get upgrade更新系统包。更新涉及 Redis 依赖的动态库或 Redis 本身时systemd 会根据依赖关系自动重启 Redis。3.5 第五步理论依据——apt-daily-upgrade.timer 是什么理论依据apt-daily.timer和apt-daily-upgrade.timer是 Ubuntu/Debian 系统内置的自动更新机制Timer作用默认触发时间apt-daily.timer每日执行apt update刷新软件包索引每天 06:00 左右apt-daily-upgrade.timer每日执行apt upgrade安装安全更新每天 06:00 左右比 daily 晚几分钟这些 timer 的触发时间由/lib/systemd/system/apt-daily.timer和/etc/crontab定义。系统会根据上一次触发时间 24小时计算下一次触发时间但由于 jitter随机偏移和系统启动延迟实际触发时间会有几分钟波动。引用Debian/Ubuntu 官方文档《AutomaticUpdates》明确指出这两个 timer 是系统级别的自动更新机制会在触发时执行 apt 操作可能导致依赖包更新和服务重启。3.6 第六步日志交叉验证需要 sudo 权限由于初始排查没有 root 权限让运维同学执行以下命令 100% 确认根因# 查看 apt-daily-upgrade 和 redis-server 在该时间段的日志sudojournalctl-uapt-daily-upgrade-uredis-server\--since2026-04-22 06:00:00\--until2026-04-22 06:20:00\-oshort-iso# 查看 dpkg 包管理日志中的软件包变更sudogrep-E2026-04-22 06:0[0-9]:|redis|redis-server|upgrade|install|configure/var/log/dpkg.log理论依据journalctl -u -u-u可以叠加用于关联多个服务的日志。--since/--until指定时间窗口-o short-iso输出 ISO 格式时间戳便于对比。/var/log/dpkg.log这是 Debian 包管理器的操作日志记录每次apt/dpkg安装、配置、升级的具体软件包名称和时间。格式为2026-04-22 06:09:15 status installed redis-server:amd64 6.0.16-1 2026-04-22 06:09:16 configure redis-server 6.0.16-1通过关联dpkg.log的时间和apt-daily-upgrade.service的日志可以精确定位是哪个软件包触发了 Redis 重启。四、根因确认4.1 事件链路apt-daily-upgrade.timer (06:09:10 触发) ↓ apt-daily-upgrade.service 启动 ↓ 执行 apt-get upgrade 安装待更新包 ↓ 更新 Redis 相关包或依赖库如 libsystemd、glibc 等 ↓ dpkg 触发 postinst 脚本 → systemctl daemon-reload ↓ systemd 重新加载 redis-server.service ↓ redis-server 被停止 → 立即启动 ↓ 业务侧 Redis 连接报错06:09:24 - 06:09:36五、解决方案5.1 当前处理关闭 apt-daily-upgrade.timer目前项目处于测试阶段为了避免自动更新对测试的影响直接关闭该 timer# 停止并禁用 apt-daily-upgrade.timersudosystemctl stop apt-daily-upgrade.timersudosystemctl disable apt-daily-upgrade.timer# 确认状态systemctl status apt-daily-upgrade.timer验证# 确认所有 timer 状态systemctl list-timers--all|grepapt输出应为空说明 apt-daily-upgrade 定时器已停止。5.2 后续建议上线前正式上线前建议评估以下方案方案做法适用场景方案 A调整触发时间将触发时间调整到业务低峰期如凌晨 04:00并设置维护窗口允许短暂服务中断方案 B分步升级使用Unattended-Upgrade的MinimalSteps选项减少服务中断需要精细控制方案 C服务保护在redis-server.service中设置Restarton-failure减少中断影响无法控制更新时机六、经验总结6.1 排查思路阶段操作目的现象观察查看 Redis 日志确认是 stop→start 而非 crash缩小排查范围不是 Redis 自身问题排除 cron检查 crontab 和 cron.d排除定时任务误操作扫描 timersystemctl list-timers 快速定位可疑定时器建立时间关联数据验证systemctl show 确认 timer 触发时间量化吻合度日志交叉验证journalctl dpkg.log 确认根因100% 闭环6.2 关键命令速查# 1. 查看服务状态systemctl statusservice# 2. 检查 cron 定时任务crontab-lsudocat/etc/crontabsudols-la/etc/cron.d/# 3. 列出所有活跃的 timersystemctl list-timers--all# 4. 查看 timer 的触发时间systemctl showtimer-pLastTriggerUSec-pNextElapseUSecRealtime-pTriggers# 5. 关联查看多服务日志journalctl-uservice1-uservice2--sinceHH:MM:SS# 6. 查看包管理变更历史grepdate/var/log/dpkg.log6.3 教训测试环境也要关注系统级定时任务apt-daily-upgrade 是 Ubuntu 默认开启的即使在测试机上也可能触发排查要「先猜后证」根据时间吻合度大胆假设再用日志小心求证没有 root 权限也能排查systemctl show 和 systemctl list-timers 不需要 root只需读权限七、参考文档Ubuntu AutomaticUpdates 官方文档systemd.timer 中文手册Debian apt/dpkg 日志说明