網站首頁 編程語言 正文
前言:
Gocache是一個基于Go語言編寫的多存儲驅動
的緩存擴展組件。它為您帶來了許多緩存數據的功能。
支持功能
多個緩存驅動存儲:支持內存、redis或您自定義存儲驅動。
支持如下功能:
- 鏈式緩存:使用具有優先級順序的多個緩存(例如,內存然后回退到redis共享緩存)。
- 可加載緩存:允許您調用回調函數將數據放回緩存中。
- 指標緩存,可讓您存儲有關緩存使用情況的指標(命中、未命中、設置成功、設置錯誤……)。
- 自動編組/解組緩存值作為結構的編組器。
- 在存儲中定義默認值并在設置數據時覆蓋它們。
- 通過過期時間和/或使用標簽緩存失效。
- 泛型的使用。
默認情況下,Gocache支持如下幾種緩存驅動:
- 內存 (bigcache) (allegro/bigcache)。
- 內存 (ristretto) (dgraph-io/ristretto)。
- 內存 (go-cache) (patrickmn/go-cache)。
- 內存緩存(bradfitz/memcache)。
- Redis (go-redis/redis)。
- 空閑緩存(coocood/freecache)。
- Pegasus ( apache/incubator-pegasus )基準測試。
開發緣由
在作者的官網博客中提到這樣的幾句話:
當我開始在 GraphQL Go 項目上實現緩存時,它已經有一個內存緩存,它使用了一個具有簡單 API 的小庫,但也使用了另一個內存緩存庫來使用具有不同庫和 API 的批處理模式加載數據,做同樣的事情:緩存項目。后來,我們還有一個需求:除了這個內存緩存之外,我們還想使用 Redis 添加一層分布式緩存,主要是為了避免我們的新 Kubernetes pod 在將新版本的應用程序投入生產時出現空緩存。
因此,作者想到是時候擁有一個統一的API來管理多個緩存存儲:內存、redis、memcache 或任何你想要的。
如何使用
安裝
要開始使用最新版本的 go-cache,您可以使用以下命令:
go get github.com/eko/gocache/v3
為避免嘗試導入庫時出現任何錯誤,請使用以下導入語句:
import ( "github.com/eko/gocache/v3/cache" "github.com/eko/gocache/v3/store" )
如果您遇到任何錯誤,請務必運行go mod tidy以清理您的 go.mod 文件。
存儲適配器
首先,當您要緩存項目時,您必須選擇要緩存項目的位置:在內存中?在共享的 redis 或 memcache 中?或者可能在另一個存儲中。
目前,Gocache 實現了以下存儲:
- BigCache:內存中的存儲。
- Ristretto : DGraph 提供的另一個內存存儲。
- Memcache:基于 bradfitz/gomemcache 客戶端庫的 memcache 存儲。
- Redis:基于 go-redis/redis 客戶端庫的 redis 存儲。
所有這些商店都實現了一個非常簡單的 API,它遵循以下接口:
type StoreInterface interface { Get(key interface{}) (interface{}, error) Set(key interface{}, value interface{}, options *Options) error Delete(key interface{}) error Invalidate(options InvalidateOptions) error Clear() error GetType() string }
此接口代表您可以在商店中執行的所有操作,并且每個操作都調用客戶端庫中的必要方法。所有這些存儲都有不同的配置,具體取決于您要使用的客戶端庫,
例如,初始化 Memcache 存儲:
store := store.NewMemcache( memcache.New("10.0.0.1:11211", "10.0.0.2:11211", "10.0.0.3:11212"), &store.Options{ Expiration: 10*time.Second, }, )
然后,必須將初始化的存儲傳遞給緩存對象構造函數。
緩存適配器
一個緩存接口來統治它們。
緩存接口與存儲接口完全相同,因為基本上,緩存將對存儲執行操作:
type CacheInterface interface { Get(key interface{}) (interface{}, error) Set(key, object interface{}, options *store.Options) error Delete(key interface{}) error Invalidate(options store.InvalidateOptions) error Clear() error GetType() string }
使用這個界面,我可以對緩存項執行所有必要的操作:設置、獲取、刪除、無效數據、清除所有緩存和另一個方法 (GetType),它可以讓我知道當前緩存項是什么,很有用在某些情況下。
從這個接口開始,實現的緩存類型如下:
-
Cache:
允許操作來自給定存儲的數據的基本緩存。 -
Chain:
一個特殊的緩存適配器,允許鏈接多個緩存(可能是因為你有一個內存緩存,一個redis緩存等......)。 -
Loadable:
?一個特殊的緩存適配器,允許指定一種回調函數,如果過期或失效,自動將數據重新加載到緩存中。 -
Metric:
一個特殊的緩存適配器,允許存儲有關緩存數據的指標:設置、獲取、失效、成功與否的項目數。 當所有這些緩存都實現相同的接口并且可以相互包裝時,美妙之處就出現了:一個指標緩存可以采用一個可加載的緩存,該緩存可以采用一個可以采用多個緩存的鏈式緩存。
下面是一個簡單的 Memcache 示例:
memcacheStore := store.NewMemcache( memcache.New("10.0.0.1:11211", "10.0.0.2:11211", "10.0.0.3:11212"), &store.Options{ Expiration: 10*time.Second, }, ) cacheManager := cache.New(memcacheStore) err := cacheManager.Set("my-key", []byte("my-value"), &cache.Options{ Expiration: 15*time.Second, // Override default value of 10 seconds defined in the store }) if err != nil { panic(err) } value := cacheManager.Get("my-key") cacheManager.Delete("my-key") cacheManager.Clear() // Clears the entire cache, in case you want to flush all cache
現在,假設您想要一個鏈式緩存,其中包含一個內存 Ristretto 存儲和一個分布式 Redis 存儲作為后備,
并帶有一個 marshaller 和指標作為結果:
// Initialize Ristretto cache and Redis client ristrettoCache, err := ristretto.NewCache(&ristretto.Config{NumCounters: 1000, MaxCost: 100, BufferItems: 64}) if err != nil { panic(err) } redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"}) // Initialize stores ristrettoStore := store.NewRistretto(ristrettoCache, nil) redisStore := store.NewRedis(redisClient, &cache.Options{Expiration: 5*time.Second}) // Initialize Prometheus metrics promMetrics := metrics.NewPrometheus("my-amazing-app") // Initialize chained cache cacheManager := cache.NewMetric(promMetrics, cache.NewChain( cache.New(ristrettoStore), cache.New(redisStore), )) // Initializes a marshaler marshal := marshaler.New(cacheManager) key := BookQuery{Slug: "my-test-amazing-book"} value := Book{ID: 1, Name: "My test amazing book", Slug: "my-test-amazing-book"} // Set the value in cache using given key err = marshal.Set(key, value) if err != nil { panic(err) } returnedValue, err := marshal.Get(key, new(Book)) if err != nil { panic(err) } // Then, do what you want with the value
我們還沒有談到 Marshaler,但它是 Gocache 的另一個功能:我們提供了一項服務來幫助您自動編組/解組您的對象從/到您的存儲。
這在使用 struct 對象作為鍵而不是內存存儲時很有用,因為您必須將對象轉換為字節。
所有這些功能:帶有內存和 redis 的鏈式緩存、Prometheus 指標和封送處理程序只需大約 20 行代碼即可完成。
編寫自己的緩存或存儲
如果您想實現自己的專有緩存,也很容易做到。
這是一個簡單的示例,以防您想要記錄在緩存中完成的每個操作(這不是一個好主意,但很好,這是一個簡單的 todo 示例):
package customcache import ( "log" "github.com/eko/gocache/cache" "github.com/eko/gocache/store" ) const LoggableType = "loggable" type LoggableCache struct { cache cache.CacheInterface } func NewLoggable(cache cache.CacheInterface) *LoggableCache { return &LoggableCache{ cache: cache, } } func (c *LoggableCache) Get(key interface{}) (interface{}, error) { log.Print("Get some data...") return c.cache.Get(key) } func (c *LoggableCache) Set(key, object interface{}, options *store.Options) error { log.Print("Set some data...") return c.cache.Set(key, object, options) } func (c *LoggableCache) Delete(key interface{}) error { log.Print("Delete some data...") return c.cache.Delete(key) } func (c *LoggableCache) Invalidate(options store.InvalidateOptions) error { log.Print("Invalidate some data...") return c.cache.Invalidate(options) } func (c *LoggableCache) Clear() error { log.Print("Clear some data...") return c.cache.Clear() } func (c *LoggableCache) GetType() string { return LoggableType }
同樣,您也可以實現自定義存儲。如果您認為其他人可以使您的緩存或存儲實現受益,請不要猶豫,打開拉取請求并直接為項目做出貢獻,以便我們一起討論您的想法并帶來更強大的緩存庫。
壓縮
生成模擬測試數據:
go get github.com/golang/mock/mockgen make mocks
測試套件可以運行:
make test # run unit test make benchmark-store # run benchmark test
原文鏈接:https://juejin.cn/post/7140292921739182116
相關推薦
- 2022-04-21 R語言繪制帶ErrorBar的分組條形圖代碼的分享_R語言
- 2022-01-21 win10 如何做到 C盤 的絕對干凈,所有軟件都安裝到D盤,C盤只用來存操作系統。
- 2022-02-23 IDEA git 拉取項目時報 No tracked branch configured for b
- 2022-05-11 Restful的Get請求參數為List
- 2023-01-10 Go語言defer與return執行的先后順序詳解_Golang
- 2022-03-09 C#判斷DLL文件是32位還是64位的示例代碼_C#教程
- 2023-01-28 架構師說比起404我們更怕200錯誤_相關技巧
- 2023-12-20 UML類圖中各箭頭表示總結
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支