重新认识下JVM级别的本地缓存框架Guava Cache(2)——深入解读其容量限制和数据淘汰策略
发布时间:2023-04-03 11:23:13 所属栏目:教程 来源:
导读:通过《重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来》一文,我们知道了Guava Cache作为JVM级别的本地缓存组件的诸多暖心特性,也一步步地学习了在项目中集成并使用Guava Cache进行缓存相关
|
通过《重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来》一文,我们知道了Guava Cache作为JVM级别的本地缓存组件的诸多暖心特性,也一步步地学习了在项目中集成并使用Guava Cache进行缓存相关操作。Guava Cache作为一款优秀的本地缓存组件,其内部很多实现机制与设计策略,同样值得开发人员深入的掌握与借鉴。 作为系列专栏,本篇文章我们将在上一文的基础上,继续探讨下Guava Cache对于缓存容量限制与数据清理相关的使用与设计机制,进而让我们在项目中使用起来可以更加的游刃有余,解锁更多使用技巧。 容量限制时的Size与Weight区别 弄清Size与Weight Guava Cache提供了对缓存总量的限制,并且支持从两个维度进行限制,这里我们首先要厘清size与weight两个概念的区别与联系。 限制缓存条数size public Cache<String, User> createuserCache() { return CacheBuilder.newBuilder().maximumSize(10000L).build(); } 限制缓存权重weight public Cache<String, String> createuserCache() { return CacheBuilder.newBuilder() .maximumWeight(50000) .weigher((key, value) -> (int) Math.ceil(value.length() / 1000)) .build(); } 一般而言,我们限制容器的容量的初衷,是为了防止内存占用过大导致内存溢出,所以本质上是限制内存的占用量。从实现层面,往往会根据总内存占用量与预估每条记录字节数进行估算,将其转换为对缓存记录条数的限制。这种做法相对简单易懂,但是对于单条缓存记录占用字节数差异较大的情况下,会导致基于条数控制的结果不够精准。 比如: 需要限制缓存最大占用500M总量,缓存记录可能大小范围是1k~100k,按照每条50k进行估算,设定缓存容器最大容量为限制最大容量1w条。如果存储的都是1k大小的记录,则内存总占用量才10M(内存没有被有效利用起来);若都存储的是100k大小的记录,又会导致内存占用为1000M,远大于预期的内存占用量(容易造成内存溢出)。 为了解决这个问题,Guava Cache中提供了一种相对精准的控制策略,即基于权重的总量控制,根据一定的规则,计算出每条value记录所占的权重值,然后以权重值进行总量的计算。 还是上面的例子,我们按照权重进行设定,假定1k对应基础权重1,则100k可转换为权重100。这样一来: 限制缓存最大占用500M,1k对应权重1,Nk代表权重N,则我们可以限制总权重为50w。这样假如存储的都是1k的记录,则最多可以缓存5w条记录;而如果都是100k大小的记录,则最多仅可以缓存5000条记录。根据存储数据的大小不同,最大存储的记录条数也不相同,但是最终占用的总体量可以实现基本吻合。 所以,基于weight权重的控制方式,比较适用于这种对容器体量控制精度有严格诉求的场景,可以在创建容器的时候指定每条记录的权重计算策略(比如基于字符串长度或者基于bytes数组长度进行计算权重)。 使用约束说明 在实际使用中,这几个参数之间有一定的使用约束,需要特别注意一下: 如果没有指定weight实现逻辑,则使用maximumSize来限制最大容量,按照容器中缓存记录的条数进行限制;这种情况下,即使设定了maximumWeight也不会生效。 如果指定了weight实现逻辑,则必须使用 maximumWeight 来限制最大容量,按照容器中每条缓存记录的weight值累加后的总weight值进行限制。 看下面的一个反面示例,指定了weighter和maximumSize,却没有指定 maximumWeight属性: public static void main(String[] args) { try { Cache<String, String> cache = CacheBuilder.newBuilder() .weigher((key, value) -> 2) .maximumSize(2) .build(); cache.put("key1", "value1"); cache.put("key2", "value2"); System.out.println(cache.size()); } catch (Exception e) { e.printstacktrace(); } } (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
