我有一个对象流,我想在其中计算该对象中某个字段的平均值,然后将该平均值保存回该对象。我想要一个5分钟的翻滚窗口,并保留1小时。我是Kafka的新手,所以我想知道这是否是解决问题的正确方法。
首先,我创建一个持久性存储:
StoreBuilder<WindowStore<String, Double>> averagesStoreSupplier =
Stores.windowStoreBuilder(
Stores.persistentWindowStore(WINDOW_STORE_NAME, Duration.ofHours(1), Duration.ofMinutes(5), true),
Serdes.String(),
Serdes.Double());
streamsBuilder.addStateStore(averagesStoreSupplier);
然后我用以下方式致电我的变压器:
otherKTable
.leftJoin(objectKTable.transformValues(new AveragingTransformerSupplier(WINDOW_STORE_NAME), WINDOW_STORE_NAME),
myValueJoiner)
.to("outputTopic")
这是我的变压器:
public class AveragingTransformerSupplier implements ValueTransformerWithKeySupplier<String, MyObject, MyObject> {
private final String stateStoreName;
public TelemetryAveragingTransformerSupplier(final String stateStoreName) {
this.stateStoreName = stateStoreName;
}
public ValueTransformerWithKey<String, MyObject, MyObject> get() {
return new ValueTransformerWithKey<>() {
private WindowStore<String, Double> averagesStore;
@Override
public void init(ProcessorContext processorContext) {
averagesStore = Try.of(() ->(WindowStore<String, Double>) processorContext.getStateStore(stateStoreName)).getOrElse((WindowStore<String, Double>)null);
}
@Override
public MyObject transform(String s, MyObject myObject) {
if (averagesStore != null) {
averagesStore.put(s, myObject.getNumber());
Instant timeFrom = Instant.ofEpochMilli(0); // beginning of time = oldest available
Instant timeTo = Instant.now();
WindowStoreIterator<Double> itr = averagesStore.fetch(s, timeFrom, timeTo);
double sum = 0.0;
int size = 0;
while(itr.hasNext()) {
KeyValue<Long, Double> next = itr.next();
size++;
sum += next.value;
}
myObject.setNumber(sum / size);
}
return myObject;
}
@Override
public void close() {
if (averagesStore != null) {
averagesStore.flush();
}
}
};
}
}
我有几个问题。 首先,我定义WindowStore的方法是否是形成翻滚窗口的正确方法?我将如何创建一个跳跃窗口?
第二,从开始到现在,我都在我的变压器内部从商店中获取所有物品。由于我将其定义为5分钟的窗口和1小时的保留时间,这是否意味着商店中的商品是5分钟的数据快照?保留在这里做什么?
我正在处理琐碎的事,但是不确定是否有更好的方法使用聚合和联接来做到这一点,即使我做得正确也是如此。另外,我还不得不将获取存储的尝试放在尝试中,因为初始化多次被调用,有时会遇到Processor has no access to StateStore
异常。
答案 0 :(得分:0)
在这种情况下,我建议使用DSL代替Processor API。 cf. https://cwiki.apache.org/confluence/display/KAFKA/Kafka+Stream+Usage+Patterns了解详情。
我有几个问题。首先,我定义WindowStore的方法是否是形成翻滚窗口的正确方法?我将如何创建一个跳跃窗口?
带窗口的商店可用于跳跃窗口或翻滚窗口-它取决于您在处理器中使用的方式,而不是如何创建商店,以及获得的窗口语义。
第二,从开始到现在,我都在我的变压器内部从商店中获取所有物品。由于我将其定义为5分钟的窗口和1小时的保留时间,这是否意味着商店中的商品是5分钟的数据快照?保留在这里做什么?
创建商店时,参数windowSize
不能按预期的方式工作。您需要使用Transformer
在put(key, value, windowStartTimestamp)
代码中手动编码开窗逻辑-atm,您正在使用使用put(key, value)
的{{1}},即当前记录时间戳记,如windowStartTimestamp -我怀疑那是您想要的。保留时间基于窗口时间戳,即旧窗口到期后将被删除。