都说spark那么牛,有没有啥坑啊( 二 )
log4j.logger.org.apache.spark.scheduler=ERROR
4.高并发下的Cleaner的内存泄露
说道这里,Cleaner的设计应该算是spark最糟糕的设计。spark的ContextCleaner是用于回收与清理已经完成了的 广播boradcast,shuffle数据的。但是高并发下,我们发现这个地方积累的数据会越来越多,最终导致driver内存跑满而挂掉。
l我们先看下,是如何触发内存回收的
没错,就是通过System.gc() 回收的内存,如果我们在jvm里配置了禁止执行System.gc,这个逻辑就等于废掉(而且有很多jvm的优化参数一般都推荐配置禁止system.gc 参数)
lclean过程
这是一个单线程的逻辑,而且每次清理都要协同很多机器一同清理,清理速度相对来说比较慢,但是SQL并发很大的时候,产生速度超过了清理速度,整个driver就会发生内存泄露。而且brocadcast如果占用内存太多,也会使用非常多的本地磁盘小文件,我们在测试中发现,高持续性并发的情况下本地磁盘用于存储blockmanager的目录占据了我们60%的存储空间。
我们再来分析下 clean里面,那个逻辑最慢
真正的瓶颈在于blockManagerMaster里面的removeBroadcast,因为这部分逻辑是需要跨越多台机器的。
针对这种问题,
l我们在SQL层加了一个SQLWAITING逻辑,判断了堆积长度,如果堆积长度超过了我们的设定值,我们这里将阻塞新的SQL的执行。堆积长度可以通过更改conf目录下的ya100_env_default.sh中的ydb.sql.waiting.queue.size的值来设置。
l建议集群的带宽要大一些,万兆网络肯定会比千兆网络的清理速度快很多。
l给集群休息的机会,不要一直持续性的高并发,让集群有间断的机会。
l增大spark的线程池,可以调节conf下的spark-defaults.conf的如下值来改善。
5.线程池与threadlocal引起的内存泄露
发现spark,Hive,lucene都非常钟爱使用threadlocal来管理临时的session对象,期待SQL执行完毕后这些对象能够自动释放,但是与此同时spark又使用了线程池,线程池里的线程一直不结束,这些资源一直就不释放,时间久了内存就堆积起来了。
针对这个问题,延云修改了spark关键线程池的实现,更改为每1个小时,强制更换线程池为新的线程池,旧的线程数能够自动释放。
6.文件泄露
您会发现,随着请求的session变多,spark会在hdfs和本地磁盘创建海量的磁盘目录,最终会因为本地磁盘与hdfs上的目录过多,而导致文件系统和整个文件系统瘫痪。在YDB里面我们针对这种情况也做了处理。
7.deleteONExit内存泄露

推荐阅读
- 古人都说:“一颗绿萝七个鬼”,家中为什么忌讳养绿萝?
- 都说冬天要“少浇水”,家里有“4种花”要勤浇水,预防黄叶
- 为啥电器实体店的价格比淘宝贵那么多
- 为啥开通了百度云超级会员下载速度还是会那么慢
- 白皮书一般是政府发布的正式报告或文件,那么现在物联网、智慧城市等热门领域这么多企业发布的白皮书算咋回事呢
- 为啥网上那么多诈骗的都没人管
- 车神探|探闻丨C-NCAP提升标准!这一批测试的结果还那么水吗?
- 汽车驾驶|设计师邀海外人士,变速箱寄人篱下,弯道超车,哪有那么容易
- 凯迪拉克CT6|都说新辉昂回归百万级质感,看完后发现不假
- 趣头条|都说科三太难,但这些“技巧”没有掌握,就不要再说自己努力过
