Spark Streaming 流计算优化记录(2)-不同时间片数据流的Join

1. 不同时间片数据流的Join

         初体验之后, 看了一下Spark WebUi 的日志, 发现由于Spark Streaming需要每秒跑一次, 以实时计算数据, 所以程序不得不每秒都读一次HDFS去获取数据进行inner join.

         本来SparkStreaming会对其进行处理的数据进行缓存, 以减少IO和提高计算速度的, 但由于现在我们的场景是要把每秒都有新数据的数据流与大约2周才更新一次HDFS数据进行inner join, 也就是两个数据流所要缓存的数据的时间区间是不一样的, 来自Kafka的数据流顶多缓存10秒就够了, 但来自HDFS的数据由于更新很慢, 则至少需要缓存一周. 但是原生的Spark Streaming只能支持时间间隔区间与缓存区间一致的数据流进行join, 这将导致不得不每秒或者每几秒都要去HDFS读取3G多数据, 进而对程序处理的实时性造成很大影响. (当然

         “甘点得啊!”, 因此我们不得不扩展DStream(确切的说, 是扩展FileInputDStream, 自己写了一个LatestFileInputDStream用于处理不同时间片的数据流的整合.

         SparkStreaming会每隔一段duration或remember time的时间做一次缓存或checkpoint, 为了解决不同时间片的数据流的缓存和checkpoint间隔时间不一致的问题, 我们需要在扩展FileInputDStream的LatestFileInputDStream中重写缓存和checkpoint的逻辑, 使它能够没两周从HDFS中读一次最新的数据, 然后和每秒从Kafka不断涌入的数据进行Inner Join.

         SparkStreaming的checkpoing逻辑大部分封装在DStreamCheckpointData类中:


         我们需要重写和扩展DStreamCheckpointData的相关方法, 以避免SparkStreaming按秒进行缓存.

        

DStream中的generatedRDDs也会保存DStream过去所解析出来的RDD.


但DStream对此并没有提供相关的扩展机制, 我们也不希望对原生Spark的扩展太过于侵入性, 并没对generatedRDDs的机制进行修改, 幸好的是它保存的只是RDD的引用, 并不是计算出来的数据, 否则每秒保存3G数据的话再多的内存也会被撑爆.


         虽然我们只扩展的checkpoint机制, 而没有动DStream. generatedRDDs的缓存机制, 但我们也实现了自己的定时缓存机制, 避免受SparkDStream的秒级缓存影响. 最终得到了我们自己的可支持不同时间间隔的LatestFileInputDStream.


用LatestFileInputDStream取代原生Spark的FileInputDStream后, 速度大大改观, 起码不用在屏幕旁等好几小时了, 妈妈可以喊我回家吃饭了. 
展开阅读全文

没有更多推荐了,返回首页