Spark+Hadoop集群性能调优

  • Hadoop短路本地读(原理:unix domain socket),提高文件读取性能
  • Hadoop的NameNode节点连接数设置要合理,设置hdfs-site.xml的dfs.namenode.handler.count配置,合理的连接值:python -c 'import math ; print int(math.log(计算节点的数量) * 20)'
  • Data Locality的问题(万兆网络下这个参数对性能的影响就比较小了),spark work启动的ip要和hadoop datanode的ip一致,如果是ip需要都配置为ip如果是hostname那就都配置为hostname,不然Spark计算时无法正常设置Data Locality,也就是Locality Level大部分变成了Any。和Tachyon搭配使用同样存在此问题,需要注意调整。参考:https://issues.apache.org/jira/browse/SPARK-10149
  • 控制好WORK_INSTANCE的数量,说白了,需要配置好核数,充分利用好多核CPU,要么多进程,要么多线程,无论那种配置,把CPU充分利用好才能达到最佳状态。如果启动多个Spark Application,将WORK_INSTANCE设置为1即可,如果只启用了一个Spark Appliction,你的服务器核数有比较好,建议将WORK_INSTANCE设置的多一些,充分利用好CPU
  • Spark SQL采用Parquet格式,提高查询性能,同时还能减少磁盘IO和网络IO
  • Spark集群的节点数量较多时(大于20台),建议开启spark.speculation=true,避免单台机器因为负载过高影响整体查询速度。
  • 对于超过10G的大表查询,建议调高spark.kryoserializer.buffer.max
  • join类型的SQL计算,如果数据量很大的话,考虑使用hive,MapReduce的shuffle默认内存速度可能比Spark要快
  • 考虑给Spark集群服务器添加小块的SSD(128或256G都可以),将spark的SPARKLOCALDIRS指定为SSD的目录,提高shuffle的性能
  • 使用Tachyon做数据缓存,将读写分离,提高并发查询性能
  • 注意服务器网络相关配置,避免将内网ip段配置为外网ip,Spark会根据ip反解hostname,如果ip配置错误,会导致RPC异常,影响查询速度
  • 出现性能问题时,多分析Spark Appliction UI中的任务执行情况,找出影响耗时的具体因素,并关注系统日志,Spark的Work的日志默认存放在spark/work目录下
  • 重启Spark集群,注意先关闭Spark上的应用,如果直接重启可能会导致进程残留或进程僵死(原来就碰到过之前的Work没有完全kill掉,狂占CPU导致性能下降很严重)
  • Spark 1.5中使用Tungsten引擎,如果SQL语句过长的话,会导致Driver端CPU占用率暴增,需要控制SQL语句的长度,特别需要注意case when的语句
  • GC优化:-XX:+UseG1GC -XX:+PrintFlagsFinal -XX:+PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy -XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -XX:InitiatingHeapOccupancyPercent=35
  • Spark 1.6.1的代码存在多线程并发bug,建议一个executor只启动一个core,避免多线程并发带来的各种问题
  • Driver端的GC建议改为串行回收器,避免GC问题,导致服务器CPU被打满
  • Spark SQL广播的表,注意大小的设置,过大时,如果任务并发较多,很容易将Driver端的内存用尽

资源分配

定位性能瓶颈,是在磁盘IO、内存、CPU还是网络。

万兆网络下一般网络是没什么问题。

内存容易出现问题,需要特别关注服务器剩余内存,如果剩余内存较少,那么cache的数据相应也会变少,Spark读取Hadoop的缓存命中率会变低,影响读取性能。

需要特别控制内存的使用,如果内存使用过多,那么系统会分配Swap内存,整个系统的性能会急剧下降,应该尽可能避免用到Swap分区。

磁盘IO方面,最好保证每台机器的平均磁盘IO,读取在2.5MB/s,写入在5MB/s以下,过高的磁盘IO会造成CPU等待磁盘,进而影响性能。这个可以监控cpu_wio的性能指标。

其他

/etc/rc.local中增大ulimit设置:limit -SHn 102400避免出现:java.lang.OutOfMemoryError: unable to create new native thread

linux系统内核调优(/etc/sysctl.conf):

vm.zone_reclaim_mode=1  
net.ipv4.ip_forward = 0  
kernel.sysrq = 0  
kernel.core_uses_pid = 1  
net.ipv4.tcp_syncookies = 1  
kernel.msgmnb = 65536  
kernel.msgmax = 65536  
kernel.shmmax = 68719476736  
kernel.shmall = 4294967296  
net.ipv4.tcp_max_tw_buckets = 6000  
net.ipv4.tcp_sack = 1  
net.ipv4.tcp_window_scaling = 1  
net.ipv4.tcp_rmem = 4096 87380 4194304  
net.ipv4.tcp_wmem = 4096 16384 4194304  
net.core.wmem_default = 8388608  
net.core.rmem_default = 8388608  
net.core.rmem_max = 16777216  
net.core.wmem_max = 16777216  
net.core.netdev_max_backlog = 262144  
net.core.somaxconn = 2048  
net.ipv4.tcp_max_orphans = 3276800  
net.ipv4.tcp_max_syn_backlog = 262144  
net.ipv4.tcp_timestamps = 0  
net.ipv4.tcp_synack_retries = 1  
net.ipv4.tcp_syn_retries = 1  
net.ipv4.tcp_tw_recycle = 1  
net.ipv4.tcp_tw_reuse = 1  
net.ipv4.tcp_mem = 94500000 915000000 927000000  
net.ipv4.tcp_fin_timeout = 2  
net.ipv4.tcp_keepalive_time = 1200  
net.ipv4.ip_local_port_range = 1024 65535  
net.ipv6.conf.all.disable_ipv6=1