初识KAFKA

·  阅读 361
初识KAFKA

每个公司都在用数据武装自己,应用随时随地产生数据,我们获取这些数据,对数据进行分析,利用数据分析的结论支持管理层做决策。数据已然成为一个公司最核心的资源,像今日头条、淘宝这样的应用,用户在其上的每一个行为都会产生数据,这些数据最终转化为随后推荐给该用户的可能感兴趣的内容或商品。

数据从产生的地方到它被处理的地方,这个过程首先要快,假如今天点击了头条的一篇文章,等到第二天才能看到推荐的相似的内容显然是不可接受的;其次这个过程还要对使用者透明,这样使用者才能把精力集中到手头的业务上。

如何使得数据从产生到被处理这个过程又快又透明呢?答案就是本专栏的主角--KAFKA。

消息的发布/订阅

在深入学习KAFKA之前,有必要先了解一下消息的发布/订阅模式,该模式由4个角色组成:

  • 一段数据:就是所谓的消息。
  • 中心服务:发布者把消息发送到中心服务,订阅者从中心服务订阅并获取消息,从而实现发布者和订阅者之间的解耦。
  • 发布者:发送消息,但是它不直接把消息发送给接受者,而是把消息进行分类后发送到中心服务器。
  • 订阅者:订阅并从中心服务器接收特定类型的消息。

现在我们假设世界上压根就没有一个叫KAFKA(或者任何MQ系统)的东西,而业务又迫切需要一个消息的发布/订阅系统,需求来了:

产品经理:我设计了一个活动,需要把活动页的PV/UV还有其他一些指标在仪表盘上呈现出来,我知道这种事情对你来说轻而易举,稍后我会把详细需求文档发给你,这个需求很急,赶紧安排人干起来吧!

最简单粗暴的发布/订阅系统

时间虽然紧迫,但是对你而言似乎问题不大。你派出组内两员大将A和B,B负责仪表盘的开发,A负责收集需要的指标并把它们发送给B的仪表盘服务。

B:老大,我的仪表盘开发的差不多了,我提供了一个rest api,A调用我的API把事件传过来就可以啦。

A:我调了B的接口联调了一下,一切正常,没有问题。

此时你的系统结构就像下面这个样子:

不久之后,产品又来了新的需求:

产品经理:上一个需求完成的很棒,现在我们需要对用户数据做一些分析,看看为什么产品的销量总是上不去,C是咱们公司的数据分析专家,你们可以聊一聊。

于是你找到了C,告诉他最新的需求,C很爽快的说:没问题,我们这边已经有接口了,你调用一下,把用户的行为数据上报过来就可以了。

于是A修改了一下他的代码,把数据同时上报给仪表盘服务和数据分析服务。

现在让我们来仔细的审视一下这个系统:产生数据的应用直连到处理数据的应用上,假如生产数据的应用越来越多,处理数据的服务也越来越多(不光有仪表盘,数据分析,还有推荐,AI预测等等),那么很快你的系统将变成下面这个样子:

用单独的服务改进系统

如此多的连接,用不了多久可能就会让你崩溃,**问题的本质在于数据的生产者和数据的消费者是直接耦合在一起的,**于是你牺牲了几个脑细胞后很快想到了解决方案:用一个单独的服务来接收各个应用发送的消息,并向需要这些数据的系统提供数据查询接口,改进后的系统长下面这个样子:

整个系统一下子从一团乱麻变的脉络清晰可见,发送者和接收者通过一个单独的服务解了耦。恭喜你,其实你已经设计了一个消息的发布/订阅系统,虽然它很简单。

重复造轮子

改进后的系统上线没多久,你偶尔在一次公司的内部分享中得知,负责日志处理的部门用了几乎和你一模一样的思路实现了他们的日志系统:各个应用把日志发送到一个日志服务中心,日志查找服务和日志分析服务从日志服务中心获取日志并处理,就像下面这样:

