高效能記憶體快取 ristretto
背景
ristretto
是 dgraph
團隊開源的一款高效能記憶體快取庫,旨在解決高併發場景下的快取效能和吞吐瓶頸。dgraph
專攻的方向是高效能圖資料庫,ristretto
就是其圖資料庫和 KV 資料庫產品的核心依賴。
與 golang 社群常見的其他單程式記憶體快取類庫(groupcache
,bigcache
,fastcache
等)相比,ristretto
在快取命中率和讀寫吞吐率上的綜合表現更優。
ristretto 簡介
ristretto
主要有以下優點:
- 高命中率 - 特殊設計的錄入/驅逐政策
- 驅逐(SampledLFU):與精確 LRU 相當,但在搜尋和資料跟蹤上有更好的效能
- 錄入(TinyLFU):以極小的記憶體開銷獲取額外的效能提升
- 高吞吐率
- 權重感知的驅逐策略 - 價值權重大的條目可以驅逐多個價值權重小的條目
- 依託權重可以擴充套件出快取最大記憶體佔用、快取最多條目數等場景
- 完全併發支援
- 效能指標 - 吞吐量、命中率及其他統計資料的效能指標
- 使用者友好的 API 設計
- 支援指定快取失效時間
ristretto
在 v0.1.0(2021-06-03) 版本釋出時已正式標註為生產可用!
ristretto 使用舉例
構建大小(條目數)受限的快取
讓我們利用 ristretto
構建一個快取條目數最大為 10 的快取試試看:
package main
import (
"fmt"
"github.com/dgraph-io/ristretto"
)
func main() {
cache, err := ristretto.NewCache(&ristretto.Config{
// num of keys to track frequency, usually 10*MaxCost
NumCounters: 100,
// cache size(max num of items)
MaxCost: 10,
// number of keys per Get buffer
BufferItems: 64,
// !important: always set true if not limiting memory
IgnoreInternalCost: true,
})
if err != nil {
panic(err)
}
// put 20(>10) items to cache
for i := 0; i < 20; i++ {
cache.Set(i, i, 1)
}
// wait for value to pass through buffers
cache.Wait()
cntCacheMiss := 0
for i := 0; i < 20; i++ {
if _, ok := cache.Get(i); !ok {
cntCacheMiss++
}
}
fmt.Printf("%d of 20 items missed\n", cntCacheMiss)
}
執行程式碼可以發現最後只有 10 個條目還儲存在快取中
$ go run main.go
10 of 20 item missed
注:當我們的快取並非限制最大記憶體佔用時,
IgnoreInternalCost
一定要設為true
,否則建立出的快取將出現詭異的表現。
測試快取過期時間
還是建立一個簡單的快取,然後存一個過期時間為 1 秒的條目進去,看看接下來的快取讀寫表現:
package main
import (
"log"
"time"
"github.com/dgraph-io/ristretto"
)
func main() {
cache, err := ristretto.NewCache(&ristretto.Config{
NumCounters: 100,
MaxCost: 10,
BufferItems: 64,
IgnoreInternalCost: true,
})
if err != nil {
panic(err)
}
// set item with 1s ttl
cache.SetWithTTL("foo", "bar", 1, time.Second)
// wait for value to pass through buffers
cache.Wait()
if val, ok := cache.Get("foo"); !ok {
log.Printf("cache missing")
} else {
log.Printf("got foo: %v", val)
}
// sleep longer and try again
time.Sleep(2 * time.Second)
if val, ok := cache.Get("foo"); !ok {
log.Printf("cache missing")
} else {
log.Printf("got foo: %v", val)
}
}
執行程式碼可以發現已過期的條目被正常清除出了快取
$ go run main.go
2021/09/03 14:19:56 got foo: bar
2021/09/03 14:19:58 cache missing
總結
ristretto
是支援高併發高吞吐的記憶體快取庫,尤其適用於資料庫、搜尋引擎、檔案系統等 io 密集場景。需要注意的是 ristretto
只適用於單機單程式的快取方案,更像是 golang 中的 Caffeine
(java),並不作為 redis 和 memcache 的替代品。
大家趕快試試吧!
參考資料
- https://github.com/dgraph-io/ristretto
- https://dgraph.io/blog/post/introducing-ristretto-high-perf-go-cache/
- https://github.com/dgraph-io/badger
- https://github.com/hashicorp/golang-lru
- https://github.com/golang/groupcache
歡迎加入 GOLANG 中國社群:https://gocn.vip
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- CQengine高效能記憶體資料快取查詢框架記憶體快取框架
- CPU快取記憶體快取記憶體
- Glide - 記憶體快取與磁碟快取IDE記憶體快取
- DDD 和 記憶體快取記憶體快取
- 記憶體快取選型記憶體快取
- 多核cpu、cpu快取記憶體、快取一致性協議、快取行、記憶體快取記憶體協議
- Oracle資料庫高效能秘密之資料快取記憶體Oracle資料庫快取記憶體
- Android記憶體優化之記憶體快取Android記憶體優化快取
- docker部署redis快取記憶體DockerRedis快取記憶體
- 談談CPU快取記憶體快取記憶體
- CPU快取和記憶體屏障快取記憶體
- django 快取表格到記憶體Django快取記憶體
- Oracle資料庫高效能祕密之資料快取記憶體Oracle資料庫快取記憶體
- Java記憶體快取-通過Google Guava建立快取Java記憶體快取GoGuava
- MRAM快取記憶體的組成快取記憶體
- ASP.NET Core - 快取之記憶體快取(上)ASP.NET快取記憶體
- ASP.NET Core - 快取之記憶體快取(下)ASP.NET快取記憶體
- Java記憶體快取-通過Map定製簡單快取Java記憶體快取
- iOS開發之記憶體與快取iOS記憶體快取
- 建立快取記憶體機制-java版快取記憶體Java
- 記憶體資料庫快取介紹記憶體資料庫快取
- 【Linux】Linux 的快取記憶體Linux快取記憶體
- 淺談快取寫法(三):記憶體快取該如何設計快取記憶體
- 快取記憶體一致性協議MESI與記憶體屏障快取記憶體協議
- 快取及使用 Circuit Breaker 限制記憶體使用快取UI記憶體
- TMCache原始碼分析(一)—TMMemoryCache記憶體快取原始碼記憶體快取
- iOS 除SDWebImage之外清理記憶體中快取iOSWeb記憶體快取
- Oracle Exadata與SGA快取記憶體CQOracle快取記憶體
- TMCache原始碼分析(一)---TMMemoryCache記憶體快取原始碼記憶體快取
- Android記憶體快取LruCache原始碼解析Android記憶體快取原始碼
- Linux手動釋放快取記憶體Linux快取記憶體
- Oracle調整緩衝區快取記憶體Oracle快取記憶體
- 直接記憶體和堆記憶體誰快記憶體
- 鐵威馬NAS如何使用SSD快取記憶體?快取記憶體
- java 記憶體模型-03-快取和重排序Java記憶體模型快取排序
- laravel redirect快閃記憶體blade讀取不到Laravel記憶體
- 記憶體資料庫快取介紹總結記憶體資料庫快取
- 11g result cache 結果快取記憶體快取記憶體