LFU算法实现

打印 上一主题 下一主题

主题 867|帖子 867|积分 2601

LFU (Least Frequently Used) 是一种用于缓存管理的算法。它通过跟踪每个缓存项被访问的频率来决定哪些项应该被移除。LFU算法倾向于保留那些利用频率较高的项,而移除那些利用频率较低的项。以下是LFU算法的具体先容:
工作原理


  • 计数器:每个缓存项都有一个计数器,用于记载该项被访问的次数。
  • 增加计数:每次缓存项被访问时,其计数器加一。
  • 移除策略:当缓存满时,移除计数器值最小的项。如果有多个项的计数器值类似,则根据预定规则(如最早被访问的项)移除其中一个。
实现

LFU算法的实现可以利用多种数据布局,如哈希表、双向链表和优先队列。以下是一种常见的实现方法:
利用哈希表和优先队列

  • 哈希表 (cache):用于存储缓存项及其计数器。
  • 优先队列 (min-heap):用于快速找到计数器值最小的项。
具体步骤如下:

  • 插入/更新缓存项

    • 如果缓存项已存在,更新其计数器并调整优先队列中的位置。
    • 如果缓存项不存在,检查缓存是否已满。如果已满,移除优先队列中计数器值最小的项,然后插入新项。

  • 访问缓存项

    • 如果缓存项存在,更新其计数器并调整优先队列中的位置。
    • 如果缓存项不存在,返回未命中。

应用场景

LFU算法实用于以下场景:

  • 数据访问具有显着的热点数据,且热点数据相对稳固。
  • 需要高效管理缓存资源,减少缓存未命中率。
Go实现
  1. package lfu
  2. import (
  3.         "container/list"
  4.         "sync"
  5. )
  6. type entry struct {
  7.         key   any
  8.         value any
  9.         freq  int
  10. }
  11. type LFUCache struct {
  12.         mtx       sync.Mutex // protects the cache
  13.         capacity  int
  14.         size      int
  15.         minFreq   int
  16.         cache     map[any]*list.Element
  17.         frequency map[int]*list.List
  18. }
  19. // NewLFUCache creates a new LFU cache
  20. func NewLFUCache(capacity int) *LFUCache {
  21.         return &LFUCache{
  22.                 capacity:  capacity,
  23.                 cache:     make(map[any]*list.Element),
  24.                 frequency: make(map[int]*list.List),
  25.         }
  26. }
  27. // Get retrieves a value from the cache
  28. func (c *LFUCache) Get(key any) any {
  29.         c.mtx.Lock()
  30.         defer c.mtx.Unlock()
  31.         if elem, found := c.cache[key]; found {
  32.                 c.incrementFrequency(elem)
  33.                 return elem.Value.(*entry).value
  34.         }
  35.         return nil
  36. }
  37. // Put inserts or updates a value in the cache
  38. func (c *LFUCache) Put(key, value any) {
  39.         c.mtx.Lock()
  40.         defer c.mtx.Unlock()
  41.         if c.capacity == 0 {
  42.                 return
  43.         }
  44.         if elem, found := c.cache[key]; found {
  45.                 elem.Value.(*entry).value = value
  46.                 c.incrementFrequency(elem)
  47.         } else {
  48.                 if c.size == c.capacity {
  49.                         c.evict()
  50.                 }
  51.                 newEntry := &entry{key, value, 1}
  52.                 if c.frequency[1] == nil {
  53.                         c.frequency[1] = list.New()
  54.                 }
  55.                 elem := c.frequency[1].PushFront(newEntry)
  56.                 c.cache[key] = elem
  57.                 c.minFreq = 1
  58.                 c.size++
  59.         }
  60. }
  61. // incrementFrequency increases the frequency of a cache entry
  62. func (c *LFUCache) incrementFrequency(elem *list.Element) {
  63.         e := elem.Value.(*entry)
  64.         oldFreq := e.freq
  65.         e.freq++
  66.         c.frequency[oldFreq].Remove(elem)
  67.         if c.frequency[oldFreq].Len() == 0 {
  68.                 delete(c.frequency, oldFreq)
  69.                 if c.minFreq == oldFreq {
  70.                         c.minFreq++
  71.                 }
  72.         }
  73.         if c.frequency[e.freq] == nil {
  74.                 c.frequency[e.freq] = list.New()
  75.         }
  76.         newElem := c.frequency[e.freq].PushFront(e)
  77.     c.cache[e.key] = newElem
  78. }
  79. // evict removes the least frequently used cache entry
  80. func (c *LFUCache) evict() {
  81.         list := c.frequency[c.minFreq]
  82.         elem := list.Back()
  83.         if elem != nil {
  84.                 list.Remove(elem)
  85.                 delete(c.cache, elem.Value.(*entry).key)
  86.                 c.size--
  87.         }
  88. }
复制代码
声明:本作品采用署名-非商业性利用-类似方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行答应,利用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开辟者社区:孟斯特

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

兜兜零元

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表