天天看点

Spark广播变量及GC调优

最新在工作中,需要在广告中过滤黑名单,具体业务鉴于保密,暂不详细阐述,本文想要说的是本次应用过程中使用Spark广播变量及使用GC调优解决该问题的要点,有用到的伙伴可以参考

正常spark日志解析中加入黑名单解析

根据前期调研查看,黑名单一类25万+,3.86MB,黑名单二类106万+,46.3MB,理论上完全可以将其封装,采用spark广播变量的方式广播到每一个节点处理

但是实际在测试中,遇到一些问题,总结一下      

正常一个小时日志解析参数

--num-executors 10 --driver-memory 4g --executor-memory 30g --executor-cores 4 ,解析时间6~7min,接下来按照上述解析流程做了以下测试        

- 测试一、将两种黑名单广播出去解析之后,多次测试均超过1h无果,将任务kill掉

- 测试二、将两种黑名单广播出去解析之后,加大executors数和executor-memory,多次测试均超过1h无果,将任务kill掉

- 测试三、将两种黑名单广播出去解析之后,加大executors数和executor-memory,将默认GC垃圾回收器换成G1,G1属于并行化垃圾回收器,超过50个task表现比较优秀,多次测试均超过1h无果,将任务kill掉

```

--conf spark.driver.extraJavaOptions="-XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseG1GC -XX:+PrintFlagsFinal \

-XX:+PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy \

-XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark" \

```

- 测试四、将两种黑名单广播出去解析之后,加大executors数和executor-memory,将默认GC垃圾回收器换成G1,并且加大垃圾回收线程,多次测试均超过1h无果,将任务kill掉

```

--conf spark.driver.extraJavaOptions="-XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseG1GC -XX:+PrintFlagsFinal \

-XX:+PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy \

-XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -XX:InitiatingHeapOccupancyPercent=35 -XX:ConcGCThreads=20" \

```

- 测试五、问题还应该回归到代码中寻求解决思路,当时广播的时候,数据加载到内存,把list广播出去,后续解析使用list.contains,后来想到list和map在这个方法上性能应该不一样,ArrayList使用的是数组来存储元素,而HashMap使用哈希表来存储元素,查看源码,list底层是数组,每调用一次contains方法,要遍历一次数据,通过index实现,时间复杂度O (n2),但是在HashMap,key被存储到hash表中,查找时是在hash表上进行查找,时间复杂度几乎是O (1),经过测试,果不其然,解析完,用时7min,以后大家如有用到,需注意,list的性能在千以下还可以,在10万,100万级别,匹配的性能会大大缩小,性能比map差20倍不止,至此验证了黑名单解析可以采用spark广播的方式。

list contains通过调用自己的indexof实现,indexof源码如下   

```

public int indexOf(Object o) {

        if (o == null) {

            for (int i = 0; i < size; i++)

                if (elementData[i]==null)

                    return i;

        } else {

            for (int i = 0; i < size; i++)

                if (o.equals(elementData[i]))

                    return i;

        }

        return -1;

    }

```

当然还可以在impala中使用join的方式解决该问题,impala默认采用hashjoin方式,非nextLoop算法,此处不再熬述。

后续有时间将GC的测试过程贴图,最近较忙

继续阅读