spark调优是需要根据业务需要调整的,并不是说某个设置是一成不变的,就比如机器学习一样,是在不断的调试中找出当前业务下更优的调优配置。下面零碎的总结了一些我的调优笔记。
spark 存储的时候存在严重的分配不均的现象,有几台机器在过渡使用, 有几台机器却很少被使用,有几台机器缓存了几十个上百个RDD blocks 有的机器一个RDD blocks 都没有,这样存储有RDD blocks 的可以进行运算,运算的tasks 最多为该机器core数。
spark.storage.memoryFraction 分配给用于缓存RDD的内存的比例
比如如果spark.executor.memory 30g spark.storage.memoryFraction 0.5 则用于缓存的内存为14G 多, 默认留一些做其他用。
每一个RDD blocks 的大小不一定是64兆 可能小于64兆,另外如果driver不是子节点,driver 程序运行的节点上的用于缓存的内存 ,就不会被使用。
事实上一个两三G 的数据 需要用的缓存也至少需要两三G,如果中间过程中还有产生RDD 且也需要缓存到内存,则需要分配更多的内存用于缓存。在缓存足够多的情况的
更多的内存不足错误提示(OOM) 来源于计算的时候产生的一些中间对象即计算所需要的内存。
所以分配用于缓存的内存 应该是这么算的, 比如我有10G的文件,4台机器,则每台机器至少2.5g缓存,如果每台机器分配给excutor 的内存为10g ,则memoryFraction 则至少为0.25 最好配大一些,但不能太大, 太大会导致计算内存不够。而且如果中间过程还有产生新的RDD,则需要根据实际情况调大memoryFraction。
RDD 缓存分布不均匀 是影响spark 的很大的性能之一,为什么这么说?
因为有的机器分配给用于RDD 缓存的内存都用完了 ,这样相对而言在这个机器上计算的开销也会大,有的机器缓存占用的内存很少,就算用这个机器来计算,还需要启动Node_local 模式,这样会影响计算的时间。
为什么一个2G 的数据,默认块大小为64M. default.parallelism 设置成100,可它总是不按这个数据来分,比如经常分成了108个blocks,影响partions个数的参数还有哪些?还有我明明有四个节点,但经常有节点被分配的RDD 和计算都很少很少,这种资源浪费的情况应该怎么调解?
《续》
1. spark性能配置
我目前的环境是5台机器,每台机器8个核。如果有以下两种配置方案:
(a)
SPARK_WORKER_INSTANCES = 8
SPARK_WORKER_CORES = 1
(b)
SPARK_WORKER_INSTANCES = 1
SPARK_WORKER_CORES = 8
如何处理?
答: a方案每个节点会启动8个worker运行8个JVM,每个worker将会启动一个excutors, b方案将会启动一个worker运行一个JVM。如果数据很小,选择b方案,因为可以节省启动JVM的开销,如果数据很大,启动JVM的时间可以忽略,则选a方案。
如果5台机器的内存都是48g,a,b方案在添加如下配置:
(a)SPARK_WORKER_MEMORY = 6g //给每个worker 分配6G 内存
(b)SPARK_WORKER_MEMORY = 48g
配置的时候注意:
SPARK_WORKER_CORES * SPARK_WORKER_INSTANCES= 每台机器总cores
2.Hadoop配置详解:
1.core-site.xml
常用的设置:
fs.default.name hdfs://mastername:9000
这是一个描述集群中NameNode结点的URI(包括协议、主机名称、端口号),集群里面的每一台机器都需要知道NameNode的地址。DataNode结点会先在NameNode上注册,这样它们的数据才可以被使用。独立的客户端程序通过这个URI跟DataNode交互,以取得文件的块列表。默认的文件系统的名称,默认的是设置单机配置,如果是伪分布式则设置hdfs://localhost:9000,如果是完全分布式则设置成hdfs://mastername:9000
hadoop.tmp.dir /tmp/hadoop-${user.name}
hadoop.tmp.dir是hadoop文件系统依赖的基础设置,很多路径都依赖它,如果hdfs-site.xml中不配置namenode和datanode的存放位置,默认就放在这个路径中,所以最好设置,而且设置到持久目录中。使用默认的路径会根据不同的用户名生成不同的临时目录。
优化参数:
hadoop.logfile.size 10000000 日志文件最大为10M
hadoop.logfile.count 10 日志文件数量为10个
hadoop跑了很多任务后,可以通过设置hadoop.logfile.size和hadoop.logfile.count来设定最大的日志大小和数量来自动清楚日志。
io.file.buffer.size 4096 流文件的缓冲区为4K
这是读写sequence file的buffer size,可以减少I/O次数,在大型的Hadoop cluster,建议使用更大的值。
hdfs-site.xml
常用设置:
dfs.replication 它决定着 系统里面的文件块的数据备份个数。对于一个实际的应用,它应该被设为3(这个数字并没有上限,但更多的备份可能并没有作用,而且会占用更多的空间)。少于三个的备份,可能会影响到数据的可靠性(系统故障时,也许会造成数据丢失)
dfs.data.dir 这是DataNode结点被指定要存储数据的本地文件系统路径。DataNode结点上的这个路径没有必要完全相同,因为每台机器的环境很可能是不一样的。但如果每台机器上的这个路径都是统一配置的话,会使工作变得简单一些。默认的情况下,它的hadoop.tmp.dir, 这个路径只能用于测试的目的,因为,它很可能会丢失掉一些数据。所以,这个值最好还是被覆盖。
dfs.name.dir 这是NameNode结点存储hadoop文件系统信息的本地系统路径。这个值只对NameNode有效,DataNode并不需要使用到它。上面对于/temp类型的警告,同样也适用于这里。在实际应用中,它最好被覆盖掉。
dfs.permissions true 文件操作时的权限检查标识,控制读写权限,false不控制读写权限。
dfs.block.size 67108864 缺省的文件块大小为64M
hadoop fsck /文件目录 –files –locations –blocks 查看文件存储信息
用法:hadoop fsck [GENERIC_OPTIONS]<path> [-move | -delete | -openforwrite] [-files [-blocks [-locations |-racks]]]
<path> 检查的起始目录。
-move 移动受损文件到/lost+found
-delete 删除受损文件。
-openforwrite 打印出写打开的文件。
-files 打印出正被检查的文件。
-blocks 打印出块信息报告。
-locations 打印出每个块的位置信息。
-racks 打印出data-node的网络拓扑结构。
dfs.namenode.logging.level info 输出日志类型
优化设置:
dfs.df.interval 60000 磁盘空间统计间隔为6秒
dfs.client.block.write.retries 3 块写入出错时的重试次数
dfs.heartbeat.interval 3 数据节点的心跳检测间隔时间
dfs.balance.bandwidthPerSec 1048576 启动负载均衡的数据节点可利用带宽最大值为1M
dfs.datanode.failed.volumes.tolerated 0
决定停止数据节点提供服务充许卷的出错次数。0次则任何卷出错都要停止数据节点。
dfs.datanode.data.dir.perm 755 数据节点的存贮块的目录访问权限设置
更多信息请参读:
http://hadoop.apache.org/docs/r2.2.0/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
mapred-site.xml
mapreduce.framework.name yarn
mapred.job.tracker mastername:9001 作业跟踪管理器是否和MR任务在一个进程中。默认值是local,单节点。Job 运行的host和端口号。
mapred.local.dir ${hadoop.tmp.dir}/mapred/local MR的中介数据文件存放目录
mapred.system.dir ${hadoop.tmp.dir}/mapred/system MR的控制文件存放目录
mapred.temp.dir ${hadoop.tmp.dir}/mapred/temp MR临时共享文件存放区
常见名词解释:
Driver:使用Driver这一概念的分布式框架很多,比如Hive等,spark中的Driver即运行Application的main() 函数并且创建SparkContext,创建sparkContext的目的是为了准备spark应用程序的运行环境,在spark中由SparkContext负责和clusterManager通信,进行资源的申请、任务的分配和监控等。当Excutor部分运行完毕后,Driver同时负责将SparkContext关闭,通常用SparkContext代表Driver。
Excutor:某个Appliction运行在Worker节点上的一个进程,该进程负责运行某些Task,并且负责将数据存在内存或者磁盘上。每个Application都有各自独立的一批Excutor。在Spark on yarn 模式下,进程名称为CoarseGrainedExcutorBackend。一个CoarseGrainedExcutorBackend进程有且仅有一个Excutor对象,它负责将Task包装成taskRunner,并从线程池中抽取出一个空闲线程运行Task,每个CoarseGrainedExcutorBackend能并行运行的Task的数量就取决于分配给他的cpu的个数了。
Cluster Manager:指的是在集群上获取资源的外部服务,目前有:
Standalone:Spark原生的资源管理,有Master负责资源的分配,可以在亚马逊的EC2上运行。
Apache Mesos:与Hadoop Mapreduce兼容性良好的一种资源调度框架;
Hadoop Yarn:主要是指的Yarn的ResourceManger;