golang高性能缓存库支持过期缓存、LFU、LRU和ARC算法插件GCache的使用

Golang高性能缓存库GCache使用指南

GCache是一个支持过期缓存、LFU、LRU和ARC算法的Golang缓存库。

特性

  • 支持过期缓存、LFU、LRU和ARC算法
  • 线程安全
  • 支持淘汰、清除和添加条目的事件处理器(可选)
  • 自动加载不存在的缓存(可选)

安装

$ go get github.com/bluele/gcache

示例代码

1. 手动设置键值对

package main

import (
  "github.com/bluele/gcache"
  "fmt"
)

func main() {
  // 创建容量为20的LRU缓存
  gc := gcache.New(20).
    LRU().
    Build()
  gc.Set("key", "ok")
  value, err := gc.Get("key")
  if err != nil {
    panic(err)
  }
  fmt.Println("Get:", value)
}

输出:

Get: ok

2. 设置带过期时间的键值对

package main

import (
  "github.com/bluele/gcache"
  "fmt"
  "time"
)

func main() {
  gc := gcache.New(20).
    LRU().
    Build()
  // 设置10秒后过期的键值对
  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 {
    panic(err)
  }
  fmt.Println("Get:", value)
}

输出:

Get: ok
// 10秒后, 再次尝试:
panic: ErrKeyNotFound

3. 自动加载值

package main

import (
  "github.com/bluele/gcache"
  "fmt"
)

func main() {
  gc := gcache.New(20).
    LRU().
    // 定义加载函数
    LoaderFunc(func(key interface{}) (interface{}, error) {
      return "ok", nil
    }).
    Build()
  value, err := gc.Get("key")
  if err != nil {
    panic(err)
  }
  fmt.Println("Get:", value)
}

输出:

Get: ok

4. 带过期时间的自动加载

package main

import (
  "fmt"
  "time"

  "github.com/bluele/gcache"
)

func main() {
  var evictCounter, loaderCounter, purgeCounter int
  gc := gcache.New(20).
    LRU().
    // 定义带过期时间的加载函数
    LoaderExpireFunc(func(key interface{}) (interface{}, *time.Duration, error) {
      loaderCounter++
      expire := 1 * time.Second
      return "ok", &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("key")
  if err != nil {
    panic(err)
  }
  fmt.Println("Get:", value)
  time.Sleep(1 * time.Second)
  value, err = gc.Get("key")
  if err != nil {
    panic(err)
  }
  fmt.Println("Get:", value)
  gc.Purge()
  if loaderCounter != evictCounter+purgeCounter {
    panic("bad")
  }
}

输出:

Get: ok
evicted key: key
Get: ok
purged key: key

缓存算法

1. LFU (Least-Frequently Used)

淘汰使用频率最低的条目。

func main() {
  // 容量为10的LFU缓存
  gc := gcache.New(10).
    LFU().
    Build()
  gc.Set("key", "value")
}

2. LRU (Least Recently Used)

淘汰最近最少使用的条目。

func main() {
  // 容量为10的LRU缓存
  gc := gcache.New(10).
    LRU().
    Build()
  gc.Set("key", "value")
}

3. ARC (Adaptive Replacement Cache)

在LRU和LFU之间动态平衡以获得更好的综合效果。

func main() {
  // 容量为10的ARC缓存
  gc := gcache.New(10).
    ARC().
    Build()
  gc.Set("key", "value")
}

4. SimpleCache (默认)

没有明确的淘汰优先级,依赖于键值映射的顺序。

func main() {
  // 容量为10的简单缓存
  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")
  // 输出: "value"
  fmt.Println(v)
}

过期缓存

func main() {
  // LRU缓存,容量10,1小时后过期
  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)
  }
}

输出:

evicted key: 0

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)
  }
}

输出:

added key: 0
added key: 1
added key: 2

作者

Jun Kimura


更多关于golang高性能缓存库支持过期缓存、LFU、LRU和ARC算法插件GCache的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能缓存库支持过期缓存、LFU、LRU和ARC算法插件GCache的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


GCache - Golang高性能缓存库

GCache是一个功能强大的Golang缓存库,支持多种缓存算法和过期策略。下面我将详细介绍它的主要特性及使用方法。

主要特性

  1. 支持多种缓存淘汰算法:

    • LRU (Least Recently Used)
    • LFU (Least Frequently Used)
    • ARC (Adaptive Replacement Cache)
    • Simple (无淘汰策略)
  2. 支持缓存过期策略:

    • 固定过期时间
    • 滑动过期时间
    • 永不过期

安装

go get -u github.com/bluele/gcache

基本使用示例

1. 创建缓存实例

package main

import (
	"fmt"
	"time"
	"github.com/bluele/gcache"
)

func main() {
	// 创建一个LRU缓存,容量为100
	cache := gcache.New(100).
		LRU().
		Build()
	
	// 设置缓存值
	cache.Set("key1", "value1")
	
	// 获取缓存值
	value, err := cache.Get("key1")
	if err != nil {
		panic(err)
	}
	fmt.Println("Get:", value)
}

2. 不同缓存算法示例

// 创建LFU缓存
lfuCache := gcache.New(100).
	LFU().
	Build()

// 创建ARC缓存
arcCache := gcache.New(100).
	ARC().
	Build()

3. 过期时间设置

// 创建带过期时间的缓存
expireCache := gcache.New(100).
	LRU().
	Expiration(time.Second * 10). // 10秒后过期
	Build()

// 设置带过期时间的单个条目
expireCache.SetWithExpire("key2", "value2", time.Second*5)

4. 高级功能

// 创建带加载函数的缓存
loaderCache := gcache.New(100).
	LRU().
	LoaderFunc(func(key interface{}) (interface{}, error) {
		// 当缓存未命中时自动调用此函数加载数据
		return "loaded-value", nil
	}).
	Build()

// 自动加载
value, err := loaderCache.Get("key-not-exist")
fmt.Println(value) // 输出: loaded-value

// 添加过期回调
callbackCache := gcache.New(100).
	LRU().
	AddedFunc(func(key, value interface{}) {
		fmt.Printf("Added key: %v, value: %v\n", key, value)
	}).
	EvictedFunc(func(key, value interface{}) {
		fmt.Printf("Evicted key: %v, value: %v\n", key, value)
	}).
	Build()

5. 性能优化技巧

// 使用指针类型减少拷贝
type BigStruct struct {
	Data [1024]byte
}

cache := gcache.New(100).
	LRU().
	Build()

bigData := &BigStruct{}
cache.Set("big-key", bigData) // 存储指针而非结构体本身

// 批量操作减少锁竞争
cache.SetAll(map[interface{}]interface{}{
	"key1": "value1",
	"key2": "value2",
	"key3": "value3",
})

算法选择建议

  1. LRU:适用于大多数场景,对最近访问的数据有较好的保留
  2. LFU:适用于访问频率差异大的场景
  3. ARC:结合了LRU和LFU的优点,自适应调整,但内存开销稍大
  4. Simple:当不需要淘汰策略时使用

注意事项

  1. GCache不是线程安全的,如果需要在多个goroutine中使用,需要自行加锁
  2. 对于大型对象,建议存储指针而非值类型
  3. 过期检查是惰性的,只有在访问时才会检查是否过期

性能对比

GCache在性能上表现优异,与其他流行缓存库相比:

  • bigcachefreecache功能更丰富
  • groupcache更灵活
  • 比简单的map+mutex实现更高效

通过合理选择算法和配置,GCache可以满足大多数高性能缓存需求。

回到顶部