go 语言内存缓存
由 deepseek 总结
| 特性 | ristretto | otter | bigcache | freecache | fastcache | groupcache |
|---|---|---|---|---|---|---|
| 仓库 | hypermodeinc/ristretto | maypok86/otter | allegro/bigcache | coocood/freecache | VictoriaMetrics/fastcache | golang/groupcache |
| Stars | 6.9k | 2.6k | 8.1k | 5.4k | 2.4k | 13.3k |
| 主要特点 | 高性能、高命中率、基于成本的逐出 | 高吞吐、低内存开销、自适应W-TinyLFU | 专为存储大量条目优化,对GC友好 | 零GC开销,支持存储数亿条目 | 极快、线程安全、对GC开销小 | 分布式缓存与填充库,可替代memcached |
| 过期时间 | 支持 | 支持 | 支持 (LifeWindow) | 支持 | 不支持 | 不支持 |
| 驱逐策略 | SampledLFU (采样LFU) | 自适应 W-TinyLFU | 基于生命窗口和清理窗口 | 近似LRU | 当达到最大缓存大小时自动驱逐 | 无显式驱逐,依赖缓存填充机制 |
| GC压力 | 小 | 极小 | 极小 (通过map[uint64]uint32和无指针字节切片) | 零GC开销 (通过预分配内存和分片) | 极小 (通过分片和离堆分配) | 取决于使用方式 |
| 并发模型 | 完全并发 | 高并发下性能优异 | 分片锁,支持高并发 | 256个分片,每个分片有自己的锁 | 多桶(bucket)设计,每个桶有独立锁 | 分布式,节点间通过一致性哈希协调 |
| 内存限制 | 支持 (MaxCost) | 支持 (MaximumSize) | 支持 (HardMaxCacheSize) | 严格限制 (创建时预分配) | 严格限制 (创建时设定) | 取决于节点内存 |
| 持久化 | 不支持 | 支持 (保存/加载到文件) | 不支持 | 计划中 | 支持 (保存/加载到文件) | 不支持 |
| 典型适用场景 | 需要高命中率和成本控制的单机缓存 | 需要高性能、丰富特性(如异步刷新)的缓存 | 存储海量数据且对GC延迟敏感的场景 | 对GC延迟零容忍,需要严格内存控制的场景 | 追求极致速度、不需要过期时间的场景 | 构建分布式缓存系统,防止缓存击穿 |
| API 复杂度 | 简单 | 配置丰富,API灵活 | 简单 | 简单 | 非常简单 | 分布式场景下配置稍复杂 |
| Go版本要求 | 1.21 及以上 | 1.24 及以上 | 1.12 及以上 | - | - | 1.24 及以上 (最新更新) |
总结
-
ristretto: 官方自述为高性能、正确性优先的并发缓存库。通过独特的准入/逐出策略(TinyLFU准入 + SampledLFU逐出)实现了同类最佳的高命中率。支持基于成本的逐出(一个大的新条目可逐出多个小的旧条目)。适用于对缓存命中率和细粒度控制有极高要求的单机服务。
-
otter: 较新的缓存库,旨在提供极佳的开发者体验和高性能。它实现了自适应W-TinyLFU策略,自动根据负载模式调整,在高竞争下吞吐量表现出色,内存开销低。特性非常丰富,支持过期、异步刷新、统计、持久化等。适用于需要高性能且功能全面(如防缓存击穿、数据刷新)的现代Go应用。
-
bigcache: 专为解决Go GC问题而设计。通过使用map[uint64]uint32和存储于字节切片中的条目,极大地减少了堆上的指针数量,从而降低GC压力。初始化时需预估窗口内条目数和最大条目大小以优化内存。适用于需要缓存数百万甚至更多小对象,且对GC停顿时间极度敏感的读多写少场景。
-
freecache: 通过将数据分片到256个段,每个段使用环形缓冲区和索引切片来存储数据,实现了零GC开销。内存完全预分配,访问是线程安全的。适用于需要极致性能、零GC、且能预先分配好大块内存的高并发场景。
-
fastcache: 从VictoriaMetrics中提取的缓存库,设计追求极致的速度和内存效率。同样通过分桶和64KB的块来减少内存碎片和GC开销。最大的限制是不支持过期时间。适用于不需要过期功能、但对速度有极致要求,且希望代码简单并能持久化缓存的场景(如指标缓存)。
-
groupcache: 官方出品的分布式缓存库,设计哲学与单机缓存截然不同。它是一组协同工作的客户端库,没有独立的服务器节点。通过一致性哈希分片和singleflight机制,确保同一个key在集群中只被加载一次,从而防止缓存击穿。不支持过期和显式驱逐。适用于需要构建分布式缓存系统、希望简化部署(无需额外缓存中间件)的Go项目,特别是当缓存数据相对静态时。