Kafka Streams 技术指南

  • 理论知识篇

本文所描述的Kafka是指Apache Kafka,针对Kafka的基础知识,如Topic,Partition以及其依赖的Apache Zookeeper不做过多描述。

Kafka Streams是Kafka提供的一个用于构建流式处理程序的Java库,它与Spark Streaming、Apache Flink 等流式处理框架不同,是一个仅依赖与Kafka的Java库,而不是一个流式处理框架。除了Kafka之外,Kafka Streams不需要额外的流式处理集群,提供了轻量级、易用的流式处理API。

  1. 流处理与批处理

流处理(Streaming Processing)是指处理无限数据集的数据处理,而流处理是与批处理(Batch Processing)相对应的。这里的无限数据,是指数据是源源不断的。这并不意味着批处理不能处理这种无限数据集,只是通常情况下,它更擅长处理有限数据集。以下分别是流处理和批处理的流程示意图:

 

  1. 消息语义一致性

流处理通常是低延时的,每来一条消息计算一次结果,但由于它处理的大多是无界数据,因此在流处理中,计算结果会不断地接近精确结果。批处理则正好相反,批处理能提供准确的计算结果,但往往延时很高。如果计算结果不准确,流处理是无法完全替代批处理的。目前实现流处理正确性的基础是精确一次处理语义(Exactly Once Semantics,EOS)。常用的消息语义一致性保障有以下三种:

  1. 至多一次(At most once)语义:消息或事件对应用状态的影响最多只有一次。
  2. 至少一次(At least once)语义:消息或事件对应用状态的影响最少一次。
  3. 精确一次(Exactly once)语义:消息或事件对应用状态的影响有且只有一次。

Kafka 借鉴了分布式系统中两阶段提交(2-Phase Commit,2PC)的思想,在 Kafka 内部实现了基于 2PC 的事务机制。对于 Kafka Streams 而言,它天然支持端到端的 EOS,因为它本来就是和 Kafka 紧密相连的。下图展示了一个典型的 Kafka Streams 应用的执行逻辑:

通常情况下,一个 Kafka Streams 需要执行 5 个步骤:读取最新处理的消息位移;读取消息数据;执行处理逻辑;将处理结果写回到 Kafka;保存位置信息。这五步的执行必须是原子性的,否则无法实现精确一次处理语义。在设计上,Kafka Streams 在底层大量使用 Kafka 事务机制和幂等性 Producer 来实现多分区的原子性写入,又因为它只能读写 Kafka,因此 Kafka Streams 很容易地就实现了端到端的 EOS。

Kafka Streams 最大的特色是它不是一个具备完整功能的框架,如Flink中的资源管理器,但可以用它来构建高伸缩性、高弹性、高容错性的分布式应用以及微服务。使用 Kafka Streams API 构建的应用就是一个普通的 Java 应用程序。

  1. 分布式集群部署

分布式协调方面,Kafka Streams 应用依赖于 Kafka 集群提供的协调功能,来提供高容错性和高伸缩性。Kafka Streams 应用底层使用了消费者组机制来实现任意的流处理扩缩容。应用的每个实例或节点,本质上都是相同消费者组下的独立消费者,彼此互不影响。它们之间的协调工作,由 Kafka 集群 Broker 上对应的协调者组件来完成。当有实例增加或退出时,协调者自动感知并重新分配负载。下图展示了每个 Kafka Streams 实例内部的构造,每个实例都由一个消费者实例、特定的流处理逻辑,以及一个生产者实例组成,而这些实例中的消费者实例,共同构成了一个消费者组,如下图:

  1. 事件时间和时间窗口

时间在流处理领域内是非常关键的:一方面,它是决定流处理应用能否实现正确性的前提;另一方面,流处理中时间窗口等操作依赖于时间概念才能正常工作。常见的有两类:事件发生时间(Event Time)和事件处理时间(Processing Time)。理想情况下,我们希望这两个时间相等,即事件一旦发生就马上被处理,但在实际场景中,这是不可能的:

