我有一个流管道,该流管道消耗了流源(Kafka),并将写入CloudSQL数据库。目标是使用过去一小时内收到的记录的键/值总和来实时更新CloudSQL数据库。
例如在最近一小时内,收到3个记录为KV <001,3>
,<001,4>
,<001,2>
的记录,数据库应包含记录001, 9
。超过一个小时的记录不包括在内。
我当前的解决方法是在KafkaIO.read
之后将SlidingWindow转换为GroupByKey:
.apply(Window.into(SlidingWindows
.of(Duration.standardSeconds(3600))
.every(Duration.standardSeconds(20)))
).apply(GroupByKey.create())
后跟一个对每个键求和的ParDo,然后更新SQL数据库。
结果是我的CloudSQL数据库每20秒更新一次最新一小时的每个键的汇总,从而满足功能要求。问题在于这会导致CloudSQL大量更新:大多数KV输出与先前的窗口相同,因此每20s的每个窗口都会触发一个小时的交易(约500k)。
仅当消耗具有该键的记录时才触发每个KV输出,或者避免输出自上一个窗口以来未更改的KV,才有意义。或者,在CloudSQL插入之前进行某种过滤,以吸收所有内容,并且仅输出已更改的KV。这可能还是有其他解决方案?
答案 0 :(得分:0)
一种可能的探索方法是在滑动窗口聚合的下游使用State API。
然而,流入此元素的元素是无序的,因此您不能仅存储元素并将其与传入值进行比较。
用于State API DoFn的窗口的大小将是任意的,它越大,不需要的upsert越多。缺点是,窗口越大,您将在ValueState中保留的键越多,可能不再需要这些键。避免使用全局窗口,因为这将需要您构建GC函数,因为该窗口永不过期,并且密钥空间将永远增长。