byte[]做缓存key导致JVM异常

现象

产品的query模块运行一段时间后,就不能正常提供服务,严重影响了服务的可用性

追查

查看日志,发现读取Hbase时发生了OutOfMemory现象。
首先获取JVM的进程号,为16796
$jstat -gcutil 16796 发现频繁的发生full gc,显然full gc没有将内存清理掉
这里写图片描述
$jmap -histo 16796 查看进程中的对象,发现包com.fasterxml.jackson.databind.node引入的对象格外多(包括包中的对象以及引用的[C、[B等对象)。
然后查看代码,发现代码中引入了缓存。我们查询的数据源是HBase,当时的作者为了减少和HBase之间的IO交互,将查询的内容进行了缓存,而key是HBase的(byte[])rowkey。想法是好的,但实际上起了负面作用。查询缓存的第一步是检查key是否在缓存中,该过程首先判断key的hashcode是否能和已有的key匹配,如果匹配,再判断是否equals。因为数组的hashcode和对象的地址有关,而和内容是没有关系的,这样缓存永远都不会命中。

 LoadingCache<byte[], ArrayNode> rowKey2ArrayNodeCache = CacheBuilder.newBuilder()
    .maximumSize(MAX_CACHE_NUMBER)
    .expireAfterWrite(CRASH_CACHE_DURATION, TimeUnit.HOURS)
    .build(new CacheLoader<byte[], ArrayNode>() {
        @Override
        public ArrayNode load(byte[] key) throws Exception {
            return EMPTY_NODE;
        }
    });

在查询前后,发现缓存果真一次都没有命中

解决

  1. 我们的query压力不大,将这段无用的缓存模块删掉,这为我们节约了大量的内存
  2. query模块不是单点的,而且JVM随着时间的运行,会产生大量的碎片,从而影响性能。我们让query模块每天在凌晨的一个随机的时间点重启
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值