虚线表示理想状态,即Event Time等于Processing Time,而粉色的曲线表征的是真实情况,即 Processing Time 落后于 Event Time,而且落后的程度(Lag)不断变化。如果流处理应用要实现结果的正确性,就必须要使用基于Event Time的时间窗口,而不能使用基于Processing Time的时间窗口。时间窗口机制则是将流数据沿着时间线切分的过程。常见的时间窗口包括:固定时间窗口(Fixed Windows)、滑动时间窗口(Sliding Windows)和会话窗口(Session Windows)。固定时间窗口又分滚动和跳跃时间窗口。Kafka Streams 同时支持这几种时间窗口。下图为他们直接的区别:

 

  • 开发实战篇
  1. Streams DSL 和 Processor API

Kafka Streams应用其实就是指调用了Streams API的Java应用程序。在Kafka Streams中,流处理逻辑是用拓扑来表示的,一个拓扑就是一个有向无环图(DAG),它由多个处理节点(Node)和连接节点的多条边组成,如下图所示:

图中的节点称为Processor或操作算子,它封装了具体的事件处理逻辑。Kafka Streams开放了两大类API去定义 Processor 逻辑。一类DSL,声明式的函数式 API,例如:

从所有 Movie 事件中过滤出Title是“动画片”的事件,这就是 DSL 声明式 API 的实现方式。另一类是Processor API。不论是用哪组 API 实现,所有流处理应用本质上都可以分为两类:有状态的应用和无状态的应用。有状态的应用指的是应用中使用了类似于连接、聚合或时间窗口(Window)的API。

无论哪种API,最基本的两个对象都是流(KStream)和表(KTable),下图为最基本的Demo代码:

在流处理领域,流和表是有机统一的:流在时间维度上聚合之后形成表,表在时间维度上不断更新形成流,这就是所谓的流表二元性(Duality of Streams and Tables)。流表二元性在流处理领域内的应用是 Kafka 框架赖以成功的重要原因之一。下面这张图展示了表转换成流,流再转换成表的全过程。

从这个过程中可以看出,流可以看作是表的变更事件日志(Changelog)。流转换成表的过程可以说是这个过程的逆过程:我们为流中的每条事件打一个快照(Snapshot),就形成了表。

  1. Windows API

前面说过,Kafka Streams支持3类时间窗口,前两类窗口通过

方法来实现,会话窗口通过

来实现。假设在刚才的Demo中,我们想每一分钟统计一次单词计数,那么需要在调用count之前增加下面这行代码:

同时,你还需要修改 counts 的类型:

因为引入了时间窗口,所以,事件的Key也必须要携带时间窗口的信息。

 

  • 领域应用篇

Kafka Streams在金融领域的应用。为了降低金融领域内的获客成本,其中一方面就是做好客户细分,实现客户生命周期内价值的最大化。为了实现这一目的通过对每个人日常生活方方面面的大数据信息可判断客户最真实的想法。将这些数据汇总在一起,我们就能完整地构造出客户的画像,从而给用户打标签(Tag)。在网络上,能够标识用户身份信息的常见ID有 5种。身份证号手机号设备 ID应用注册账号Cookie在构建用户画像系统时,我们会从多个数据源上源源不断地收集各种个人用户数据,这时需要一种技术事实去关联各个 (如各设备之间)ID映射。

从实时计算或流处理的角度来看,实时 ID Mapping 能够转换成一个流-表连接问题(Stream-Table Join),即我们实时地将一个流和一个表进行连接。消息流中的每个事件或每条消息包含的是一个未知用户的某种信息,它可以是用户在页面的访问记录数据,也可以是用户的购买行为数据。这些消息中可能会包含我们刚才提到的若干种 ID信息。连接的另一方表保存的是用户所有的ID信息,随着连接的不断深入,表中保存的ID品类会越来越丰富,也就是说,流中的数据会被不断地补充进表中,最终实现对用户所有 ID 的映射以下为主要的代码示例

 

最主要是buildTopology函数,先构造了 StreamsBuilder 对象实例,之后读取配置文件,获取了要读写的所有 Kafka Topic。其中的4个topic作用如下:streamTopic:保存用户登录 App 后发生的各种行为数据,格式是 IDMapping 对象的 JSON 串。rekeyedTopic:这个Topic是一个中间Topic,它将 streamTopic 中的手机号提取出来作为消息的 Key,同时维持消息体不变。tableTopic:保存用户注册 App 时填写的手机号。我们要使用这个主题构造连接时要用到的表数据。outputTopic:保存连接后的输出信息,即映射了用户所有ID数据的IDMapping对象,将其转换成 JSON 后输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值