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)
}
相關文章
相關標籤/搜索