我正在调查Spark Streaming作为我正在构建的反欺诈服务的解决方案,但我正在努力弄清楚如何将其应用于我的用例。用例是:流式传输来自用户会话的数据,并在为该用户收集数据10秒后计算给定用户的风险分数。我打算使用2秒的批处理间隔时间,但需要使用整个10秒窗口中的数据。起初,updateStateByKey()似乎是完美的解决方案,因为我可以使用系统收集的事件构建UserRisk对象。麻烦的是,我不知道如何告诉Spark在10秒过后停止更新用户,因为在10秒标记时,我对UserRisk对象运行推理引擎,并保持结果。另一种方法是窗口转换。窗口转换的问题是我必须手动重复数据删除,这可能是浪费。有关如何告诉updateStateByKey在一段时间过后停止减少某个键的任何建议?
答案 0 :(得分:0)
如果您不想使用窗口,可以将批处理间隔减少到1秒,然后在updateStateByKey中更新增量计数器,并在达到10时绕过更新功能。
myDstreamByKey.updateStateByKey( (newValues: Seq[Row], runningState: Option[(UserRisk, Int)]) => {
if(runningState.get._2 < 10){
Some(( updateUserRisk(runningState.get._1, newValues), runningState.get._2 + 1) )
}else{
runningState
}
} )
为了简单起见,我认为State始终是Some,但你必须根据你的业务逻辑处理它,我不知道。
在我的示例中,Row是一个伪造的案例类,代表您的原始数据,而UserRisk是累积状态。 updateUserRisk函数包含更新UserRisk的业务逻辑
答案 1 :(得分:0)
根据您的情况,您可以尝试 reduceByKeyAndWindow Dstream功能,它将满足您的要求
以下是java中的示例代码
JavaPairDStream<String, Integer> counts = pairs.reduceByKeyAndWindow(
new Function2<Integer, Integer, Integer>() {
public Integer call(Integer i1, Integer i2) {
return i1 + i2;
}
}, new Function2<Integer, Integer, Integer>() {
public Integer call(Integer i1, Integer i2) {
return i1 - i2;
}
}, new Duration(60 * 1000), new Duration(2 * 1000));
一些重要的链接
http://spark.apache.org/docs/latest/streaming-programming-guide.html#window-operations