一、Kafka的名字是怎么来的

Jay Kreps(工作于LinkedIn,Kafka创始人之一):我想既然Kafka是为了写数据而产生的,那么用作家的名字来命名会显得更有意义。我在大学时期上过很多文学课程,很喜欢Franz Kafka。况且,对于开源项目来说,这个名字很酷。不过,名字和应用本身基本没有太多联系。
——《Kafka权威指南》P13

二、Kafka和Scala、Java是什么关系?

Kafka是使用Java开发的应用程序。
——《Kafka权威指南》P14
截至本书写作时,Kafka的版本是0.9.0.1,对应的Scala版本是2.11.0。
——《Kafka权威指南》P17

提到Kafka运行环境,总会让安装Java。提到Kafka版本,总会带上Scala。这到底是什么关系呢?

1、Kafka是由Scala和Java混合编写,最终编译成字节码运行在JVM上。

Scala类似于python在机器学习上的用法,封装的层次比较高,使用起来很方便,函数式编程写法类似Java8的Stream。Scala和Java可以混合编写,生成JVM字节码,这样就能够运行在JRE环境下了,也就是为什么编译的时候需要Scalac和Javac,运行的时候需要JRE的原因。

  • 官网提到了这两个编译器

We build and test Apache Kafka with Java 8, 11 and 14. We set the release parameter in javac and scalac to 8 to ensure the generated binaries are compatible with Java 8 or higher (independently of the Java version used for compilation).
—— github:apache / kafka

  • github的代码统计是Java,说明大部分是Java代码
    image.png

  • Scala的定义是

Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。
Scala 运行在Java虚拟机上,并兼容现有的Java程序。
Scala 源代码被编译成Java字节码,所以它可以运行于JVM之上,并可以调用现有的Java类库。
——《Scala菜鸟教程》

  • kafka服务端的代码(包括stream)由Scala编写,客户端的代码基本都由Java编写。

2、最初的版本是使用Scala写的

作者最开始是使用Scala编写。

三、Kafka是什么?

可能用了很久,对kafka的定义仍然停留在“消息队列中间件”上面,但其实官网给出了更为明确的定义。

3.1 旧版本定义

在0.9.0以前,官网的Kafka定义为:
image.png

Kafka® is a distributed, partitioned, replicated commit log service. It provides the functionality of a messaging system, but with a unique design.
Kafka是一个分布式的、分区的、副本冗余的提交日志的服务。它提供了消息系统的功能,但具有独特的设计。
—— Kafka 0.9.0 官网

“独特设计”体现在很多方面,其实就是和传统消息队列的区别,比如可以从任意的位置重新消费而不是消费完后就马上删掉,可以支持多个消费节点负载均衡地消费而不是消费后再进行负载均衡,等等。

3.2 新版本定义

2.4.x则是这样描述的:
image.png

Apache Kafka® is a distributed streaming platform
Apache Kafka(因为已经纳入Apache了)是一个分布式的流平台。
—— Kafka 2.4.x官网

因为kafka已经加入了Stream流的概念,支持实时流计算等新特性。从图中也可以看到,它有了更多的概念,比如Connectors,Stream Processors。但事实上,Kafka现在作为Stream流平台被大厂使用的范例几乎没有,因为Apache Spark这些更专业的封装程度更高的流平台难道不香吗?极客时间《Kafka核心技术与实战》里面提到,Kafka作为流平台的优势有两点:

  • 更容易实现端到端的正确性(Correctness)
    流平台和批处理的区别在于,流平台处理的数据量大,但不精确;批处理精确地处理所有数据,但有瓶颈。如果使用Spark等进行有状态的数据计算,很可能在输入数据和输出数据的时候(例如使用Kafka作为管道),有可能会产生重复消息,造成计算的结果不精确。而如果把kafka既当作数据管道,又作为流平台,它就会在内部处理,就是精确的。然而按照我的理解,这些异常情况对大数据的结果并没有太大的影响,大数据本来就是要处理数据重复、噪声数据等等各种问题的。

  • Kafka体积小巧,结构简单,比Spark这样的庞大系统更容易集成
    Kafka的定位就是,不和Spark这样的成熟流平台产生竞争,而是作为一个功能简单,甚至很多功能都需要自己开发的高度自定义的流平台。这点我还是很赞同的,但是自己开发周边套件的价值很高、代价太大,如果有公司愿意做当然很棒,以后都不会被别人的技术卡脖子,然而大多数这样的部门都还在生存边缘挣扎,很难会去把资源投入到这样的事情上去。

四、Kafka可以用来做哪些事情?

官网上已经列出了Kafka的使用场景,我这里主要认为分为了两类:

4.1 消息系统

4.1.1 消息队列(Messaging)

这是最基本和最广泛的使用场景了,一切传统消息队列(ActiveMQ、RabbitMQ等)的使用理由它都可以适用,如:

  • 将生产者和消费者解耦
  • 削峰填谷,缓存未处理的消息

Kafka有更好的吞吐量、更低的端到端时延、高可靠,水平扩展,以及分区、数据持久化等实用特性。

4.1.2 网站活动跟踪(Website Activity Tracking)

利用Kafka的订阅-发布模型,将用户的行为活动存储到后端数据仓库进行二次处理和展示,可以用来跟踪单个用户维度的活动时间轴。

4.1.3 度量指标采集(Metrics)

对于分布式的应用,单台机器的指标对业务而言意义没有那么明显。将业务指标发送给kafka的同一个主题,然后再生成度量,能够从整体上对业务的情况进行把握。

4.1.4 日志聚合(Log Aggregation)

分布式的应用,已经不能像以前一样看单台日志了。例如,当想要跟踪某个请求,由于负载均衡,你根本不知道请求会发往哪台机器。因此Kafka可以用于日志聚合,把多台机器的日志收集到一起进行展示,ELK(Elasticsearch、Logstash、Kibana)的通用日志解决方案就是一个非常好的例子。

4.1.5 事件源(Event Sourcing)

将事件按照时间顺序进行记录。暂时还没想到和遇到过这类实践场景。

4.1.6 提交日志(Commit Log)

提交日志已经是各大分布式中间件、数据库集群高可用的基本解决方案。例如希望所有的节点数据同步,那么只需要把主节点上的操作日志在副本节点上重复地执行一遍,最终的结果就一定是一致的。Kafka可以用作这种提交日志的中间件。

4.2 流处理

对于一些机器学习和实时流的应用,Kafka的流处理是很重要的特性。Kafka可以对数据进行实时聚合、转换等操作。例如,stream1是用户搜索关键词的事件流,stream2是用户点击链接的事件流,我们希望知道用户搜索哪类关键词后会点击哪种类型的链接,那么可以设置一个时间区间如30秒,通过kafka将两条流按时间区间聚合,可以得到这个用户在搜索关键词之后点击了哪些链接,从而为机器学习提供原始数据。

目前没有实践过这种应用场景。

4.3 分布式存储系统

Jay Kreps在2017年写过一篇文章《It’s Okay To Store Data In Apache Kafka》,大意是说,虽然kafka不应该被用于像“数据库”那样随机存取的持久化存储,但可以用于永久存储日志之类的东西。但看个开心就好,生产环境没有人会用Kafka来当存储,难道S3不香吗。

Kafka原理和源码(一):Kafka基础