压测时程序直接崩溃,堆栈指向 map 赋值,日志显示并发写。日志里能对上时间点,这种反而好排。
多个 goroutine 同时写同一个 map,运行时检测到竞争直接终止进程。这一点先确认清楚,后面就不用反复试。
var mu sync.RWMutex mu.Lock() m[key] = val mu.Unlock() mu.RLock() v := m[key] mu.RUnlock()
「Go 并发 map」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
别只看报错的最后一行,往上看几行,真正的起因通常在上面。同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。
把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。改完隔一天再看一次,当场正常不代表能稳住。
测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。
处理上按这个顺序:用读写锁保护所有访问路径;或改用 sync.Map;缩小临界区避免锁内做耗时操作。
结果对不对很好判断,并发压测不再崩溃,用竞态检测工具跑一遍也没有报告。