我正在编写一个应用程序,试图计算每小时访问页面的用户数。我试图过滤特定的事件,按userId和事件小时时间分组,然后仅按小时分组以获取用户数。但是将KTable分组会导致过度的cpu刻录并在尝试关闭流时锁定。有更好的方法吗?
events
.groupBy(...)
.aggregate(...)
.groupBy(...);
.count();
答案 0 :(得分:1)
鉴于您在“我只想在一个小时的时间窗口内知道执行特定操作的用户数量”上方的问题的答案,我建议以下几点。
假设您有类似这样的记录:
class ActionRecord {
String actionType;
String user;
}
您可以定义一个聚合类,如下所示:
class ActionRecordAggregate {
private Set<String> users = new HashSet<>();
public void add(ActionRecord rec) {
users.add(rec.getUser());
}
public int count() {
return users.size();
}
}
然后您的流媒体应用程序可以:
.map()
)对其进行重新命名.groupByKey()
)对它们进行分组ActionRecordAggregate
所以看起来像这样:
stream()
.map((key, val) -> KeyValue.pair(val.actionType, val))
.groupByKey()
.windowedBy(TimeWindows.of(60*1000))
.aggregate(
ActionRecordAggregate::new,
(key, value, agg) -> agg.add(value),
Materialized
.<String, ActionRecordAggregate, WindowStore<Bytes, byte[]>>as("actionTypeLookup")
.withValueSerde(getSerdeForActionRecordAggregate())
);
然后,要返回事件,您可以查询状态存储:
ReadOnlyWindowStore<String, ActionRecordAggregate> store =
streams.store("actionTypeLookup", QueryableStoreTypes.windowStore());
WindowStoreIterator<ActionRecordAggregate> wIt =
store.fetch("actionTypeToGet", startTimestamp, endTimestamp);
int totalCount = 0;
while(wIt.hasNext()) {
totalCount += wIt.next().count();
}
// totalCount is the number of distinct users in your
// time interval that raised action type "actionTypeToGet"
希望这会有所帮助!