Go 言語は LRU 除去アルゴリズムを実装します

ここに画像の説明を挿入

1. LRU除去アルゴリズム

LRU(最近使用されていないもの)

LRULeast Recently Usedこれは、仮想ページのストレージ管理に使用され、ページがメモリにロードされた後の使用状況に基づいて決定を行う、最も最近使用されていないページ置換アルゴリズムの略語です各ページの将来の使用状況は予測できないため、「最近の過去」は「近い将来」の近似としてしか使用できません。そのため、LRU アルゴリズムでは、最も長期間使用されていないページを削除します。

1.1 定義

  • 構造を定義する
type Cache struct {
    
    
	maxBytes int64   	  //允许使用的最大内存
	Nbytes   int64		  //当前已使用的内存
	ll       *list.List   //双向列表
	cache    map[string]*list.Element  
	//键是字符串,值是双向链表中对应节点的指针
	OnEvicted func(key string, value Value)
	//是某条记录被`移除`时的回调函数,可以为 nil。
}

// Value use Len to count how many bytes it takes
/*
使用Len来计算需要多少个字节
允许值是实现了 Value 接口的任意类型

该接口只包含了一个方法 Len() int,用于返回值所占用的内存大小。
*/
type Value interface {
    
    
	Len() int
}

1.2 インスタンス化

  • この Cache オブジェクトをインスタンス化して、New にします。
// 对于Cache进行了实例化,能New一个Cache出来。
func New(maxBytes int64, onEvicted func(string, Value)) *Cache {
    
    
	return &Cache{
    
    
		maxBytes:  maxBytes,  
		ll:        list.New(),
		cache:     make(map[string]*list.Element),
		OnEvicted: onEvicted,
	}
}

1.3 追加または更新

  • キャッシュを増やすか更新する
func (c *Cache) Add(key string, value Value) {
    
    
	if ele, ok := c.cache[key]; ok {
    
    
		c.ll.MoveToFront(ele)  		//这个键存在,移动到队尾
		kv := ele.Value.(*entry)	
		//kv 是值, 因为value是接口, 
		//因此类型断言设置为*entry
		c.Nbytes += int64(value.Len()) - int64(kv.value.Len()) 
		// 计算现在的缓存,以至于将其中的
		kv.value = value
	} else {
    
    
		ele := c.ll.PushFront(&entry{
    
    key, value}) //没有的话,就创建这一个键值对
		c.cache[key] = ele
		c.Nbytes += int64(len(key)) + int64(value.Len())
	}

	for c.maxBytes != 0 && c.maxBytes < c.Nbytes {
    
    	
		// 如果超出缓存容量
		c.RemoveOldest()							
		// 那么移除双向链表中的最后一项
	}
}

1.4 クエリ

  • キャッシュ内の値を取得する
// Get look ups a key's value
func (c *Cache) Get(key string) (value Value, ok bool) {
    
    
	if ele, ok := c.cache[key]; ok {
    
     
		// 如果这个需要查找的值是存在的,则将对应的节点移动到队尾,并返回查找到的值
		c.ll.MoveToFront(ele)
		// 双向链表作为队列,队首队尾是相对的,在这里约定 front 为队尾
		kv := ele.Value.(*entry)
		return kv.value, true
	}
	return
}

1.5 削除

  • キャッシュの削除 (廃止)
// RemoveOldest removes the oldest item
//这里的删除,实际上是缓存淘汰。即移除最近最少访问的节点(队首)
func (c *Cache) RemoveOldest() {
    
    
	ele := c.ll.Back()    //取到队首节点
	if ele != nil {
    
    
		c.ll.Remove(ele)  //从链表中删除
		kv := ele.Value.(*entry)  //获取值
		delete(c.cache, kv.key)  //从字典 c.cache 中删除该节点的映射关系。
		c.Nbytes -= int64(len(kv.key)) + int64(kv.value.Len()) //计算这里大小
		if c.OnEvicted != nil {
    
    
			c.OnEvicted(kv.key, kv.value)
		}
	}
}

このメソッドは同時実行をサポートできないため、複数のスレッドが競合すると書き込みが発生します。顺序与读取顺序的混乱
これは競合するリソースです。ロックを追加して、このキャッシュ メカニズムを最適化できます。

おすすめ

転載: blog.csdn.net/weixin_45304503/article/details/129639596