极客兔兔Gee-Cache Day1

极客兔兔7Days

GeeCache

- Day1
  • interface{}:任意类型

  • 缓存击穿:一个高并发的请求查询一个缓存中不存在的数据项,因此这个请求穿透缓存直接到达后端数据库或数据源来获取数据。如果这种请求非常频繁,就会导致后端系统的负载突然增加,可能会使数据库或数据源响应变慢甚至宕机,从而影响整个系统的性能和稳定性。

    • 解决1:设置热点数据永不过期
    • 解决2:使用锁机制确保只有一个请求去访问数据库,其他的请求等待这个请求的结果
    • 解决3:设置时间更长的二级缓存
  • 缓存淘汰策略

    • FIFO:先进先出,也就是淘汰缓存中最老(最早添加)的记录
    • LFU:最少使用,也就是淘汰缓存中访问频率最低的记录
    • LRU:最近最少使用,相对于仅考虑时间因素的 FIFO 和仅考虑访问频率的 LFU,LRU 算法可以认为是相对平衡的一种淘汰算法。
  • list常用方法New()PushFront(v interface{}) *ElementPushBack(v interface{}) *ElementRemove(e *Element) interface{}Front() *ElementBack() *ElementNext() *ElementPrev() *Element

  • 使用list和map实现,cache中记录缓存最大容量和当前数据大小,对于刚访问的元素,将其移到list的最头部,表示最近刚使用过,删除时选择最尾部的数据进行删除,entry实际是list的节点数据类型,在删除对应节点后,同时删除map中的数据,实现查找、删除、增加、修改功能

  • 代码

    • package gee
      
      import "container/list"
      
      type Cache struct {
      	maxBytes int64
      	nbytes   int64
      	ll       *list.List
      	cache    map[string]*list.Element
      }
      
      type entry struct {
      	key   string
      	value Value
      }
      
      type Value interface {
      	Len() int
      }
      
      func New(maxBytes int64) *Cache {
      	return &Cache{
      		maxBytes: maxBytes,
      		ll:       list.New(),
      		nbytes:   0,
      		cache:    make(map[string]*list.Element),
      	}
      }
      
      // 查找
      func (c *Cache) Get(key string) (value Value, ok bool) {
      	if ele, ok := c.cache[key]; ok {
      		// 假设头部是队尾
      		c.ll.MoveToFront(ele)
      		kv := ele.Value.(*entry)
      		return kv.value, true
      	}
      	return nil, false
      }
      
      // 删除
      func (c *Cache) Delete() {
      	ele := c.ll.Back()
      	if ele != nil {
      		c.ll.Remove(ele)
      		// 类型断言
      		kv := ele.Value.(*entry)
      		delete(c.cache, kv.key)
      		c.nbytes -= int64(len(kv.key)) + int64(kv.value.Len())
      	}
      }
      
      // 添加
      func (c *Cache) Add(key string, value Value) {
      	if ele, ok := c.cache[key]; ok {
      		c.ll.MoveToFront(ele)
      		kv := ele.Value.(*entry)
      		c.nbytes += int64(value.Len()) - int64(kv.value.Len())
      		kv.value = value
      	} else {
      		ele := c.ll.PushFront(&entry{key, value})
      		c.nbytes += int64(len(key)) + int64(value.Len())
      		c.cache[key] = ele
      	}
      	for c.maxBytes != 0 && c.maxBytes < c.nbytes {
      		c.Delete()
      	}
      }
      
      func (c *Cache) Len() int {
      	return c.ll.Len()
      }
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值