首先要说的是机器配置
namenode/datanode:
cpu : 8core memory: 56G
我现在是基于yarn+spark的架构来说。
现在设置
yarn.nodemanager.resource.memory-mb =51200 (50GB) --每个node可以最多使用50GB作为 container 的分配
yarn.scheduler.minimum-allocation-mb =512 (0.5GB) --分配的递增单位是 0.5GB
yarn.scheduler.maximum-allocation-mb =51200 ( 50GB) --最大的container是50GB, 也就是说,可以从 0.5G 1G 1.5G 2G 一直到 50G 一个container
--===================================================
数据输入为 10个文件,大小总共10G txt非压缩
使用spark-sql,默认的numPartitions 是1 ,所以 desired partition size = 10GB / 1 = 10GB
spark 的 block size = 512MB (实践中观察到,但实际的dfs.blocksize = 128MB, 有待进一步查明真相)
计算输入分区size公式= max(split size, min (desired partition size, block size))
默认的 mapreduce.input.fileinputformat.split.minsize=1 ( 1 byte)
所以 输入分区size= 512MB (如果需要解压的话,那么会变得更大)
现在需要计算 executor和container的大小.
executor大小 >= 输入分区的大小, 所以设置 512MB, 但需要考虑:
1)如果core资源较多,executor内设置多个线程(多个core分配给一个executor)的情况,那么GC的压力会比较大,如果GC time较长,那么需要考虑增加executor的内存;最好就是有多少个core就增加多少倍的输入分区大小。
2)如果需要cache数据的话,那么需要设置spark.storage.memoryFraction,默认值是0.6, 那么cache内存大小计算=executor*0.868*0.6
所以除去cache的内存,executor剩下0.4左右的大小。
所以 executor size * 0.868 * 0.4 = 512 MB * cores/executor (最小值 1 core,即单线程)
container size = executor size + max(executor size * 0.1, 384) = N * 512MB (因为递增单位为512MB)
executor num = nodes * 50G / container size
这个executor num可以根据整个cluster可以允许该用户使用多少资源而定,还有core的分配。这样可以支持多用户共享整个cluster的资源。
接下来我还会给大家讲讲如何处理OOM的问题,还有如何处理我们的输入跟输出的调优。