优化 Java Spark 服务忙了整整一周,实验了各种办法和各种参数组合。
为什么要优化
现网有个spark服务,白天数据量大,积存数据,夜间数据量小,再把积存的数据处置惩罚完,固然达到了平衡,包管了每天的数据能处置惩罚完,但白天的数据处置惩罚延迟比较大。
数据积存的原因
接办这个服务以来,我不停以为是因为下载图片耗时长导致的数据处置惩罚速率慢。这周测试发现,存储图片的时间,判断图片是否存在,不存在则生存图片到本机文件夹,这两个步骤有时耗时几十毫秒,有时甚至耗时十几分钟!
难点
数据处置惩罚并行度小了不行,会导致数据处置惩罚速率慢;并行度大了也不行,会导致上述两个步骤有概率出现特别慢的环境,从而有概率严重拖慢spark任务;通过测试发现,并行度无论怎么设置,都会有概率出现特别慢的环境。
办理办法
- 通过spark.streaming.kafka.maxRatePerPartition参数和JavaStreamingContext构造函数的batchDuration参数,控制数据流量
- 开启spark推测执行,并设置合适的参数
- 通过redis分布式锁控制并行度
关键代码如下:
spark.streaming.kafka.maxRatePerPartition参数设置:- sparkConf.set("spark.streaming.kafka.maxRatePerPartition", "1");
复制代码 推测执行参数设置:- sparkConf.set("spark.speculation", "true");
- sparkConf.set("spark.speculation.interval", "5s");
- sparkConf.set("spark.speculation.quantile", "0.1");
- sparkConf.set("spark.speculation.multiplier", "6");
复制代码 batchDuration参数设置:- JavaStreamingContext jssc = new JavaStreamingContext(jsc, Durations.milliseconds(10000));
复制代码 Redis分布式锁tryLock定义:- public static boolean tryLock(String key) {
- String r = RedisClusterUtil.getJedis().set(redisKeyPre + key, "value", "NX", "PX", 10);
- if ("OK".equals(r)) {
- return true;
- } else {
- return false;
- }
- }
复制代码 Redis分布式锁tryLock使用- try {
- String key = String.valueOf(partitionId % 8);
- while (!RedisLock.tryLock(key)) {
- Thread.sleep(5);
- }
- } catch (InterruptedException e) {
- log.error("获取Redis锁异常!!!");
- }
复制代码 说明:锁超时释放,没有使用unlock手动释放
优化效果
通过以上方法,降低了判断图片文件是否存在和生存图片这两个步骤出现长耗时的概率和出现长耗时时的耗时时长。
但是依然有概率会出现特别慢的环境。如下图所示:
Spark截图1
Spark截图2
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |