
Caffeine 在内存布局上做到了严格的职责分离,它的底层并非单一结构,而是由“数据的存储”与“淘汰元数据的存储”共同组成:
ConcurrentHashMap(数据载体):FrequencySketch(频率记录器):long 数组,通过多个不同的 Hash 算法映射位图来记录访问频率。ConcurrentHashMap 中存在的同时,其引用会被串联在逻辑队列中,用于维护淘汰顺序。这三个队列分别是:传统的 LRU 无法应对周期性扫描(会导致热点数据被洗掉),而传统的 LFU 无法应对突发流量(旧的热点数据占据缓存不放)。Caffeine 提出的 W-TinyLFU (Window-TinyLFU) 完美融合了两者的优点。
数据的生命周期与流转机制如下:
FrequencySketch 中查询两者的历史访问频率。FrequencySketch 内部有一个计数器。当系统的总访问次数达到一定阈值时,所有 Key 的频率记录都会减半(衰减),从而给新数据让出竞争空间。这是 Caffeine 碾压 Guava Cache 的核心所在。传统缓存(如 Guava)在每次读写数据后,都需要同步更新 LRU 双向链表。因为链表操作非线程安全,必须加锁。在高并发下,这把锁成为了吞吐量的绝对瓶颈。
Caffeine 彻底解耦了“操作数据”和“维护策略”的执行逻辑:
ConcurrentHashMap 拿到数据后,只负责将这次访问事件(Event)记录到一个类似于 Striped64(类似 LongAdder)的 RingBuffer 中。利用多段细粒度的环形数组,极大地避免了 CPU 缓存行的伪共享(False Sharing)问题,实现了完全无锁的记录。FrequencySketch 频率、移动 Window/Main 区的双向链表指针时,完全不需要加任何全局锁。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。