高性能内存缓存
Otter 是基于缓存和并发数据结构研究的 Go 语言最强大的缓存库之一。Otter 还借鉴了其他语言缓存库(如 caffeine)的设计经验。
📖 目录
✨ 特性
- 简单的 API:只需在构建器中设置所需参数即可使用
- 自动配置:Otter 根据应用程序的并行度自动配置
- 泛型:可以安全地使用任何可比较类型作为键,任何类型作为值
- TTL:过期的值将自动从缓存中删除
- 基于成本的淘汰:Otter 支持基于每个条目成本的淘汰
- 删除监听器:可以在构建器中传递回调函数,当条目从缓存中删除时将调用该函数
- 统计信息:可以收集各种使用统计数据
- 出色的吞吐量:Otter 可以处理大量请求
- 高命中率:使用新的 S3-FIFO 算法,显示出优秀的结果
🗃 相关工作
Otter 基于以下论文:
📚 使用方法
📋 要求
- Go 1.19+
🛠️ 安装
go get -u github.com/maypok86/otter
✏️ 示例
Otter 使用构建器模式,允许您方便地创建具有不同参数的缓存实例。
具有固定 TTL 的缓存
package main
import (
"fmt"
"time"
"github.com/maypok86/otter"
)
func main() {
// 创建容量为 10000 个元素的缓存
cache, err := otter.MustBuilder[string, string](10_000).
CollectStats().
Cost(func(key string, value string) uint32 {
return 1
}).
WithTTL(time.Hour).
Build()
if err != nil {
panic(err)
}
// 设置带有 TTL(1 小时)的项目
cache.Set("key", "value")
// 从缓存中获取值
value, ok := cache.Get("key")
if !ok {
panic("未找到键")
}
fmt.Println(value)
// 从缓存中删除项目
cache.Delete("key")
// 删除数据并停止 goroutine
cache.Close()
}
具有可变 TTL 的缓存
package main
import (
"fmt"
"time"
"github.com/maypok86/otter"
)
func main() {
// 创建容量为 10000 个元素的缓存
cache, err := otter.MustBuilder[string, string](10_000).
CollectStats().
Cost(func(key string, value string) uint32 {
return 1
}).
WithVariableTTL().
Build()
if err != nil {
panic(err)
}
// 设置带有 TTL(1 小时)的项目
cache.Set("key1", "value1", time.Hour)
// 设置带有 TTL(1 分钟)的项目
cache.Set("key2", "value2", time.Minute)
// 从缓存中获取值
value, ok := cache.Get("key1")
if !ok {
panic("未找到键")
}
fmt.Println(value)
// 从缓存中删除项目
cache.Delete("key1")
// 删除数据并停止 goroutine
cache.Close()
}
📊 性能
🚀 吞吐量
吞吐量基准测试是 caffeine 基准测试的 Go 语言移植版。这个微基准测试在 zipf 分布上比较了缓存的吞吐量,这允许展示各种实现中的低效之处。
您可以在这里找到结果。
🎯 命中率
命中率模拟器在各种跟踪上测试缓存:
- 合成(zipf 分布)
- 传统(广泛知名且在各种项目和论文中使用)
- 现代(最近从世界上最大公司的生产环境中收集)
💾 内存消耗
内存开销基准测试显示了在不同容量下缓存将需要多少额外内存。
👏 贡献
欢迎贡献,在提交新的 PR 之前,请确保先开启一个新的 issue,以便社区成员可以讨论。 有关更多信息,请参阅贡献指南。
此外,您可能会发现现有的开放 issue,这些 issue 可以帮助改进项目。
本项目遵循标准的行为准则,以便您了解哪些行为会被接受和不被接受。