实际业务实现中常常会使用到本地缓存,用以减少对实际存储的访问,我们会针对不同的使用场景设计不同的缓存模式,但是基本的实现方式都是一个巨大的Map/Table(不同语言)。下面用go来说,总体的实现都是通过一个,根据不同的需求,LFU,LRU再设计map里面具体的entry的struct,保存需要的计数用来做淘汰,下面从不同使用角度来说明一下
普通的保存配置项的本地缓存
实际使用中,某些中台服务/服务发现需要拉取比较多的etcd配置(也有可能在其他存储),但是整体上还是有限的。此时不需要考虑key的淘汰,存在本地不会占用过多内存。目标是反而是为了避免对etcd或存储的长期访问以及保证配置有一个实时更新的机制。
有两种方法
- 定期去pull
- 本地需要维护配置的全量,需要预先知道所有配置, 不灵活
- 所有配置同时拉取对存储是个负担,可能需要随机打散
- 读取完了以后缓存下来并设定一个过期时间
- 过期以后下次访问就重新拉取
- 单次拉取失败取已经过期的缓存值返回
相对来说第二种方法比较好,这种实现比较简单
import (
"sync"
"time"
)
var localCache *Cache = &Cache{}
type Cache struct {
m sync.Map
}
type Entry struct {
Expire time.Time
Value interface{}
}
func (c *Cache) Set(key string, value interface{}, expiration time.Duration) {
entry := &Entry{
Ex