Kafka自我总结

一、Kafka的基本概述

1、Kafka是什么?
官网上对Kafka的定义叫:Adistributed publish-subscribe messaging system。所以准确的说Kafka是一个消息订阅和发布的系统。它最初由LinkedIn公司开发,之后成为Apache项目的一部分。Kafka是一个分布式的,可划分的,冗余备份的持久性的日志服务。它主要用于处理活跃的流式数据。

2、Kafka可以起到两个作用?
(1)降低系统组网复杂度。
(2)降低编程复杂度,各个子系统不在是相互协商接口,各个子系统类似插口插在插座上,Kafka承担高速数据总线的作用。

3、Kafka中的相关概念
Topic:特指Kafka处理的消息源(feeds of messages)的不同分类。
Partition:Topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。
Message:消息,是通信的基本单位,每个producer可以向一个topic(主题)发布一些消息。
Producers:消息和数据生产者,向Kafka的一个topic发布消息的过程叫做producers。
Consumers:消息和数据消费者,订阅topics并处理其发布的消息的过程叫做consumers。
Broker:缓存代理,Kafka集群中的一台或多台服务器统称为broker。

4、Kafka的特性:

1)数据在磁盘上存取代价为O(1),而一般数据在磁盘上是使用BTree存储的,存取代价为O(lgn)。

2)高吞吐率:即使在普通的节点(非常普通的硬件)上每秒钟也能处理成百上千的message。

3)显式分布式:即所有的producer、broker和consumer都会有多个,均匀分布并支持通过Kafka服务器和消费机集群来分区消息。

4)支持数据并行加载到Hadoop中

5) 支持Broker间的消息分区及分布式消费,同时保证每个partition内的消息顺序传输。

6)同时支持离线数据处理和实时数据处理:当前很多的消息队列服务提供可靠交付保证,并默认是即时消费(不适合离线),而Kafka通过构建分布式的集群,允许消息在系统中累积,使得Kafka同时支持离线和在线日志处理。

7)Scale out:支持在线水平扩展

二、Kafka的拓扑图:
Kafka自我总结

整个系统运行的顺序可简单归纳为:
1、启动Zookeeper的server。
2、启动Kafka的server。
3、Producer如果生产了数据, 会先通过Zookeeper找到Broker,然后将数据存放进Broker。
4、Consumer如果要消费数据,会先通过Zookeeper找对应的Broker,然后消费。
5、Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。

Tip:Producer到Broker的过程是push,也就是有数据就推送到Broker,而Consumer到Broker的过程是pull,是通过Consumer主动去拉数据的,而不是Broker把数据主动发送到Consumer端的。其实在Kafka中仅保存了每个Consumer已经处理数据的offset。这样有两个好处:一是保存的数据量少,二是当Consumer出错时,重新启动Consumer处理数据时,只需从最近的offset开始处理数据即可。

三、Kayka的应用场景:
1、消息队列

比起大多数的消息系统来说,Kafka有更好的吞吐量,内置的分区,冗余及容错性,这让Kafka成为了一个很好的大规模消息处理应用的解决方案。消息系统一般吞吐量相对较低,但是需要更小的端到端延时,并尝尝依赖于Kafka提供的强大的持久性保障。在这个领域,Kafka足以媲美传统消息系统,如ActiveMR或RabbitMQ。

2、行为跟踪

Kafka的另一个应用场景是跟踪用户浏览页面、搜索及其他行为,以发布-订阅的模式实时记录到对应的topic里。那么这些结果被订阅者拿到后,就可以做进一步的实时处理,或实时监控,或放到hadoop/离线数据仓库里处理。

3、元信息监控

作为操作记录的监控模块来使用,即汇集记录一些操作信息,可以理解为运维性质的数据监控吧。

4、日志收集

日志收集方面,其实开源产品有很多,包括Scribe、Apache Flume。很多人使用Kafka代替日志聚合(log aggregation)。日志聚合一般来说是从服务器上收集日志文件,然后放到一个集中的位置(文件服务器或HDFS)进行处理。然而Kafka忽略掉文件的细节,将其更清晰地抽象成一个个日志或事件的消息流。这就让Kafka处理过程延迟更低,更容易支持多数据源和分布式数据处理。比起以日志为中心的系统比如Scribe或者Flume来说,Kafka提供同样高效的性能和因为复制导致的更高的耐用性保证,以及更低的端到端延迟。

5、流处理

这个场景可能比较多,也很好理解。保存收集流数据,以提供之后对接的Storm或其他流式计算框架进行处理。很多用户会将那些从原始topic来的数据进行阶段性处理,汇总,扩充或者以其他的方式转换到新的topic下再继续后面的处理。例如一个文章推荐的处理流程,可能是先从RSS数据源中抓取文章的内容,然后将其丢入一个叫做“文章”的topic中;后续操作可能是需要对这个内容进行清理,比如回复正常数据或者删除重复数据,最后再将内容匹配的结果返还给用户。这就在一个独立的topic之外,产生了一系列的实时数据处理的流程。Strom和Samza是非常著名的实现这种类型数据转换的框架。

6、事件源

事件源是一种应用程序设计的方式,该方式的状态转移被记录为按时间顺序排序的记录序列。Kafka可以存储大量的日志数据,这使得它成为一个对这种方式的应用来说绝佳的后台。比如动态汇总(News feed)。

