原來 sync-Once 還能這麼用
介紹
sync.Once
估計大家都不陌生,官方介紹中,
Once is an object that will perform exactly one action
正是因爲這個特性,Once
常常被用於單例對象的初始化場景。
也正是因爲這個特性,其實它還能做一些其他的事情。
緩存擊穿
日常背誦八股文,我相信你們對緩存擊穿這個詞特別熟悉。
緩存擊穿一般代指熱點key
緩存失效 (到期 | 刪了),同一時刻大量對熱點key
的併發請求。緩存找不到數據,所有請求都打入到DB
層。此時,身爲開發的你,明天和意外就不知道哪個先到了。
爲了防止這種情況發生,針對相同key
的請求,只需要一個請求 (A) 到達DB
層取數據,其他請求等待A
通知就行了。
就像這樣,
圖片來源:[1]
singleflight
Go
裏有很多防緩存擊穿的工具,比如singleflight
庫。
通過上面簡單的代碼大概能看出,其實就是對key
做了緩存。
把一個key
對應call
結構存儲在map
中。保證只有一個key
真正執行fn()
服務 ,其他請求則通過sync.waitGroup
的wait
等待結果。
至於g.docall(c,key,fn)
,
當帶着全村人希望的那個請求,獲取到數據,給對應key
的call
賦值,最終執行done
,通知等待這個key
全村的村民獲取數據。
代碼並不複雜。
自定義 singleflight
我們也可以實現一個簡易版本的。
代碼整體不難,主要的點在於我們是通過通道來實現通知自家兄弟取數據。
最後,讓我們使用Once
來達到同樣的效果,不然標題不白起了嘛。
上面核心代碼都寫出來了,實際開發中需要對請求資源做一些超時控制等操作。
總結
平常對Once
的使用只停留在初始化工作上,而弱化了它的使用場景。對於其他工具也是一個道理,這就需要去積累和挖掘了。
附錄
[1]https://medium.com/codex/caching-system-stability-766bf5fff69f
https://blog.chuie.io/posts/synconce/
如果文章對你有所幫助,點贊、轉發、留言都是一種支持!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/zFDtkpRUgikgntaNxa2fGw