Caffeine 与 Guava Cache 性能对比深度评测

背景

缓存是服务端开发中最常用的用于提升性能的常规手段。在Java领域,使用得比较多的有Guava Cache 和Caffeine。Guava Cache 是google开发的经典的缓存库,尤其是guava库几乎所有Java开发者都会用到它。Caffeine, 它Java 8 重写,参考了 Guava 的 API,使用方式和Guava Cache基本类似。但由于它引入了全新的驱逐算法(W-TinyLFU),号称性能更强。时常在网上看到有人对Caffeine性能赞不绝口。本文就基于这2个缓存做做一个性能测试,看看他们的性能有大差距。

Caffeine 与 Guava Cache 特性比较

二者比较

特性 Guava Cache (LRU) Caffeine (W-TinyLFU)
核心逻辑 谁最近来了,谁留下来 谁平时来得最勤,谁留下来
内存开销 正常对象开销 极低。利用 Count-Min Sketch 压缩频率统计
适用场景 一般场景够用 高并发、数据具有明显热点特征

Caffeine中缓存管理的方式

Caffeine中,对缓存的管理使用了分区机制。主要分为windows区和main区(有点类似Java 垃圾回收中的年轻代与老年代)。

它的这种设计是为了同时解决“稀疏流量(突发访问)”和“热点数据(高频访问)”的缓存驻留问题,避免因一次性的大量扫描把真正的热点数据挤出缓存(即“缓存污染”)。

Caffeine 默认通常将约 1% 的空间分给 Window 区,99% 给 Main 区

window区

默认约占总缓存大小的 1%。它是标准的 LRU 队列。所有新写入(Put)或者新加载(Load)的数据,必须先进入 Window 区

作用:作为“缓冲区”。

专门应对突发流量或一次性扫描。如果一个数据只是被“路过”访问一次,它会在 Window 区里待一会,随着新数据不断进来,它很快就会从 Window 区的尾部被挤出去。

如果没有 Window 区,大量新数据涌入会直接把 Main 区里的高频老数据挤走。有了 Window 区,这些“一次性数据”在填满 Window 区后,如果后续没有再次被访问,就会直接被淘汰掉,甚至没有机会进入 Main 区

Window区是Caffeine中的第一道防线。用来过滤掉很少访问的数据

main区

Probation