golang下的併發、並行優化
GO語言是非常適合高併發場景的,那麼,業務系統具體會遇到哪些高併發的場景呢?該如何考慮效能開銷呢?那麼本文就筆者在業務系統常常遇到的問題來拋磚引玉~
請求合併
這是什麼場景呢?回源!回源DB,二進位制流回源源站等等~高併發的場景下,大量使用者訪問同一個物件,那麼做請求合併可以節省非常可觀的資源,singleflight~ 當然這是程序內的用法。
批量協議
好像和請求合併有點像?不太一樣。比較經典的case就是redis的pipeline。能批量就批量,減少太多的封包解包,減少cpu和頻寬~
merge請求
額~~merge什麼?比如一個視訊id更新計數,那麼9->18->25......對了,計數從1漲到100,難道我要寫100次db嗎?很明顯,可以記憶體裡merge~~
並行請求
這個用法在閘道器服務就非常常見啦~當你的服務需要聚合A、B、C這3個系統的資料,而A、B和C之間沒有依賴,那麼完全可以並行請求。golang裡常用errgroup 去實現。
減少鎖以及系統呼叫
有些情況鎖是很難避免的,但是可以通過一些鎖粒度拆分優化去減少鎖的開銷。系統呼叫對cpu的開銷都是挺明顯的,具體可以壓測檢視top,us%的開銷在90%以上,說明效能優化還是可以的。
序列化協議,json和pb
這裡既包括API的協議,也同時包括快取物件的序列化協議。快取的訪問常常會幾倍於api請求,經常有放大,所以更要重視。
非同步處理,使用channel,而不是無限制go func()
比如更新快取的場景。這點挺容易理解,無限制的goroutine會帶來大量的context切換,浪費cpu。當然channel的長度要做限制和監控。消費者goroutine數可以適當配置。