原來 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.waitGroupwait等待結果。

至於g.docall(c,key,fn)

當帶着全村人希望的那個請求,獲取到數據,給對應keycall賦值,最終執行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