您的位置:首页 > 其它

第116课: Spark Streaming性能优化:如何在毫秒内处理处理大吞吐量的和数据波动比较大 的程序

2016-06-03 21:14 916 查看
第116课:  Spark Streaming性能优化:如何在毫秒内处理处理大吞吐量的和数据波动比较大 的程序

1 大吞吐量和数据波动比较大的程序
2 Spark streaming中的解决方案

-数据规模非常大,数据的处理会大于batch interval
-数据波动非常大,峰值非常大,让人提心吊胆的地方
办法:加硬件: 内存、cpu cores 但要花公司的钱
      限流:log日志观察;如双11,限流会损失交易
      增加batch的时间,但波峰之外的时间不需要
上述办法都不理想。

唯一的有效的效果显著的办法,不要等待!!什么意思?就是无论batch duration数据大小和处理的复杂度,都会立即完
成当前batch的处理,然后立即去处理下一个batch的任务!!

怎么做?此时既要完成业务计算,又要达到毫秒级别的延迟!
一个可行的办法是:Spark Streaming的业务处理逻辑放在线程池中!!!而绝妙的精彩之处在于Spark Streaming执行的时候业务
逻辑就是以task的方式放在线程池中的。所有可以最大化的复用线程,从而最佳化的使用硬件资源!

模拟代码如下:

Dstream.foreachRDD{rdd =>
       rdd.foreachPartition(splite=>{
           //业务处理逻辑,如果直接处理是阻塞式的,
           //但是此时我们可以使用线程池去处理业务逻辑(此处的线程池是你自己定义的),此时任务肯定是毫秒级别完成的
        
           此时唯一要注意的线程数受限于物理硬件,所以需要根据实际情况设定线程池中并发task的个数,例如不能超过200个,
            如果超过了,新的task就采用阻塞式操作。此时其他的线程在并行运行并且不断地完成task,就会有新的 可用线程来进行
 异步操作

但有一个悲剧的结果,如果executor崩溃了就会导致数据丢失了,但这个是一个不太常见的场景。其他的情况下 这个方案能很好的使用。

})

}

可能有人担心一个问题:数据是一个Partition、一个Partition的交给线程池去处理,会不会影响作业或数据的完整性?不会的,这个跟阻塞式的存储没有区别。阻塞式的存储方式也是交给Executor的线程池的线程去处理的。所以,不会有数据的不成功、数据的切割等问题,作为Task,该属于哪个Job就属于哪个Job,彼此之间没有任何影响,这是非常强有力的解决方式,处理立即可以返回,处理的时间就是从线程池中拉动一条线程就返回的时间,延迟非常低。不过如果数据一直扔进去,这个BatchDuration没处理完,下一个Batch Duration又来了,这样要用很多线程,这个时候必须根据分配的Cores的个数设定一个线程池,如果超过200个并行的线程就做出改变,超过200个就采取阻塞式操作,其他的线程在并行运行并且不断的完成Task,就会有新的可用线程来进行异步操作。
shuffle有时候涉及多个partition,每个partition的处理时间不一样,又是异步处理,是否有问题?不会有任何问题,异步是在Spark Streaming,走的是Spark调度模型,对Spark Core没什么影响。从Job的角度讲,后面的Stage依赖前面的Stage,Stage内部有一系列Task,把具体的partition交给线程处理,从Stage的角度,前面处理不完,后面就无法进行,foreachRDD方式是直接对RDD进行操作,一般业务逻辑都集中在这里,其他的操作一般都不是耗时的操作,可能大家担心前面的Stage没执行完,Task又是异步的,后面是否还是要等,如果要这么做确实这样的,但实际情况是前面的Stage不做耗时的计算,把耗时的计算放到RDD中,直接对RDD进行操作,Stage内部是并行,外部是串行的。Task交给Executor中的线程池的线程去运行,Executor中的线程池的线程运行Task的时候,当Task的代码处理partition时,又开辟了一条新的线程,业务逻辑的线程是开发者自己定义的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: