假设我使用的是kafka流(kafka-streams-scala库,版本2.2.0)。
我需要使用kafka流为kafka主题中的键保留一些最新值。我用它来丰富另一个流。所以我需要像KTable或GlobalKTable这样的东西,但是它们仅保留一个值。
我想出了一种可行的方法:创建流和可变Map,然后使用stream.foreach
跟踪每个键的N个最近值。
val stream: KStream[String, GenericRecord] = builder.stream[String, GenericRecord]("topicName")
val map = scala.collection.mutable.Map[String, List[MyObject]]
stream.foreach((k, v) => {
//update map
})
我的问题是,是否有更好的方法来实现这一目标-使用流API还是至少不使用可变映射。
答案 0 :(得分:3)
所以我需要类似KTable或GlobalKTable的东西,但它们仅保留一个值。
继续使用KTable
(或GlobalKTable
),但使用结构化值和/或集合作为“值”。在Kafka中,没有什么强制要求您将消息值限制为仅原始数据类型(例如Integer
或String
)。
思考:KStream<UserId, List<ClickEvent>>
。在这里,每个消息都属于一个特定的用户(由密钥UserId
标识),并且每个消息都有与该用户关联的零个,一个或多个ClickEvent
的列表。这种“有效”的方式,您只需要具有要使用的数据类型的适当的SERDES(序列化器/反序列化器)即可。
例如,https://github.com/confluentinc/kafka-streams-examples(direct link to example for v5.2.1,用于Apache Kafka v2.2)中的CustomStreamTableJoin
示例使用Pair
类将元组存储在Kafka的消息中值,并附带PairSerde
。正如您在自己的用例中提到的那样,可以执行(并且由开发人员完成)存储值的集合(如List<ClickEvent>
)。
我需要使用kafka流为kafka主题中的键保留一些最新值。 [...] 我想出了一种可行的方法:创建流和可变的Map,[...]
您不需要使用Map
。该密钥已经在Kafka消息中可用,因此您只需要一个类似List的数据类型作为消息值。
或至少没有可变的地图。
除非有特殊原因,否则您不需要(也不应)使用可变数据结构,我认为您的用例中没有。当处理一条新消息并将相应的输出存储在KTable
中时,该键在表中存储的任何内容都将被覆盖-因此使用不可变的数据结构作为消息值是完全可以的。