浅谈Caffeineh缓存框架

浅谈Caffeine

Caffeine

Caffeine是一种建立在java8基础上的高性能缓存框架。它是一种本地缓存,功能类似Guava cache,可以理解为其是Guava cache的一个加强版本。

性能比较:

在这里插入图片描述

Caffeine功能介绍

缓存淘汰策略

提供了三种缓存淘汰策略,分别是基于大小、时间、引用方式。

基于大小的方式:

1、可以使用Caffeine.maximumSize(long)方法来指定缓存的最大容量。

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
    .maximumSize(10_000)
    .build();

2、可以使用权重的策略来进行驱逐,

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
    .maximumWeight(10_000)
    .build();
基于时间的方式:

1、expireAfterAccess(long, TimeUnit):在最后一次访问或者写入后开始计时,在指定的时间后过期。假如一直有请求访问该key,那么这个缓存将一直不会过期

2、expireAfterWrite(long, TimeUnit): 在最后一次写入缓存后开始计时,在指定的时间后过期

3、expireAfter(Expiry): 自定义策略,过期时间由Expiry实现独自计算。

基于引用的方式:

Caffeine.weakKeys() 使用弱引用存储key。如果没有其他地方对该key有强引用,那么该缓存就会被垃圾回收器回收。由于垃圾回收器只依赖于身份(identity)相等,因此这会导致整个缓存使用身份 (==) 相等来比较 key,而不是使用 equals()。

Caffeine.weakValues() 使用弱引用存储value。如果没有其他地方对该value有强引用,那么该缓存就会被垃圾回收器回收。由于垃圾回收器只依赖于身份(identity)相等,因此这会导致整个缓存使用身份 (==) 相等来比较 key,而不是使用 equals()。

Caffeine.softValues() 使用软引用存储value。当内存满了过后,软引用的对象以将使用最近最少使用(least-recently-used ) 的方式进行垃圾回收。由于使用软引用是需要等到内存满了才进行回收,所以我们通常建议给缓存配置一个使用内存的最大值。 softValues() 将使用身份相等(identity) (==) 而不是equals() 来比较值。

注意:Caffeine.weakValues()和Caffeine.softValues()不可以一起使用。

Caffeine的淘汰算法—W-TinyLFU

缓存淘汰算法的作用是在有限的资源内,尽可能识别出哪些数据在短时间会被重复利用,从而提高缓存的命中率。常用的缓存淘汰算法有LRU、LFU、FIFO等。

LRU(Least Recently Used)算法认为最近访问过的数据将来被访问的几率也更高。LRU通常使用链表来实现,如果数据添加或者被访问到则把数据移动到链表的头部,链表的头部为热数据,链表的尾部如冷数据,当数据满时,淘汰尾部的数据。其实现比较简单,但是存在一些问题,如:当存在数据遍历时,会导致LRU命中率急剧下降,缓存污染情况比较严重。LRU算法也并非一无是处,其在突发流量下表现良好。

LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。根据LFU的思想,如果想要实现这个算法,需要额外的一套存储用来存每个元素的访问次数,会造成内存资源的浪费。

Caffeine采用了一种结合LRU、LFU优点的算法:W-TinyLFU,其特点:高命中率、低内存占用。在搞懂W-TinyLFU算法之前,首先了解一下TinyLFU算法:TinyLFU是一种为了解决传统LFU算法空间存储比较大的问题LFU算法,它可以在较大访问量的场景下近似的替代LFU的数据统计部分,它的原理有些类似BloomFilter。首先回顾一下BloomFilter原理:在BloomFilter中,使用一个大的bit数组用于存储所有key,每一个key通过多次不同的hash计算来映射数组的不同bit位,如果key存在将对应的bit位设置为1,这样就可以通过少量的存储空间进行大量的数据过滤。在TinyLFU中,把多个bit位看做一个整体,用于统计一个key的使用频率,TinyFLU中的key也是通过多次不同的hash计算来映射多个不同的bit组。在读取时,取映射的所有值中的最小的值作为key的使用频率,TinyLFU算法如下图所示:

在这里插入图片描述

在Caffeine中,维护了一个4-bit CountMinSketch用来记录key的使用频率。4-bit也就意味着,统计的key最大使用频率为15,TinyLFU有一个缺点,在应对突发流量的时候,可能由于没有及时构建足够的频率数据来保证自己驻留在缓存中,从而导致缓存的命中率下降,为了解决这个问题,产生了W-TinyLFU算法。

W-TinyLFU主要用来解决一些稀疏的突发访问元素。在一些数目很少但突发访问量很大的场景下,TinyLFU将无法保存这类元素,因为它们无法在给定时间内积累到足够高的频率。因此W-TinyLFU就是结合LFU和LRU,前者用来应对大多数场景,而LRU用来处理突发流量。

Caffeine淘汰机制—W-TinyLFU算法

W-TinyLFU由两部分组成,主缓存使用SLRU回收策略和TinyLFU回收策略,而窗口缓存使用没有任何回收策略的LRU回收策略,增加的窗口缓存用于应对突发流量的问题,如下图所示:

在这里插入图片描述

窗口缓存占用总大小的1%左右,主缓存占用99%。Caffeine可以根据工作负载特性动态调整窗口和主空间的大小,如果新增数据频率比较高,大窗口更受欢迎;如果新增数据频率偏小,小窗口更受欢迎。主缓存内部包含两个部分,一部分为Protected,用于存比较热的数据,它占用主缓存80%空间;另一部分是Probation,用于存相对比较冷的数据,占用主缓存20%空间,数据可以在这两部分空间里面互相转移。

缓存淘汰的过程:新添加的数据首先放入窗口缓存则把窗口缓存淘汰的数据转移到主缓存Probation区域中。如果这时主缓存也满了,则从主缓存的Probation区域淘汰数据,把这条数据称为受害者,从窗口缓存淘汰的数据称为候选人。接下来候选人和受害者进行一次pk,来决定去留。pk的方式是通过TinyFLU记录的访问频率来进行判断,具体过程如下:

  1. 首先获取候选人和受害者的频率
  2. 如果候选人大于受害者,则淘汰受害者
  3. 如果候选人频率小于等于5,则淘汰候选人
  4. 其余情况随机处理。
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值