最近在研究golang的一些優秀開源項目,而後看到了groupcache。該開源庫實現了一個分佈式緩存庫,在分析groupcache的原理和實現以前,咱們先來看看正常業務中會怎麼實現簡單的緩存功能。golang
一個緩存最核心的功能實際上是針對kv對的get和set,若是參照mc和redis,可能還有delete以及過時鍵刪除。下面看下筆者實現的代碼:redis
//簡單緩存模型 var Cache = &CachePool{ items: make(map[string]interface{}), } //new一個全局緩存池 func NewCache() *CachePool { return &CachePool{ items: make(map[string]interface{}), } } type CachePool struct { items map[string]interface{} sync.RWMutex } /** * put a value to CachePool * value = map[string]interface{}{ * "content":"", * "expired":1442342332, * } */ func (cache *CachePool) Put(key string, data map[string]interface{}) { cache.Lock() defer cache.Unlock() cache.items[key] = data } func (cache *CachePool) Get(key string) interface{} { cache.RLock() if val, ok := cache.items[key]; ok { if value, ok := val.(map[string]interface{}); ok { cache.RUnlock() if time.Now().Unix() < value["expires"].(int64) { return value["content"] } else { //過時鍵須要刪除 cache.Lock() delete(cache.items, key) cache.Unlock() return nil } } } cache.RUnlock() return nil } func (cache *CachePool) Del(key string) bool { cache.Lock() defer cache.Unlock() if _, ok := cache.items[key]; ok { delete(cache.items, key) return true } return false }
該緩存採用的是被動緩存的策略,即若是發現get的key過時了纔會刪除該key,所以每次set的數據是一個map類型,包含該key的值以及失效的時間戳。緩存
能夠看下下面的測試代碼:分佈式
func TestCache(t *testing.T) { user1 := make(map[string]interface{}) user1["content"] = "my name is chris" user1["expires"] = time.Now().Add(60 * time.Second).Unix() //計算過時時間 Cache.Put("user1", user1) user2 := map[string]interface{}{"content": "my name is richard", "expires": time.Now().Unix() + 5} Cache.Put("user2", user2) fmt.Println("user1 is: ", Cache.Get("user1")) fmt.Println("user2 is: ", Cache.Get("user2")) //等5秒,等待user2過時 <-time.After(5 * time.Second) fmt.Println(*Cache) fmt.Println("user2 is:", Cache.Get("user2")) fmt.Println(*Cache) }