7、持久性日志(commit log)

Kafka可以为一种外部的持久性日志的分布式系统提供服务。这种日志可以在节点间备份数据,并为故障节点数据回复提供一种重新同步的机制。Kafka中日志压缩功能为这种用法提供了条件。在这种用法中,Kafka类似于Apache BookKeeper项目。

四、Kafka设计
1、吞吐量

高吞吐是kafka需要实现的核心目标之一,为此kafka做了以下一些设计:

(1)数据磁盘持久化:消息不在内存中cache,直接写入到磁盘,充分 利用磁盘的顺序读写性能
(2)zero-copy:减少IO操作步骤
(3)数据批量发送
(4)数据压缩
(5)Topic划分为多个partition,提高parallelism

2、负载均衡
(1)producer根据用户指定的算法,将消息发送到指定的partition
(2)存在多个partiiton,每个partition有自己的replica,每个replica分布在不同的Broker节点上
(3)多个partition需要选取出lead partition,lead partition负责读写,并由zookeeper负责fail over
(4)通过zookeeper管理broker与consumer的动态加入与离开

3、拉取系统
由于kafka broker会持久化数据,broker没有内存压力,因此,consumer非常适合采取pull的方式消费数据,具有以下几点好处:
(1)简化kafka设计
(2)consumer根据消费能力自主控制消息拉取速度
(3)consumer根据自身情况自主选择消费模式,例如批量,重复消费,从尾端开始消费等

4、可扩展性
当需要增加broker结点时,新增的broker会向zookeeper注册,而producer及consumer会根据注册在zookeeper上的watcher感知这些变化,并及时作出调整。

Kayka的设计要点:

1、直接使用linux 文件系统的cache,来高效缓存数据。

2、采用linux Zero-Copy提高发送性能。传统的数据发送需要发送4次上下文切换,采用sendfile系统调用之后,数据直接在内核态交换,系统上下文切换减少为2次。根据测试结果,可以提高60%的数据发送性能。Zero-Copy详细的技术细节可以参考:https://www.ibm.com/developerworks/linux/library/j-zerocopy/

3、数据在磁盘上存取代价为O(1)。kafka以topic来进行消息管理,每个topic包含多个part(ition),每个part对应一个逻辑log,有多个segment组成。每个segment中存储多条消息(见下图),消息id由其逻辑位置决定,即从消息id可直接定位到消息的存储位置,避免id到位置的额外映射。每个part在内存中对应一个index,记录每个segment中的第一条消息偏移。发布者发到某个topic的消息会被均匀的分布到多个part上(随机或根据用户指定的回调函数进行分布),broker收到发布消息往对应part的最后一个segment上添加该消息,当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到,segment达到一定的大小后将不会再往该segment写数据,broker会创建新的segment。

4、显式分布式,即所有的producer、broker和consumer都会有多个,均为分布式的。Producer和broker之间没有负载均衡机制。broker和consumer之间利用zookeeper进行负载均衡。所有broker和consumer都会在zookeeper中进行注册,且zookeeper会保存他们的一些元数据信息。如果某个broker和consumer发生了变化,所有其他的broker和consumer都会得到通知。


五、High Availability机制

1、什么是High Availability机制?
通过Data Replication(数据备份)Leader Election(选举leader)来保证的,Data Replication指的是每一个Partition都可能会有1个或者多个Replica(备份),其中有一个Replica(备份)会被推选为Leader节点,其余落选的为Follower节点,其中Leader将会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)。

2、Replica(备份)算法 (假设总共有n个broker):
(1)将所有Broker和待分配的Partition排序
(2)将第i个Partition分配到第(i mod n)个Broker上
(3)将第i个Partition的第j个Replica分配到第((i + j) mode n)个Broker上

3、主从同步
Producer只将该消息发送到该Partition的Leader,Leader会将该消息写入其本地Log。每个Follower都从Leaderpull数据。每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中(提高了效率)。一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW(高水位:表示最近一次提交消息的偏移位置)并且向 Producer发送ACK。
对于Kafka而言,Kafka存活包含两个条件,一是它必须维护与ZooKeeper的session(这个通过ZooKeeper的Heartbeat机制来实现);二是Follower必须能够及时将 Leader的消息复制过来,不能“落后太多”。 落后太多将会被从ISR中移除。

4、借助Zookeeper和ISR选Leader Election(选举leader)

Kafka并未采用“Majority Vote”(“少数服从多数”)。而是在Kafka0.8以后增加了一个Controller概念,它在所有broker中选出一个controller,所有Partition的Leader选举都由controller决定,controller会将Leader的改变直接通过RPC的方式(比ZooKeeper Queue的方式更高效)通知需为此作为响应的Broker。同时controller也负责增删Topic以及Replica的重新分配。只有ISR里的成员才有被选为Leader的可能。在这种模式下,对于n+1个Replica,一个Partition能在保证不丢失已经commit的消息的前提下容忍n个Replica的失败。在大多数使用场景中,这种模式是非常有利的。虽然Majority Vote与ISR相比有不需等待最慢的Broker这一优势,但是Kafka官方认为Kafka可以通过Producer选择是否被commit阻塞来改善这一问题,并且节省下来的Replica和磁盘使得ISR模式仍然值得。