在Spark Streaming程序中,若需要使用有状态的流来统计一些累积性的指标,比如各个商品的PV。简单的代码描述如下,使用mapWithState()算子:

val productPvStream = stream.mapPartitions(records => {
var result = new ListBuffer[(String, Int)]
for (record <- records) {
result += Tuple2(record.key(), 1)
}
result.iterator
}).reduceByKey(_ + _).mapWithState(
StateSpec.function((productId: String, pv: Option[Int], state: State[Int]) => {
val sum = pv.getOrElse(0) + state.getOption().getOrElse(0)
state.update(sum)
(productId, sum)
})).stateSnapshots()

PV并不是一直累加的,而是每天归零,重新统计数据。要达到在凌晨0点清除状态的目的,有以下两种方法。

编写脚本重启Streaming程序:

用crontab、Azkaban等在凌晨0点调度执行下面的Shell脚本:

stream_app_name='com.xyz.streaming.MallForwardStreaming'
cnt=`ps aux | grep SparkSubmit | grep ${stream_app_name} | wc -l` if [ ${cnt} -eq 1 ]; then
pid=`ps aux | grep SparkSubmit | grep ${stream_app_name} | awk '{print $2}'`
kill -9 ${pid}
sleep 20
cnt=`ps aux | grep SparkSubmit | grep ${stream_app_name} | wc -l`
if [ ${cnt} -eq 0 ]; then
nohup sh /path/to/streaming/bin/mall_forward.sh > /path/to/streaming/logs/mall_forward.log 2>&1
fi
fi

这种方式最简单,也不需要对程序本身做任何改动。但随着同时运行的Streaming任务越来越多,就会显得越来越累赘了。

给StreamingContext设置超时

在程序启动之前,先计算出当前时间点距离第二天凌晨0点的毫秒数:

def msTillTomorrow = {
val now = new Date()
val tomorrow = new Date(now.getYear, now.getMonth, now.getDate + 1)
tomorrow.getTime - now.getTime
}

然后将Streaming程序的主要逻辑写在while(true)循环中,并且不像平常一样调用StreamingContext.awaitTermination()方法,而改用awaitTerminationOrTimeout()方法,即:

while (true) {
val ssc = new StreamingContext(sc, Seconds(BATCH_INTERVAL))
ssc.checkpoint(CHECKPOINT_DIR) // ...处理逻辑... ssc.start()
ssc.awaitTerminationOrTimeout(msTillTomorrow)
ssc.stop(false, true)
Thread.sleep(BATCH_INTERVAL * 1000)
}

在经过msTillTomorrow毫秒之后,StreamingContext就会超时,再调用其stop()方法(注意两个参数,stopSparkContext表示是否停止关联的SparkContext,stopGracefully表示是否优雅停止),就可以停止并重启StreamingContext。

以上两种方法都是仍然采用Spark Streaming的机制进行状态计算的。如果其他条件允许的话,还可以抛弃mapWithState(),直接借助外部存储自己维护状态。比如将Redis的Key设计为product_pv:[product_id]:[date],然后在Spark Streaming的每个批次中使用incrby指令,就能方便地统计PV了,不必考虑定时的问题。

转载自微信公众号:大数据技术与架构

