Ristretto 简介: 一个高性能GO缓存
原文作者:Dmitry Filimonov
本文永久链接:Ristretto 简介: 一个高性能GO缓存
译者:784909593
校对:b8kings0ga
这个博客登上了 Golang subreddit 的顶部,并且在 Hacker News 的trending上排在前十位。 一定要在那里参与讨论,并通过给我们一个 star,表达对我们的喜欢。
经过六个月的研发,我们自豪的宣布缓存 Ristretto:一个高性能、并发、可设置内存上限的 Go 缓存的初始版本。他是抗争用、扩展性好、提供稳定的高命中率。
前言
这一切都始于 Dgraph 中需要一个可设置内存上限的、并发的 Go 缓存。我们四处寻找解决方案,但是没有找到一个合适的。然后我们尝试使用分片 map,通过分片驱逐来释放内存,这导致了我们的内存问题。然后我们重新利用了 Groupcache 的 LRU, 用互斥锁保证线程安全。使用了一年之后,我们注意到缓存存在严重的争用问题。一个 commit 删除了该缓存,使我们的查询延迟显著改善了 5-10 倍。本质上,我们的缓存正在减慢我们的速度!
我们得出的结论是,Go 中的并发缓存库已经坏了,必须修复。 在三月, 我们写了一篇关于 Go 中的缓存状态, 提到数据库和系统需要一个智能的、可设置内存上限的缓存的问题,它可以扩展到 Go 程序所处的多线程环境。特别的,我们将这些设置为缓存的要求:
并发的;
缓存命中率高;
Memory-bounded (限制为可配置的最大内存使用量);
随着核数和协程数量的增加而扩展;
在非随机key访问(例如 Zipf)分布下很好的扩展;
发布了博客文章之后,我们组建了一个团队来解决其中提到的挑战,并创建了一个值得与非 Go 语言缓存实现进行比较的 Go 缓存库。特别的,Caffeine 这是一个基于 Java 8 的高性能、近乎最优的缓存库。许多基于 Java 8 的数据库都在使用它, 比如 Cassandra,HBase,和 Neo4j。这里有一篇关于 Caffeine 设计的文章。
Ristretto: Better Half of Espresso
从那以后我们阅读了文献, 广泛的测试了实现 ,并讨论了在写一个缓存库时需要考虑的每一个变量。 今天,我们自豪的宣布他已经准备好供更广泛的 Go 社区使用和实验。
在我们开始讲解 Ristretto 的设计之前, 这有一个代码片段展示了如何使用它:
func main() {
cache, err := ristretto.NewCache(&ristretto.Config{
NumCounters: 1e7, // key 跟踪频率为(10M)
MaxCost: 1 << 30, // 缓存的最大成本 (1GB)。
BufferItems: 64, // 每个 Get buffer的 key 数。