重复造轮子这事还真是无处不在不是?是否可以再改进一下系统让各个业务线都能复用之?

扩容是个问题

在公司全体同仁的不懈努力下,业务规模不断扩大,用户量越和数据量飞速增长,现在中心服务器已经有点扛不住了,单点瓶颈问题开始显现,于是你自然而然的想到了分布式,一台机器不行就用多台机器嘛,而涉及到分布式,你的脑海里立马浮现出了令人头疼的CAP问题,看起来造出一个通用的、可扩展的消息发布/订阅系统并没有想象中那么简单。

KAFKA的诞生

实际上我们上面举的这个例子和LinkedIn曾经遇到的问题很类似,KAFKA正是LinkedIn为了解决类似问题而祭出的终极武器。

领英内部曾经有两个系统:

监控系统

用于收集系统和应用的统计指标,这套系统采用了领英自研的数据采集器,并用了一些开源的工具存储并展示数据。除了像CPU使用率,应用性能这些传统的指标外,这套系统还有一个请求监控功能,用来监控一个用户请求在领英的内部应用之间的传递过程。

但是这套系统存在着不少的缺陷:

  • 系统是以轮询的方式定期去收集各种指标;

  • 应用的维护团队无法管理自己应用的指标,而是由这套监控系统团队管理,想新增或者删除一个指标都需要和监控系统团队一起协同处理;

  • 不同子系统的相同的度量指标,名称各不相同,比如同样是CPU使用率,可能存在Depart-A-CPU,Depart-B-CPU等,维护起来很不方便;

  • 即便是一个很简单的任务,也需要开发人员的介入。

用户行为追踪系统

是一个HTTP服务,前端服务周期性的连接到它,将一个批次的消息(消息是XML格式)发送给该服务,这批消息会交给一个离线处理系统进行处理,同样这个系统也存在很多缺陷:

  • XML的格式五花八门,并且解析这些XML很耗费性能;
  • 更改用户行为的类型需要前端团队和离线处理团队协同;
  • 前端以小时为周期传递一个批次的消息,无法做到实时处理。

这样两套系统显然很难共用一个后端服务,两套系统的数据格式不同,监控系统采用轮询模式,而行为追踪系统使用Push模式。但是这两套系统的数据又存在着一些很紧密的联系,例如某个特定类型的用户行为(行为追踪系统)可能会影响到应用的性能(监控系统),某个用户行为数据的下跌可能意味着应用的某个功能出现性能问题,但是追踪系统以小时为单位的批处理能力决定了无法实时的响应这类问题,领英急需一套实时并且具有足够好的扩展性以应对突发流量的系统。

这套系统的开发由领英的工程师Jay Kreps牵头,此人最初在领英负责一个叫Voldemort的开源分布式键值数据库系统,系统的最初目的是打造一套能同时满足监控系统和行为跟踪系统需求的消息系统,并且有足够好的扩展性,系统的目标:

  • 通过使用推拉结合的模型,解耦消息的发送者和消费者
  • 为了支持多个消费者,消息系统要能够将消息持久化存储(否则一个消费者消费完了,另一个消费者将收不到消息)
  • 穷尽一切优化手段使系统的吞吐量足够高
  • 要支持水平扩容以应对大流量数据

最终满足所有这些条件的系统诞生了,它就是KAFKA,这是一个具有典型的消息系统的接口,同时存储层更像一个日志聚合系统的消息系统。上线后,它完美的支持了领英监控系统和用户行为追踪系统每天产生的近十亿的数据。

2010年领英将KAFKA开源到GitHub,很快它就在社区炸了锅,2011年领英将KAFKA贡献给了Apache,到目前,KAFKA正在被来自世界各地,拥有着最大流量的公司使用着。

关于为什么把这套系统叫KAFKA,KAFKA之父Jay Kreps是这样说的:因为KAFKA是一个用了各种优化手段以满足高吞吐量写入的消息系统,所以使用一个作家的名字是一个好主意,我征求了很多同伴的意见,他们都比较喜欢Fraz Kafka(奥匈帝国的一个作家),而且Kafka这个名字做为一个开源项目的名称听上去很酷,所以我们决定将这套系统命名为KAFKA。

