前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >byte[]做缓存key导致JVM异常

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

作者头像
jiewuyou
发布2022-09-29 17:18:22
5520
发布2022-09-29 17:18:22
举报
文章被收录于专栏:数据人生

现象

产品的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和对象的地址有关,而和内容是没有关系的,这样缓存永远都不会命中。

代码语言:javascript
复制
 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模块每天在凌晨的一个随机的时间点重启
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 现象
  • 追查
  • 解决
相关产品与服务
TDSQL MySQL 版
TDSQL MySQL 版(TDSQL for MySQL)是腾讯打造的一款分布式数据库产品,具备强一致高可用、全球部署架构、分布式水平扩展、高性能、企业级安全等特性,同时提供智能 DBA、自动化运营、监控告警等配套设施,为客户提供完整的分布式数据库解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档