zookeeper集群oom记录
起因
cloudera集群邮件告警,zookeeper server离线。
第一次处理,无脑重启集群。因为白天没什么任务,直接重启可以解决部分资源紧张问题。
第一次处理结果,失败。
原因复查
重启不能解决,那么就是真的有问题了。
首先,我们检查了集群角色日志,发现out of memory错误。
显然应用内存爆了……
第二次处理,在Cloudera manager中修改zookeeper配置,添加内存到2G。
第二次处理结果,失败。
内存从1G调整到2G,直接double,没道理再崩啊 0-0
dump分析
没办法,拉出zk服务的oom时的堆转储文件
可以看到,起初的dump文件800+M;后来的dump文件1.6+G
神奇,挂的很完美
在序列化当前事务时出错。
通过java visual vm查看,数组扩容时出错。跟进去看
输出流写出大量数据,导致数组扩容。申请不到足够内存。
那么问题来了,zk上,通过只会存储极少量注册信息。怎么会有这么多数据。
zk数据检查
zk服务已经宕机,我们无法通过寻常方式检查zk节点信息。
如此,我们想到zk数据存储在哪里呢?
答案是:datadir指定的目录,配置在zoo.cfg中
我们观察到,数据目录下,同时有zk日志文件、快照文件。
可以看到,快照文件大小,无比接近dump文件。进一步确认数据量爆炸。
快照文件查看方式如下,
java -cp /opt/cloudera/parcels/CDH-6.0.0-1.cdh6.0.0.p0.537114/lib/zookeeper/lib/log4j.jar:/opt/cloudera/parcels/CDH-6.0.0-1.cdh6.0.0.p0.537114/lib/zookeeper/build/*:/opt/cloudera/parcels/CDH-6.0.0-1.cdh6.0.0.p0.537114/lib/zookeeper/build/lib/*:/opt/cloudera/parcels/CDH-6.0.0-1.cdh6.0.0.p0.537114/lib/zookeeper/*:/opt/cloudera/parcels/CDH-6.0.0-1.cdh6.0.0.p0.537114/lib/zookeeper/lib/*:/opt/cloudera/cm/lib/plugins/event-publish-6.0.0-shaded.jar:/opt/cloudera/cm/lib/plugins/tt-instrumentation-6.0.0.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.3000540f8 | more
配合grep/awk/sort等,我们发现,集群上有近10000个数据节点。
其中有部分节点比较大,达到0.3M。
进一步观察,较大的这些文件,都是hive share lock。
集群中一直有hive在运行,但是从没发现hive使用了如此多的zk资源。属实意外!!!
hive事务实现
穿插一点hive:hive事务由共享锁、排它锁实现。在我锁使用的版本中,锁被保存的zk。
询问可能使用hive的同事,事发时间确实有跑脚本。
那么问题基本定位,gps位置信息在hive中分区存储,拥有大量分区表。
同事的sql使用了这些分区表,所以zk中写入了大量hive共享锁信息(估计近4000)
zk重启
调大zk内存到5G,重启
可以看到follower从leader同步快照文件。由于文件较大,同步慢慢不结束。
这里方法有点暴力,生产不建议操作
强制重新初始化zk数据目录zookeeper-server-init
,重启zk
最后的处理
关闭hive事务(当前业务上刚好没用到该特性)
重启所有服务