周期性清除Spark Streaming流状态的方法的更多相关文章

  1. Dream_Spark-----Spark 定制版:005~贯通Spark Streaming流计算框架的运行源码

    Spark 定制版:005~贯通Spark Streaming流计算框架的运行源码   本讲内容: a. 在线动态计算分类最热门商品案例回顾与演示 b. 基于案例贯通Spark Streaming的运 ...

  2. Spark Streaming流式处理

    Spark Streaming介绍 Spark Streaming概述 Spark Streaming makes it easy to build scalable fault-tolerant s ...

  3. Spark之 Spark Streaming流式处理

    SparkStreaming Spark Streaming类似于Apache Storm,用于流式数据的处理.Spark Streaming有高吞吐量和容错能力强等特点.Spark Streamin ...

  4. 5.Spark Streaming流计算框架的运行流程源码分析2

    1 spark streaming 程序代码实例 代码如下: object OnlineTheTop3ItemForEachCategory2DB { def main(args: Array[Str ...

  5. 大数据开发实战:Spark Streaming流计算开发

    1.背景介绍 Storm以及离线数据平台的MapReduce和Hive构成了Hadoop生态对实时和离线数据处理的一套完整处理解决方案.除了此套解决方案之外,还有一种非常流行的而且完整的离线和 实时数 ...

  6. Spark Streaming带状态更新

    带状态的更新是使用的updateStateByKey方法,里面传入一个函数,函数要自己写,注意需要设置checkpoint import org.apache.spark.streaming.kafk ...

  7. 贯通Spark Streaming流计算框架的运行源码

    本章节内容: 一.在线动态计算分类最热门商品案例回顾 二.基于案例贯通Spark Streaming的运行源码 先看代码(源码场景:用户.用户的商品.商品的点击量排名,按商品.其点击量排名前三): p ...

  8. 基于案例贯通 Spark Streaming 流计算框架的运行源码

    本期内容 : Spark Streaming+Spark SQL案例展示 基于案例贯穿Spark Streaming的运行源码 一. 案例代码阐述 : 在线动态计算电商中不同类别中最热门的商品排名,例 ...

  9. spark streaming流式计算---监听器

    随着对spark的了解,有时会觉得spark就像一个宝盒一样时不时会出现一些难以置信的新功能.每一个新功能被挖掘,就可以使开发过程变得更加便利一点.甚至使很多不可能完成或者完成起来比较复杂的操作,变成 ...

随机推荐

  1. Spring项目出现--Error:java: Compilation failed: internal java compiler error

    错误现象 使用Idea导入新项目或升级idea或新建项目时会出现以下异常信息: Error:java: Compilation failed: internal java compiler error ...

  2. 模板匹配入门实践:opencv+python识别PDB板

    任务要求: 基于模板匹配算法识别PCB板型号 使用工具: Python3.OpenCV 使用模板匹配算法,模板匹配是一种最原始.最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识 ...

  3. 【JDBC核心】实现 CRUD 操作

    实现 CRUD 操作 操作和访问数据库 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果.其实一个数据库连接就是一个 Socket 连接. java.sql 包中有 ...

  4. Flutter 基础组件:图片和Icon

    前言 Flutter中,可以通过Image组件来加载并显示图片,Image的数据源可以是asset.文件.内存以及网络. ImageProvider 是一个抽象类,主要定义了图片数据获取的接口load ...

  5. appium识别工具介绍

  6. 通过show profile分析sql语句

    set profling=1; select count(*) from xuehao; show profiles; show profile for query 1; mysql> set ...

  7. update 表名 set 某列名=now() where user in('user1','user2','user3');

    update 表名  set 某列名=now() where user in('user1','user2','user3');

  8. kubernets之namespace

    一 命名空间的介绍以及作用 1  概念 为了方便不同部门之间对kubernets集群的使用,并且对其进行有效的隔离,kubernets提供了一种资源隔离手段,通过将各种不同资源分组到 一个区域,并且统 ...

  9. APP测试之Monkey测试

    一.简介 1.什么是Monkey测试? Monkey testing,也有人叫做搞怪测试.就是用一些稀奇古怪的操作方式去测试被测试系统,以测试系统的稳定性.Monkeytest,一般指这样的测试活动, ...

  10. BAPI_SALESORDER_CREATEFROMDAT2 条件 定价元素

    用函数 BAPI_SALESORDER_CREATEFROMDAT2创建SO的时候,遇见个问题,就是如图: 会多出来一个类型,搞了半天,发现是一个函数里的一个参数,我没有设置: LOGIC_SWITC ...