为什么选择KAFKA

发布/订阅模式的消息系统琳琅满目,为什么KAFKA是个不错的选择呢?

多个生产者

KAFKA支持任意多的生产者,不管它们用多个不同的topic还是同一个topic,这使得KAFKA能够完美的聚合来自多个系统的数据并且提供一致性。举个例子,假如一个网站背后有许多个微服务支撑,现在想统计该站点的PV,那么只需要一个topic就可以了,所有的微服务都用相同的格式向这个topic写入,负责统计PV的消费者只需要消费这个topic的数据,然后不断的累加就能计算出站点PV,不需要给每个微服务都去设置一个topic。

多个消费者

KAFKA还支持多个消费者(组)消费同一个topic的数据,互不影响。例如消费者(组)A合消费者(组)B都订阅topic,A读了100个消息,然后B才启动,那么B将从开头消费消息,而不是从101开始消费。这和许多其他的消息系统有很大的区别,在这些系统中一旦一个消息被消费,其他的消费者就再也没机会消费到这个消息了。在KAFKA中,多个消费者还可以组成消费者组,KAFKA确保一条消息只会被组内的一个消费者消费。

消息留存

KAFA的消息是具有留存期的,消息写入磁盘后,可以给它配置留存期,比如留存期设为1分钟,那么消息将在磁盘上保留1分钟的时间。这样的好处是什么呢?假如某个消费者的消费进度落后了(可能是处理中有耗时操作或者突发的流量导致网络拥塞),也可以确保消息在设定的留存期内不会丢失,假如你担心突发流量导致处理速度变慢,你可以设置一个较大的消息留存时间,以防消息丢失,即便消费者重启了,消息也还在磁盘上,重启后可以继续消费。

灵活的扩容

KAFKA灵活的扩容机制使得它可以支持任意量级的数据(只要你的服务器足够多),一开始你可以只是一个单机KAFKA,稍微有一点点规模后可以用三台机器搭建一个小集群,等业务大规模扩张后,你可以用成百上千的机器组成更大的集群,集群的扩容可在线上进行,不影响整个系统的可用性。

高性能

前面提到KAFKA在实现的时候是用尽各种优化手段,这其中最广为人知的就是零拷贝和大量使用页缓存。这些优化手段使得KAFKA拥有极高的性能和吞吐量。

KAFKA是数据生态系统的核心

一个大型的数据生态系统是有许多应用一起协同工作的,而KAFKA通常居于系统的核心位置。前端应用将诸如日志、应用统计指标之类的数据写入到KAFKA,而另外一些应用从KAFKA中读取并处理这些数据,将处理的结果又再次写入到KAFKA中供其他应用使用,如下图:

KAFKA承载着整个生态系统中所有组件的数据,并提供一致的接口给所有客户,所有的组件通过KAFKA解耦,数据的生产者和消费者不需要建立直接的连接,整个生态中的组件可以随需求任意添加或者删除,生产者也无需关心数据被谁消费或有多少个消费者需要消费消息。

总结

现在我们已经对KAFKA有了初步的了解,在和它深入交流做好朋友之前,我们不妨总结一下对它的第一印象:

  • KAFKA是一个基于发布/订阅模式的消息系统
  • KAFKA解耦了消息的生产者和消费者,二者之间不再需要直接建立连接
  • KAFKA对消息做了持久化,并且可以设置消息留存时间,通过这种机制保证了在留存期内消息不会丢失
  • KAFKA拥有灵活的扩容机制,理论上可以支持任意量级的流量
  • KAFKA在设计的时候就用了各种优化手段以提高其吞吐量,其中最突出的手段就是零拷贝技术和大量使用内存分页缓存
分类:
后端
标签:
分类:
后端
标签: