本期内容:
1.SparkStreaming中的Transforamtions
2.SparkStreaming中的状态管理
一.DStream就是一个RDD之上的一个抽象,DStream和时间结合起来就不断的触发产生RDD的实例,可以说我们对Dstream的操作就初步定义了对RDD的操作,只不过需要时间的间隔也就是internalbatch去激活这个模板,生成具体的RDD的实例和具体的job.
二.我们鼓励Repartition,更多的是把更多的partition变成更少的partition,进行流的碎片的整理,我们不太鼓励把更少的partition变成更多的partion,因为会牵扯shuffle。
三.DStream是离散流,离散流就没状态,除了计算每个时间间隔产生一个job,我们还有必要计算过去十分钟或者半个小时,所以这个时候我们需要维护这个状态。后台spark提供了专门维护这个状态的函数updateStateByKey(func),即基于key,我们可以进行多个状态的维护。因为你可以把每一个时间间隔都做为一个状态,例如每一秒钟做为一个状态,我算下过去十分钟或者半个小时。值的更新就是通过传进来的func函数。
四.Transform
transform(func) |
Return a new DStream by applying a RDD-to-RDD function to every RDD of the source DStream. This can be used to do arbitrary RDD operations on the DStream. 编程的逻辑是作用于RDD |
Transform操作,允许任意的RDD和RDD的操作被应用在DStream上。他可以使这些RDD不容易暴露在DstreamAPI中。比如让两个batch产生join操作而不暴露在DstreamAPi中,然后你可以很容易的使用transform来做这。这将是非常有作用的,例如,能够将实时数据清理通过将输入的数据流和预先计算的垃圾信息过滤掉。
五.UpdateByKey
updateStateByKey(func) |
Return a new "state" DStream where the state for each key is updated by applying the given function on the previous state of the key and the new values for the key. This can be used to maintain arbitrary state data for each key. |
UpdaeStateByKey的操作,允许你维护任意的不断通过新的信息来更新的状态。使用这个函数你必须遵守两个步骤
1.定义一个状态:这个状态可以是任意的数据类型
2.定义一个状态更新函数:怎么样去使用从一个数据流中产生的旧的状态和新的状态来更新出一个状态。
六.forecachRDD(func)
foreachRDD(func) |
The most generic output operator that applies a function, func, to each RDD generated from the stream. This function should push the data in each RDD to an external system, such as saving the RDD to files, or writing it over the network to a database. Note that the function func is executed in the driver process running the streaming application, and will usually have RDD actions in it that will force the computation of the streaming RDDs. |
mapWithState将流式的状态管理性能提高10倍以上
foreachRDD(func)中的函数func是作用于最后一个RDD,也就是结果RDD,如果RDD没有数据,就不需要进行操作,foreachRDD()可以将数据写在Redis/Hbase/数据库/具体文件中,foreachRDD是在Driver程序中执行的,func就是action。
七.updateStateByKey
val cogroupedRDD = parentRDD.cogroup(prevStateRDD, partitioner) val stateRDD = cogroupedRDD.mapPartitions(finalFunc, preservePartitioning) Some(stateRDD)
cogroup是性能的瓶颈,所有的老数据,过去的数据都要进行cogroup操作,即使新的数据pairedRDD只有一条记录,也要把所有的老记录都要进行cogroup操作。这时相当耗时的。理论上讲,只应对这条记录对应的key和历史的一批数据中对应的这个key进行更新操作就行了,而它更新全部的,99%的时间都是浪费和消耗。性能非常低。也会产生shuffle。而下面的MapWithState则只更新你必须要更新的,所以极大提升了性能。
MapWithState只需要更新你必须更新的,没有必要更新所有的记录,官方宣传这个api会把流式的状态管理性能提升10倍以上。