一篇学会Caffeine W-TinyLFU源码分析

Caffeine使用一个ConcurrencyHashMap来保存所有数据,那它的过期淘汰策略采用什么方式与数据结构呢?其中写过期是使用writeOrderDeque,这个比较简单无需多说,而读过期相对复杂很多,使用W-TinyLFU的结构与算法。【资料获取】

网络上有很多文章介绍W-TinyLFU结构的,大家可以去查一下,这里主要是从源码来分析,总的来说它使用了三个双端队列:

  • accessOrderEdenDeque,accessOrderProbationDeque,accessOrderProtectedDeque,使用双端队列的原因是支持LRU算法比较方便。

  • accessOrderEdenDeque属于eden区,缓存1%的数据,其余的99%缓存在main区

  • accessOrderProbationDeque属于main区,缓存main内数据的20%,这部分是属于冷数据,即将补淘汰。

  • accessOrderProtectedDeque属于main区,缓存main内数据的80%,这部分是属于热数据,是整个缓存的主存区。

我们先看一下淘汰方法入口:

void evictEntries() {
    
  if (!evicts()) {
    
    return; 
  } 
  //先从edn区淘汰 
  int candidates = evictFromEden(); 
  //eden淘汰后的数据进入main区,然后再从main区淘汰 
  evictFromMain(candidates); 
} 

accessOrderEdenDeque对应W-TinyLFU的W(window),这里保存的是最新写入数据的引用,它使用LRU淘汰,这里面的数据主要是应对突发流量的问题,淘汰后的数据进入accessOrderProbationDeque.代码如下:

int evictFromEden() {
    
  int candidates = 0; 
  Node<K, V> node = accessOrderEdenDeque().peek(); 
  while (edenWeightedSize() > edenMaximum()) {
    
    // The pending operations will adjust the size to reflect the correct weight 
    if (node == null) {
    
      break; 
    } 
 
    Node<K, V> next = node.getNextInAccessOrder(); 
    if (node.getWeight() != 0) {
    
      node.makeMainProbation(); 
      //先从eden区移除 
      accessOrderEdenDeque().remove(node); 
      //移除的数据加入到main区的probation队列 
      accessOrderProbationDeque().add(node); 
      candidates++; 
 
      lazySetEdenWeightedSize(edenWeightedSize() - node.getPolicyWeight()); 
    } 
    node = next; 
  } 
 
  return candidates; 
} 

数据进入probation队列后,继续执行以下代码:

void evictFromMain(int candidates) {
    
  int victimQueue = PROBATION; 
  Node<K, V> victim = accessOrderProbationDeque().peekFirst(); 
  Node<K, V> candidate = accessOrderProbationDeque().peekLast(); 
  while (weightedSize() > maximum()) {
    
    // Stop trying to evict candidates and always prefer the victim 
    if (candidates == 0) {
    
      candidate = null; 
    } 
 
    // Try evicting from the protected and eden queues 
    if ((candidate == null) && (victim == null)) {
    
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值