乐趣区

关于go:Go实现LRU-Cache

在 web 程序开发中,个别会应用 redis 作为数据缓存缓存一些罕用的数据。然而有时候,当访问量特地微小的时候,redis 也不肯定能抵御这么大的流量的时候,个别会将罕用的数据放入内存中,避难频繁拜访 redis。

因为内存的资源绝对比拟低廉,咱们须要对放入内存中的数据做一些限度以及将一些不罕用的数据清理进来。这个时候就须要用到 LRU 算法(Least recently used,最近起码应用)。

LSU cache 是一种常见的缓存置换算法。会依据缓存拜访的频繁水平,将不罕用的缓存逐步淘汰掉,以开释内存资源。

在 go 语言中,利用自带的 list 双向链表能够实现相干算法性能,以下为代码示例

package lru_cache

import (
    "container/list"
    "sync"
)

type Lrc struct {
    size     int
    list     *list.List
    cacheMap map[string]*list.Element
    lock     sync.RWMutex
}

type data struct {
    key   string
    value interface{}}

func NewLrc(size int) *Lrc {
    return &Lrc{
        size:     size,
        list:     list.New(),
        cacheMap: make(map[string]*list.Element),
    }
}

// Set 写入缓存
func (l *Lrc) Set(key string, value interface{}) {l.lock.Lock()
    defer l.lock.Unlock()

    // 判断是否曾经存在
    if elem, ok := l.cacheMap[key]; ok {l.list.MoveToFront(elem)
        elem.Value.(*data).value = value
        return
    }

    item := &data{
        key:   key,
        value: value,
    }
    elem := l.list.PushFront(item)
    l.cacheMap[key] = elem

    // 判断是否超过长度限度
    if l.list.Len() > l.size && l.size > 0 {deleteItem := l.list.Back()
        l.list.Remove(deleteItem)
        deleteKey := deleteItem.Value.(*data).key
        delete(l.cacheMap, deleteKey)
    }
}

// Get 读取缓存
func (l *Lrc) Get(key string) (interface{}, bool) {l.lock.RLock()
    value, ok := l.cacheMap[key]
    l.lock.RUnlock()

    if ok {l.lock.Lock()
        l.list.MoveToFront(value)
        l.lock.Unlock()
        return value.Value.(*data).value, true
    } else {return nil, false}
}

// Delete 缓存
func (l *Lrc) Delete(key string) {l.lock.RLock()
    value, ok := l.cacheMap[key]
    l.lock.RUnlock()

    if ok {l.lock.Lock()
        l.list.Remove(value)
        key := value.Value.(*data).key
        delete(l.cacheMap, key)
        l.lock.Unlock()}
}

github

退出移动版