这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天。
本文以 CC-BY-SA 4.0 发布。
Ristretto 介绍
Ristretto 是意式浓缩咖啡的一种, 也是 Dgraph 团队 推出的 Go 语言高性能缓存库的名字。
后者的 ristretto 的 GitHub 页面 上 列举了一些优势:
- 高的命中率:
- 它在放入内存时就会对缓存内容进行评估,会对内存大小进行估计,并判断内容值不值得缓存。
- 内容的准入和清除使用了 TinyLFU 和 SampledLFU 算法,性能相对更好。
- 吞吐量更大。
- 基于开销的清除:每项内容有大小之分,可以由用户指定以实现更合适的清除方法。
- 完全并发:多 goroutine 的情况下性能也不会有太大衰减。
- 提供内置的统计。
- API 简单。
其团队的介绍文章中有对其实现的更多介绍: Introducing Ristretto: A High-Performance Go Cache
总的来说,现在涉及到并发修改等处理时,Go 语言用户更加倾向与使用各种的锁,
而忽略了一些可能会在大并发时更加方便、能减少携程切换的处理方式。
文章中提到了 Go 语言里的 sync.Map 在大量写的时候的性能实在不行。
(相比起来,Java 线程阻塞开销大,语言内置了 ConcurrentHashMap。)
而 ristretto 则是受了一些 Java 里有名的 Caffeine 缓存库的启发,
针对这些携程级别的阻塞做了优化,换了例如 TinyLFU 等算法,
甚至在统计时还进行了一些 CPU cacheline 级别的优化,取得了相当不错的性能。
API 使用例子
API 的确非常简单,基本上就是 Get, Set, Del,凭直觉就可以知怎么使用。
另外,在 ristretto.Config 里有几个回调函数:
OnEvict: 在内容被逐出缓存时被调用OnReject: 在内容被Set,但是未能被允许进入缓存时被调用OnExit: 上面两个函数任意被调用时会被调用
其实这几个回调函数非常适合用来回写数据到数据库。 甚至结合一些原子操作的话,我们可以实现一些更加复杂的对数据库的同步操作。