最近在研究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) }