Ristretto 介绍 | 青训营笔记

608 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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: 上面两个函数任意被调用时会被调用

其实这几个回调函数非常适合用来回写数据到数据库。 甚至结合一些原子操作的话,我们可以实现一些更加复杂的对数据库的同步操作。