缓存的使用(1)

一 LRU本地缓存

参与开发的系统对外部部分API请求需要进行一个鉴权,而鉴权过程中需要利用公钥拿到用户的账户信息,从而利用账户信息中的私钥对请求签名进行一个验证。

为了避免大量请求对account服务(用户账户信息服务)进行轮询,系统对账户信息利用LRU进行了缓存,这样可以做到:1 控制缓存数量 , 2 提高命中率。对LRU的更新,会获取所有的键,然后新建LRU,替换原有的LRU。考虑到account服务长时间不可用的情况,需要LRU有降级策略,只有当用于更新的LRU创建成功(即利用所有key访问account服务成功率大于设定值)才会进行替换更新。

LRU 的实现:

type Cache struct {
	MaxEntries int  // 最大缓存数目
	// 当key被从缓存中清除时所执行的回调函数
	OnEvicted func(key CacheKey,  value interface{})  
	ll list.List
	cache Map[interface{}]*list.Element
}
tyep CacheKey interface{}
type entry struct{
	key CacheKey
	value interface{}
}

重要方法实现:
Add:

func (c  *Cache)  Add(key CacheKey, value interface{}) {
	if c.cache == nil {
		c.cache = make(map[interface{}]*list.Element)
		c.ll = list.New()
	}
	if ee, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ee)
		ee.Value.(*entry).value = value
		return 
	}
	ele := c.ll.PushFront(&entry{key,value})
	c.cache[key] = ele
	if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
		c.MoveOldest()
	}
}

Get :

func ( c *Cache) Get(key CacheKey) (value interface{}, ok bool) {
	if c.cache == nil {
		return 
	}
	if ele, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ele)
		return ele.value.(*entry).value, true
	}
	return 
}

RemoveOldest:

func (c *Cache)  removeOldest() {
	if c.cache == nil {
		return
	}
	ele := c.ll.Back()
	if ele != nil {
		c.RemoveElement(ele)
	}
}

func (c *Cache) removeElement(ee *list.Element) {
	c.ll.Remove(ee )
	kv := e.Value.(*entry)
	delete(c.cache, kv.key)
	if c.OnEvicted != nil {
		c.OnEvicted(kv.key, kv.value)
	}
}

利用LRU构建账户缓存

type DoubleBufferKeyInfo {
	lru *Cache
	cli *account.Client // 账户服务的代理
	sync.RWMutex
}

func (dbk *DoubleBufferKeyInfo) Get(ak String) *KeyInfo {
	dbk.Lock()
	v, ok := dbk.lru.Get(ak)
	dbk.UnLock()

	if ok {
		return v.(KeyInfo)
	}
	ctx := context.Background()
	account, err := dbk.cli.GetAccount(ctx, ak)
	if err != nil {
	......
	}
   extra := make(map[string]interface{})
   if err := json.Unmarshal([]byte(account.Extra, &extra); err != nil {
   ......
   }
   keyInfo := &KeyInfo{
   	SecretKey : account.SecretKey
   	Extra : extra
   }
   dbk.Lock()
   dbk.lru.Add(ak, keyInfo)
   dbk.UnLock()
   return keyInfo
}

构建鉴权认证中心:

type AuthCenter struct {
	keyInfors *DoubleBufferKeyInfo
	verifyFuns map[string]VerifyFunc
}

对缓存进行更新

func InitAuthCenter(config *util.AuthCenterConfig) ( *AuthCenter, error) {
	center.KeyInfos = NewKeyInfoCache(....)
	
	// 对缓存进行更新
	go func() {
		// 为了避免我们系统所有服务(系统会有多个实例,部署在不同的数据中心)会在同一时间对账户系统
		// 服务进行访问
		rand.Seed(int64(time.Now(	).NanoSecond()))
		interval := time.Duration(rand.IntN(60)*time.Second + config.TimeInterval)
		ticker := time.Ticker(interval)
		for range ticker {
			keys := center.keyInfors.GetAllKeys()
			if next_lru , ok := updateKeyInfo(keys, config); err != nil {
				......
			} else {
				center.keyInfos.Update(next_lru)
			}
		}		   
	}
}

func updateKeyInfo(key []CacheKey, conf *util.AuthCenterConfig) (*Cache, error) {
	// 对所有key通过账户服务获取账户信息,统计访问成功率,当成功率大于设定值,生成新的LRU
	.......
}
二 cache

类似redis的远程缓存
cache 更新策略参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值