在Kafka流中加入外键

时间:2018-11-12 11:04:25

标签: apache-kafka apache-kafka-streams

让我们说我有三个Kafka主题,其中填充了代表不同聚合中发生的业务事件的事件(事件源应用程序)。这些事件允许构建具有以下属性的聚合:

  • 用户:usedId,名称
  • 应用程序的模块:moduleId,名称
  • 用户对应用程序模块的授权:GrantId,userId,moduleId,范围

现在,我想创建一个包含用户和产品名称(而不是ID)的所有资助的流。 我想这样做:

  1. 通过按userId将事件分组为用户创建KTable。 KTable以userId为键。没关系。
  2. 通过按productId分组事件为产品创建KTable。 KTable以productId为键。没关系。
  3. 从Grants流创建一个流,并加入两个KTable。 不好问题是联接似乎只能在主键上进行。但是流中的密钥是Grant的技术标识符,而user和product表的密钥不是(它们与Grant无关)。

那么如何进行?

2 个答案:

答案 0 :(得分:3)

好吧,Kafka Streams目前不直接支持外键联接。
有一个开放的KIP:https://issues.apache.org/jira/browse/KAFKA-3705

目前,可以找到一种解决方法来解决此问题。您可以使用 KStream-KTable Join

首先将 User 流和 Module 流聚合到具有事件汇总集合的各个KTable中。

prodA1

现在选择模块ID作为 Grants 流中的键。

KTable<String,Object> UserTable = userStream.groupBy(<UserId>).aggregate(<... build collection/latest event>) ;
KTable<String,Object> ModuleTable = moduleStream.groupBy(<ModuleId>).aggregate(<... build collection/latest event>);

它将密钥更改为 moduleId 。现在,您可以使用 ModuleTable 执行流表联接。它将右侧的所有匹配记录连接到左侧的键中。结果流将具有 Grant Module 数据到一个流中,并以 ModuleId 作为键。

KStream<String,Object> grantRekeyedStream = grantStream.selectKey(<moduleId>);

下一步是加入 userTable 。因此,您需要使用 userId 再次刷新 grantModuleTable 的密钥。

KStream<String,Object> grantModuleStream = grantRekeyedStream.join(moduleTable);

现在 grantModuleRekeyedStream 可以与 userTable KStream-KTable Join

一起加入
KStream<String,Object> grantModuleRekeyedStream = grantModuleTable.selectKey(<Select UserId>);

Stream之上将用户ID作为密钥,并包含该用户的所有授权和模块详细信息。

答案 1 :(得分:2)

此功能是released的一部分,是Kafka Streams 2.4.0的一部分。

这是使用此功能的official tutorial