prod对比dev:一次上线故障复盘
prod对比不能只看配置名称,真正的差距藏在数据、权限、流量和容错机制里。本文用一个可复现的订单接口案例,还原代码从dev进入prod后出现超时、回滚和修复的全过程,并回答环境隔离、配置同步、测试失真等常见问题。
问题一:dev正常,prod为什么超时?
案例来自一个可复现的订单接口:开发环境只有5000条模拟订单,数据库和应用还在同一内网;进入prod后,订单表达到千万级,数据库独立部署,接口必须经过网关、鉴权和日志链路。相同的列表查询,在dev中耗时约40毫秒,prod高峰时超过3秒。
排查后发现,查询条件中的user_id没有联合索引。dev数据少,全表扫描也看不出问题;prod数据量和并发一上来,连接池很快被慢查询占满。这里的prod对比重点不是“服务器更强”,而是数据规模、网络跳数和真实并发完全不同。
问题二:为什么上线前测试没拦住?
团队虽然有staging,但测试库每天重建,只保留少量脱敏数据,也没有模拟高峰流量。功能测试验证了结果正确,却没有检查执行计划、P95延迟和连接池占用。上线十分钟后,监控显示错误率从0.2%升到7%,这才触发回滚。
更稳的做法是给staging准备接近prod量级的数据分布,并在发布门禁中加入三项硬指标:慢查询数量、接口P95延迟、数据库连接池峰值。数据不必复制生产原文,但字段基数、冷热比例和索引结构要接近。
问题三:这次是怎么止损的?
处置顺序很关键:先停止继续放量,再把流量切回旧版本,随后保存慢查询日志和发布记录。确认旧版本恢复稳定后,才在线下补联合索引并重放请求。不要在prod高峰期边猜边改,更别一着急就重启数据库,那会抹掉部分现场信息。
修复版先放给5%流量,观察十分钟后扩大到25%,最终全量。接口P95降到180毫秒以内,连接池峰值也回到安全区间。整个过程同时补上了回滚脚本,避免下一次还靠人工找旧镜像。
问题四:prod对比到底该比什么?
建议固定比较六项:配置来源、数据规模、外部依赖、网络路径、权限边界、监控告警。版本号一致只能证明代码包相同,不能证明运行条件一致。尤其要检查超时、重试、缓存和限流,它们最容易在不同环境里悄悄分叉。
这次复盘的核心不是“prod更复杂”这句废话,而是建立可核对的环境差异表。每次上线前更新差异、标出不可模拟项,再为不可模拟项准备灰度和回滚,prod才不会变成昂贵的测试场。
常见问题
prod和dev可以共用数据库吗?
不建议。共库会带来误删、测试数据污染和权限越界风险。至少应使用独立实例、独立账号,并禁止开发账号直接写入生产数据。
staging必须和prod配置完全一样吗?
不必追求机器数量完全一致,但运行时版本、网络拓扑、关键中间件和配置加载方式应尽量一致,并明确记录无法复刻的差异。
prod故障时应该先修还是先回滚?
若故障与新版本高度相关且回滚路径可靠,通常先止损回滚。修复应在保留日志、指标和请求样本后进行。