如何使用kafka流将n个最新值保留在kafka主题中

时间:2019-05-06 09:42:35

标签: scala apache-kafka apache-kafka-streams

假设我使用的是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还是至少不使用可变映射。

1 个答案:

答案 0 :(得分:3)

  

所以我需要类似KTable或GlobalKTable的东西,但它们仅保留一个值。

继续使用KTable(或GlobalKTable),但使用结构化值和/或集合作为“值”。在Kafka中,没有什么强制要求您将消息值限制为仅原始数据类型(例如IntegerString)。

思考:KStream<UserId, List<ClickEvent>>。在这里,每个消息都属于一个特定的用户(由密钥UserId标识),并且每个消息都有与该用户关联的零个,一个或多个ClickEvent的列表。这种“有效”的方式,您只需要具有要使用的数据类型的适当的SERDES(序列化器/反序列化器)即可。

例如,https://github.com/confluentinc/kafka-streams-examplesdirect link to example for v5.2.1,用于Apache Kafka v2.2)中的CustomStreamTableJoin示例使用Pair类将元组存储在Kafka的消息中值,并附带PairSerde。正如您在自己的用例中提到的那样,可以执行(并且由开发人员完成)存储值的集合(如List<ClickEvent>)。

  

我需要使用kafka流为kafka主题中的键保留一些最新值。 [...]   我想出了一种可行的方法:创建流和可变的Map,[...]

您不需要使用Map。该密钥已经在Kafka消息中可用,因此您只需要一个类似List的数据类型作为消息值。

  

或至少没有可变的地图。

除非有特殊原因,否则您不需要(也不应)使用可变数据结构,我认为您的用例中没有。当处理一条新消息并将相应的输出存储在KTable中时,该键在表中存储的任何内容都将被覆盖-因此使用不可变的数据结构作为消息值是完全可以的。