groupcache源码走读(一):实现一个简单缓存

    最近在研究golang的一些优秀开源项目,而后看到了groupcache。该开源库实现了一个分布式缓存库,在分析groupcache的原理和实现以前,咱们先来看看正常业务中会怎么实现简单的缓存功能。golang

    PS:   若是想直接看groupcache相关的内容,请移步到groupcache的特性以及使用案例

    一个缓存最核心的功能实际上是针对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)
}
相关文章
相关标签/搜索