
告警显示 Load Average 突然升到 20,服务器就一定是 CPU 不够吗?不一定。Linux 的系统负载既包含正在使用或等待 CPU 的任务,也包含处于不可中断睡眠的任务。后者常在等待磁盘、网络文件系统或内核 I/O。把负载直接当成 CPU 使用率,扩容很可能扩错方向。

告警显示 Load Average 突然升到 20,服务器就一定是 CPU 不够吗?不一定。Linux 的系统负载既包含正在使用或等待 CPU 的任务,也包含处于不可中断睡眠的任务。后者常在等待磁盘、网络文件系统或内核 I/O。把负载直接当成 CPU 使用率,扩容很可能扩错方向。

限流、审计和地域判断经常依赖客户端 IP,但应用部署到 CDN、负载均衡器或网关之后,套接字看到的通常只是上一跳代理。直接取 X-Forwarded-For 的最左值看似解决了问题,却可能把攻击者自己填写的地址当成事实。真正可靠的做法不是“找一个请求头”,而是先划出可信代理边界。

一条看似简单的筛选语句漏掉了数据,NOT IN 在测试库正常、上线后却返回空集,统计结果还总比总行数小——这些问题常常不是数据库算错了,而是代码把 NULL 当成了普通值。理解三值逻辑,再把“未知”纳入表结构与测试,才能让查询结果符合业务直觉。

监控系统开始变慢时,团队常先增加内存,却忽略了真正的放大器:标签。一个看似普通的 user_id,可能把一条指标扩成百万条时间序列。治理基数不是少采指标,而是让指标只承担聚合判断,把细节留给更合适的信号。

定时任务、备份脚本和本地索引程序经常用一个空文件表示“正在运行”。但文件存在不等于锁仍被持有,检查后再创建也存在竞争窗口。可靠互斥的关键,是让内核管理锁的归属和释放,而不是自己猜测另一个进程是否活着。

线上进程收到 SIGSEGV 后退出,日志往往只留下“Segmentation fault”。立即重启能恢复服务,却也抹掉了最有价值的寄存器、调用栈与线程状态。Core Dump 是进程崩溃时的内存快照;把它与原始可执行文件、调试符号配对,就能从“它挂了”推进到“哪个线程、哪一行、哪个参数导致了崩溃”。

接口成功时,调用方关心数据;接口失败时,它还要决定提示用户、修正参数、重新登录还是稍后重试。如果服务有时返回字符串、有时返回 HTML、有时把所有失败都塞进 200,每个消费者只能靠猜。错误响应同样是公开契约,应当稳定、可解析,也能帮助值班人员快速定位请求。

布隆过滤器常被一句话概括为“省内存的集合”,但真正上线时,容量估小、哈希不一致或误把“可能存在”当成事实,都可能让它从优化组件变成故障来源。理解它的概率语义,先算容量,再设计兜底,才是安全用法。

接口突然出现连接超时,第一反应常常是“网络抖了”。但请求到达服务器后,要先经过 TCP 握手,再进入等待应用接收的队列;任何一段跟不上,都可能表现成连不上或偶发超时。把监听端口拆成两道队列观察,比盲目调大内核参数更容易找到真正瓶颈。

单机上的 cron 很直接:时间到了就执行。但服务扩成多个副本后,每个实例都会在同一分钟醒来;日报被发三次、账单被结算三次,往往不是“锁没加好”,而是没有先界定谁有资格执行、资格失效后旧执行者还能不能写入。可靠的方案要同时处理抢占、失联和重复副作用。