go tool pprof -http=:8080 mutex.out curl -o mutex.out localhost:6060/debug/pprof/mutex grep -n 'RLock' -r . | head -20
读多写少的缓存服务上线后偶发整站卡住,pprof 里一片 `sync.runtime_SemacquireMutex`,没有任何报错,几十秒后又自己恢复,重启和扩容都只能暂时缓解。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,持有读锁的函数内部又调用需要写锁的方法,RWMutex 不支持锁升级,写锁等所有读锁释放,而读锁正等着写锁,形成环路,只能等超时或者重启来解开。
「RWMutex 锁升级」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
处理上按这个顺序:把读锁的范围收缩到只读数据的那几行代码;需要回写的时候先释放读锁再重新去取写锁;顺着同一条调用链复查有没有嵌套加锁的地方。
改完只确认一件事:压测时不再出现整段卡顿,锁等待时间明显下降,也没再复现。
