加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 综合聚焦 > 资源网站 > 空间 > 正文

Jvm内部缓存选型?一篇文章为你解答疑惑

发布时间:2019-09-24 18:53:14 所属栏目:空间 来源:青峰科技
导读:原生Java 简单的在HashMap的链式法增加新的引用形成一个链表,即是一个HashMap又是一个链表,这样输出即有序,也可以根据访问来动态调整顺序,达到FIFO或者LRU的特点。 使用ConcurrentHashMap作为缓存,没有淘汰功能或者手动淘汰。但是寻找效率较高,而且

我们的4个段分为A,B,C,D,在后面我也会这么叫它们。而每个段里面的四个算法我叫他s1,s2,s3,s4。下面举个例子如果要添加一个访问50的数字频率应该怎么做?我们这里用size=100来举例。

  • 首先确定50这个hash是在哪个段里面,通过hash & 3(3的二进制是11)必定能获得小于4的数字,假设hash & 3=0,那就在A段。
  • 对50的hash再用其他hash算法再做一次hash,得到long数组的位置,也就是在长度128数组中的位置。假设用s1算法得到1,s2算法得到3,s3算法得到4,s4算法得到0。
  • 因为S1算法得到的是1,所以在long[1]的A段里面的s1位置进行+1,简称1As1加1,然后在3As2加1,在4As3加1,在0As4加1。
面试jvm内部缓存选型?一篇文章为你解答疑惑

这个时候有人会质疑频率最大为15的这个是否太小?没关系在这个算法中,比如size等于100,如果他全局提升了size*10也就是1000次就会全局除以2衰减,衰减之后也可以继续增加,这个算法再W-TinyLFU的论文中证明了其可以较好的适应时间段的访问频率。

读写性能

在guava cache中我们说过其读写操作中夹杂着过期时间的处理,也就是你在一次Put操作中有可能还会做淘汰操作,所以其读写性能会受到一定影响,可以看上面的图中,caffeine的确在读写操作上面完爆guava cache。主要是因为在caffeine,对这些事件的操作是通过异步操作,他将事件提交至队列,这里的队列的数据结构是RingBuffer,不清楚的可以看看这篇文章,你应该知道的高性能无锁队列Disruptor。然后会通过默认的ForkJoinPool.commonPool(),或者自己配置线程池,进行取队列操作,然后在进行后续的淘汰,过期操作。

当然读写也是有不同的队列,在caffeine中认为缓存读比写多很多,所以对于写操作是所有线程共享一个Ringbuffer。

面试jvm内部缓存选型?一篇文章为你解答疑惑

对于读操作比写操作更加频繁,进一步减少竞争,其为每个线程配备了一个RingBuffer:

数据淘汰策略

在caffeine所有的数据都在ConcurrentHashMap中,这个和guava cache不同,guava cache是自己实现了个类似ConcurrentHashMap的结构。在caffeine中有三个记录引用的LRU队列:

  • Eden队列:在caffeine中规定只能为缓存容量的%1,如果size=100,那这个队列的有效大小就等于1。这个队列中记录的是新到的数据,防止突发流量由于之前没有访问频率,而导致被淘汰。比如有一部新剧上线,在最开始其实是没有访问频率的,防止上线之后被其他缓存淘汰出去,而加入这个区域。伊甸区,最舒服最安逸的区域,在这里很难被其他数据淘汰。
  • Probation队列:叫做缓刑队列,在这个队列就代表你的数据相对比较冷,马上就要被淘汰了。这个有效大小为size减去eden减去protected。
  • Protected队列:在这个队列中,可以稍微放心一下了,你暂时不会被淘汰,但是别急,如果Probation队列没有数据了或者Protected数据满了,你也将会被面临淘汰的尴尬局面。当然想要变成这个队列,需要把Probation访问一次之后,就会提升为Protected队列。这个有效大小为(size减去eden) X 80% 如果size =100,就会是79。

这三个队列关系如下:

面试jvm内部缓存选型?一篇文章为你解答疑惑
  1. 所有的新数据都会进入Eden。
  2. Eden满了,淘汰进入Probation。
  3. 如果在Probation中访问了其中某个数据,则这个数据升级为Protected。
  4. 如果Protected满了又会继续降级为Probation。

对于发生数据淘汰的时候,会从Probation中进行淘汰。会把这个队列中的数据队头称为受害者,这个队头肯定是最早进入的,按照LRU队列的算法的话那他其实他就应该被淘汰,但是在这里只能叫他受害者,这个队列是缓刑队列,代表马上要给他行刑了。这里会取出队尾叫候选者,也叫攻击者。这里受害者会和攻击者皇城PK决出我们应该被淘汰的。

通过我们的Count-Min Sketch中的记录的频率数据有以下几个判断:

  • 如果攻击者大于受害者,那么受害者就直接被淘汰。
  • 如果攻击者<=5,那么直接淘汰攻击者。这个逻辑在他的注释中有解释:
面试jvm内部缓存选型?一篇文章为你解答疑惑
  • 他认为设置一个预热的门槛会让整体命中率更高。
  • 其他情况,随机淘汰。

【编辑推荐】

  1. 来自JVM的灵魂拷问:“你是什么垃圾?”
  2. JVM发生内存溢出的8种原因、及解决办法
  3. JVM内存分配及String常用方法
  4. 记一次隐藏很深的 JVM 线上惨案的分析、排查、解决
  5. Tomcat 和 JVM 的性能调优经验总结!拿走不谢
【责任编辑:武晓燕 TEL:(010)68476606】
点赞 0

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读