我希望能够基于消息密钥的密钥将Kafkastream中的所有记录发送到另一个主题。 例如Kafka中的流包含名称作为键和记录作为值。我想根据记录的关键将这些记录分配到不同的主题
data:(jhon-> {jhonsRecord}),(sean-> {seansRecord}),(mary-> {marysRecord}),(jhon-> {jhonsRecord2}), 预期
下面是我现在执行此操作的方式,但是由于名称列表比较笨拙,因此速度很慢。另外,即使有一些记录,我也需要遍历整个列表。请提出修复建议
for( String name : names )
{
recordsByName.filterNot(( k, v ) -> k.equalsIgnoreCase(name)).to(name);
}
答案 0 :(得分:5)
我认为您应该使用KStream::to(final TopicNameExtractor<K, V> topicExtractor)
函数。它使您能够计算每条消息的主题名称。
示例代码:
final KStream<String, String> stream = ???;
stream.to((key, value, recordContext) -> key);
答案 1 :(得分:1)
我认为您正在寻找的是KStream#branch
。
以下未经测试,但显示了总体思路
// get a list of predicates to branch a topic on
final List<String> names = Arrays.asList("jhon", "sean", "mary");
final Predicate[] predicates = names.stream()
.map((Function<String, Predicate<String, Object>>) n -> (s, o) -> s.equals(n))
.toArray(Predicate[]::new);
// example input
final KStream<Object, Object> stream = new StreamsBuilder().stream("names");
// split the topic
KStream<String, Object>[] branches = stream.branch(predicates);
for (int i = 0; i < names.size(); i++) {
branches[i].to(names.get(i));
}
// KStream branches[0] contains all records whose keys are "jhon"
// KStream branches[1] contains all records whose keys are "sean"
...
答案 2 :(得分:1)
如果您需要为每个用户生成汇总数据,则无需为每个用户写一个单独的主题。您最好在源流上编写聚合。这样一来,您不会在每个键上出现一个主题,但仍然可以对每个用户独立运行操作。
Serde<UserRecord> recordSerde = ...
KStream<Stream, UserAggregate> aggregateByName = recordsByName
.groupByKey(Grouped.with(Serdes.String(), recordSerde))
.aggregate(...)
.toStream()
有关详情,请参见https://docs.confluent.io/current/streams/developer-guide/dsl-api.html#aggregating
此方法将扩展到数百万个用户,而您目前无法通过每个用户一个主题的方法来实现这一目标。