BigCache 針對 Go 垃圾回收的設計優化
爲什麼有這篇文章
某一天在羣裏摸魚的時候,看到羣裏有人問go map的空間回收問題,把截圖貼上吧:
其實一位羣友發出的問題引起了我注意,他的問題是:go的map的值調用了delete函數是不是不會立即刪除?當然這個問題如果研究過或者深入go的內存分配或者說有了解過go的gc應該知道,這個問題答案。
關於是分段鎖的應用和怎麼去優化gc帶來的影響,有一個開源項目bigcache在這方面做的比較好。
BigCache 的設計
!! 官方作者介紹:快速,併發,基於內存的緩存庫,由於是嵌入式庫也省去了網絡上的開銷,完全基於本地內存,能保存大量數據項的同時並且對
go語言的garbage collection進行了優化。
對併發鎖的顆粒度減小,並且對gc優化它怎麼做的?
-
分段鎖
-
數據二進制存儲,避免讓
gc去嵌套掃描 -
加速併發訪問
-
避免高額的
GC開銷
官方在他們blog上列出了,他們當時寫這個庫的需求:
-
處理
10k rps(寫 5000,讀 5000) -
cache對象至少存活10分鐘 -
更快的響應時間
-
POST請求的每條JSON消息, 一有含有ID,二不大於500字節 -
POST請求添加緩存後,GET能獲取到最新結果
Go map 的問題
我在網上看到資料有提到一個問題:https://github.com/golang/go/issues/9477
問題
大致看了一下這個說了問題就是,Go 1.3和1.4RC1垃圾回收在掃描一個大的map時需要50-70ms時間,問官方怎麼能有什麼辦法減小這個時間。
然後1.5版本,如果 map 的 key 或 value 中都不含指針, GC 便會忽略這個 map。
主要的也就兩個結構體cache和cacheShard:
type cache struct {
shards []*cacheShard // 塊map 解決併發鎖顆粒度問題
hash fnv64a // 哈希函數
}
源碼中的哈希函數用的是fnv64a算法,這個算法的好處是採用位運算的方式在棧上進行運算,避免在堆上分配。
shards用來保存cacheShard的,而cacheShard也就是具體存儲數據的緩存塊,hash會對輸入的key進行計算得到cacheShard座標拿到具體的cacheShard,每個cacheShard都有自己的鎖所以才能保證小鎖顆粒度。
type cacheShard struct {
hashmap map[uint64]uint32 // 外部索引
entries queue.BytesQueue // 存儲序列化也就是byte形式存儲的數據
lock sync.RWMutex // 單個鎖
entryBuffer []byte
onRemove onRemoveCallback // 移除回調函數
isVerbose bool
statsEnabled bool
logger Logger
clock clock
lifeWindow uint64
hashmapStats map[uint64]uint32
stats Stats
}
cacheShard 中的hashmap結構的類型map[uint64]uint32,完全和key使用的string 扯不上關係,有經驗的老司機一眼就看出這其實是個索引,uint64存儲的外部鍵的哈希值,而後面的uint32用處是存儲值的位置,而真正的數據存儲在BytesQueue中,通過外部索引的值uint32類型來獲取裏面的值所在的位置索引,而BytesQueue又是經過二進制序列化的數據,取的時候提供外部索引得到座標取值,最爲妙處的設計就是外部索引不存儲指針,也不存儲符合結構,使得 garbage collection的影響降到最小。
BytesQueue
BytesQueue結構體中的array是存儲主要數據的byte數組,capacity是使用容量,maxCapacity在創建的時候可以指定最大容量,tail類似鏈表裏面的尾指針,下次插入值可以通過這個指針找到插入的位置,count當前存儲的數據條目數,headerBuffer是起到了一個切片發送拷貝時充當零時緩衝區的作用。
有興趣自己去看源代碼吧:https://github.com/allegro/bigcache
總結
BigCache的設計真的很妙,當然這個妙首先你得了解go的gc一些工作方式,然後針對這個這些特定,去優化數據結構,BigCache爲了減小鎖的顆粒度使用了分段分片,然後防止gc對數據進行掃描的耗時,有把數據採用無指針嵌套的二進制方式去存儲,能避免gc去針對底層的數據進行引用存活相關的檢測耗時,唯一缺點就是BigCache數據不能持久化存儲。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/URiURNrXHUYP1v2Q50i7Bg