orc文件导致hiveserver2的内存泄漏
环境说明
线上环境CDH6.0.1,hive没有做原始jar的替换,只是添加了一些hook逻辑代码
问题现象
hiveserver2服务启动后,短时间内存增长过快,但长时间并未进行垃圾回收,线上有些sql会执行maplocaljoin操作,采用hive.exec.submit.local.task.via.child=false模式执行未采用默认参数,默认配置会申请子jvm运行task任务,jvm资源申请会按照hiveserver2内存大小申请,导致内存设置过大申请失败故不采用默认参数,下图为hiveserver2重启后内存的使用情况
问题分析
进程对象分析
使用jmap命令抓取hiveserver2对象占用情况,由下图可以分析看到org.apache.orc.OrcProto
C
o
l
u
m
n
S
t
a
t
i
s
t
i
c
s
占用大量的内存,下边分析
o
r
g
.
a
p
a
c
h
e
.
o
r
c
.
O
r
c
P
r
o
t
o
ColumnStatistics占用大量的内存,下边分析org.apache.orc.OrcProto
ColumnStatistics占用大量的内存,下边分析org.apache.orc.OrcProtoColumnStatistics是如何生成的
OrcProto$ColumnStatistics对象来源查找
网上查看一下相关问题发现此文章和上述问题类似:orc表导致hiveserver2内存暴涨问题分析,通过上述文章解析,本人测试了作者给的几个方案,发现修改参数都无法减少stripe,继续查找CDH社区,发现如下BUG记录,查看此jira将问题定位到 CacheBuilder.newBuilder()上
分析hiveserver dump
使用 jmap -dump:format=b,file=hiveserver2.hprof xxx(hiveserver2进程id)获取dump 将dump文件导入mat分析对象来源,如下图确认到就是CacheBuilder问题产生的原因 (此数据为测试环境,展示OrcProto$ColumnStatistics获取过程)
上图根据对象的来源查看到了 ColumnStatistics是由 OrcTail类生成的,查看hive这块代码逻辑,查看 OrcTail 就是由 CacheBuilder.newBuilder 存储的对象
class LocalCache implements OrcInputFormat.FooterCache {
private static final Logger LOG = LoggerFactory.getLogger(LocalCache.class);
private static final int DEFAULT_CACHE_INITIAL_CAPACITY = 1024;
private final Cache<Path, OrcTail> cache;
LocalCache(int numThreads, int cacheStripeDetailsSize, boolean useSoftRef) {
CacheBuilder builder = CacheBuilder.newBuilder()
.initialCapacity(DEFAULT_CACHE_INITIAL_CAPACITY)
.concurrencyLevel(numThreads)
//统计的条目,如条目超出限制,会回收不太可能适用的条目
.maximumSize(cacheStripeDetailsSize);
if (useSoftRef) {
builder = builder.softValues();
}
cache = builder.build();
}
内存增加问题定位
由上述分析,即可得到 jvm内存由OrcProto C o l u m n S t a t i s t i c s 占用, O r c P r o t o ColumnStatistics占用,OrcProto ColumnStatistics占用,OrcProtoColumnStatistics由 CacheBuilder 的maximumSize 参数控制,maximumSize 默认的参数为:hive.orc.cache.stripe.details.size=10000
问题解决方案
1、又上述分析可得到,减少hive.orc.cache.stripe.details.size 参数大小也可以减少内存使用,但此方法指标不治本,不能很好的控制内存的使用大小。
2、按照HIVE-10651和HIVE-16133分析,需替换CacheBuilder.newBuilder() 中maximumSize,更换为maximumWeight可更好的控制jvm内存
上述为此问题的分析及解决方案,如有不足及错误之处,欢迎交流指出,谢谢~