线上偶发进程退出,最后一行是 `fatal error: concurrent map writes`,运行时只打印当前那一个协程的栈,另一个动手写的人完全看不到,日志里也只有一个请求的上下文。乍看像缓存或者权限的锅,追下去往往不是。

go build -race -o app-race .
GORACE='halt_on_error=0' ./app-race
go test -race -run TestCache ./...

追下去是这么回事:多个协程同时写同一个 map,运行时的 map 检测到并发写就直接 fatal,这种错误没法 recover,栈里只给触发的那一次,必须靠竞态检测器把两边都抓出来。

碰到「并发 map 写定位」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。

先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。

具体做法是,先用竞态检测模式重新编译去复现这个问题;按报告里给出的两个调用栈定位共享的那个 map;读多写少的场景换成并发安全表或者读写锁。

验收就看一点,竞态检测器连跑十分钟没有报告,fatal 错误不再出现,进程也能一直稳住。

作者 9823189