当前位置: 首页 > 工具软件 > GCache > 使用案例 >

Go --- GCache缓存官方例子

家浩瀚
2023-12-01


Github:https://github.com/bluele/gcache

介绍

为 Golang 打造的缓存库。 它支持可预期的 Cache,LFU,LRU 和 ARC。

功能

  • 支持可预见的 Cache,LFU,LRU 和 ARC。
  • Goroutine 安全
  • 支持驱逐,清除和添加条目的事件处理程序。 (可选)
  • 如果缓存不存在,则自动加载缓存。 (可选)

安装

$ go get github.com/bluele/gcache

例子

  1. 手工配置键值对

    package main
    
    import (
       "fmt"
       "github.com/bluele/gcache"
    )
    
    func main() {
         // size为设置的每小时的字节数,单位是 MB
    	// func New(size int) *CacheBuilder {
    	// 	return &CacheBuilder{
    	// 		clock: NewRealClock(),
    	// 		tp:    TYPE_SIMPLE,
    	// 		size:  size,
    	// 	}
    	// }
       gc := gcache.New(20).
          LRU().
          Build()
       gc.Set("key", "你好")
       value, err := gc.Get("key")
       if err != nil {
          panic(err)
       }
       fmt.Println("Get:", value)
    }
    
  2. 手动设置具有过期时间的键值对。

    package main
    
    import (
       "fmt"
       "github.com/bluele/gcache"
       "log"
       "time"
    )
    
    func main() {
       gc := gcache.New(20).
          LRU().
          Build()
       // 设置并带上过期时间
       gc.SetWithExpire("key", "ok", time.Second*10)
       value, _ := gc.Get("key")
       fmt.Println("Get:", value)
    
       // 等待值过期
       time.Sleep(time.Second*10)
    
       value, err := gc.Get("key")
       if err != nil {
          // Key not found.
          log.Println(err)
       }
       fmt.Println("Get:", value)
    }
    
  3. 自动负载值

    package main
    
    import (
       "fmt"
       "github.com/bluele/gcache"
       "time"
    )
    
    func main() {
       gc := gcache.New(20).
          LRU().
          // loaderFunc:当缓存值过期时,使用此函数创建一个新值。
          LoaderFunc(func(key interface{}) (interface{}, error) {
             return "默认值", nil
          }).
          Build()
       value1, err := gc.Get("张三")
       if err != nil {
          panic(err)
       }
       value2, err := gc.Get("李四")
       if err != nil {
          panic(err)
       }
       fmt.Println("张三:", value1)
       fmt.Println("李四:", value2)
       _ = gc.SetWithExpire("王五", "虽然可以修改", 5*time.Second)
       value3, err := gc.Get("王五")
       if err != nil {
          panic(err)
       }
       fmt.Print("王五:", value3)
    
       time.Sleep(5*time.Second)
    
       value4, err := gc.Get("王五")
       if err != nil {
          panic(err)
       }
       fmt.Println(" 但是过期了重新赋为", value4)
    }
    
  4. 自动加载值与到期时间

    package main
    
    import (
       "fmt"
       "time"
    
       "github.com/bluele/gcache"
    )
    
    func main() {
       var evictCounter, loaderCounter, purgeCounter int
       gc := gcache.New(20).
          LRU().
          // loaderExpireFunc:当缓存值过期时,使用此函数创建一个新值。
          // 如果*time.Duration返回nil而不是时间。loaderExpireFunc比value的持续时间永远不会过期。
          LoaderExpireFunc(func(key interface{}) (interface{}, *time.Duration, error) {
             loaderCounter++
             expire := 1 * time.Second
             // return interface{}, *time.Duration, error
             return "好好吃饭", &expire, nil
          }).
          // 如果有新的键和老的键冲突了,那么将会驱逐老的键
          EvictedFunc(func(key, value interface{}) {
             evictCounter++
             fmt.Println("evicted key:", key)
          }).
          PurgeVisitorFunc(func(key, value interface{}) {
             purgeCounter++
          fmt.Println("purged key:", key)
          }).
          Build()
       value, err := gc.Get("规律作息")
       if err != nil {
          panic(err)
       }
       fmt.Println("规律作息:", value)
    
       time.Sleep(1 * time.Second)
    
       value, err = gc.Get("规律作息")
       if err != nil {
          panic(err)
       }
       fmt.Println("规律作息:", value)
       // 手动配置键值对
       _ = gc.Set("麦", "当")
       value, err = gc.Get("麦")
       if err != nil {
          panic(err)
       }
       fmt.Println("麦:", value)
       // 清理缓存
       gc.Purge()
       // 因为我们手动配置了键值对,所以将会执行下方的panic
       if loaderCounter != evictCounter+purgeCounter {
          fmt.Println("负载计数器:",loaderCounter)
          fmt.Println("驱逐计数器:",evictCounter)
          fmt.Println("清除计数器:",purgeCounter)
          panic("bad")
       }
    }
    

缓存算法说明

  1. Least-Frequently Used (LFU)

    使用次数最少,首先丢弃最不常用的缓存。

    func main() {
      // size: 10
      gc := gcache.New(10).
        LFU().
        Build()
      gc.Set("key", "value")
    }
    
  2. Least Recently Used (LRU)

    最近最少使用,最先丢弃最近最少使用的物品。

    func main() {
      // size: 10
      gc := gcache.New(10).
        LRU().
        Build()
      gc.Set("key", "value")
    }
    
  3. daptive Replacement Cache (ARC)

    自适应替换缓存,不断平衡LRU和LFU,提高组合效果。

    详细情况参考: http://en.wikipedia.org/wiki/Adaptive_replacement_cache

    func main() {
      gc := gcache.New(10).
        ARC().
        Build()
      gc.Set("key", "value")
    }
    
  4. SimpleCache (Default)

    SimpleCache没有明确的退出缓存优先级。它取决于键-值映射顺序。

    func main() {
      gc := gcache.New(10).Build()
      gc.Set("key", "value")
      v, err := gc.Get("key")
      if err != nil {
        panic(err)
      }
    }
    

加载缓存

如果指定了LoaderFunc,值将由缓存自动加载,并存储在缓存中,直到驱逐或手动失效。

func main() {
  gc := gcache.New(10).
    LRU().
    LoaderFunc(func(key interface{}) (interface{}, error) {
      return "value", nil
    }).
    Build()
  v, _ := gc.Get("key")
  fmt.Println(v)
}

GCache协调缓存填充,使整个复制的进程集中的一个进程中只有一个加载填充缓存,然后将加载的值复用给所有调用者。

为缓存设置过期时间

func main() {
  // LRU 缓存, 大小:10MB, 过期时间: 一小时后
  gc := gcache.New(10).
    LRU().
    Expiration(time.Hour).
    Build()
}

事件处理程序

  1. 被驱逐的处理程序

    事件处理程序,用于驱逐条目。驱逐条目时执行该函数。

    func main() {
      gc := gcache.New(2).
        EvictedFunc(func(key, value interface{}) {
          fmt.Println("evicted key:", key)
        }).
        Build()
      for i := 0; i < 3; i++ {
        gc.Set(i, i*i)
      }
    }
    
  2. 添加处理程序

    事件处理程序,用于添加条目。添加条目时执行该函数。

    func main() {
      gc := gcache.New(2).
        AddedFunc(func(key, value interface{}) {
          fmt.Println("added key:", key)
        }).
        Build()
      for i := 0; i < 3; i++ {
        gc.Set(i, i*i)
      }
    }
    
 类似资料: