Apache Kafka是一个分布式流式平台。数据库
在Kafka中,客户端和服务器之间的通讯是经过简单,高性能,语言无关的TCP协议完成的。 此协议已版本化并保持与旧版本的向后兼容性。 咱们为Kafka提供Java客户端,但客户端有多种语言版本。服务器
首先咱们先了解一下kafka记录流提供的核心抽象-topic。负载均衡
Topic 是发布记录的类别或订阅源名称。kafka中topic 能够有多个订阅者, 便可以有0个,1个或者多个消费者订阅。框架
对于每个topic,Kafka 的集群都会维护着以下图这样的分区log:异步
每一个分区都是有序的、不可更高的记录序列,这些记录都是持续的被追加到结构化的commit log中。分区中的每一个记录都会打上本分区惟一的被称为offset的序列id。分布式
Kafka集群负责将全部发布的记录(不管是否消费)持久化,这些记录都是有一个配置的保留时间。例如,若是保留时间设置的是两天,那么记录发布以后两天内是能够消费的,两天以后就会被清除来事放空间。Kafka的性能在数据大小方面其实是恒定的,所以长时间存储数据不是问题。函数
实际上,每一个消费者保留的惟一元数据是该消费者在log中的偏移量或位置。偏移量是由消费者来控制的:一般消费者在读取记录的时候会线性的推动其偏移量,可是实际上,既然消费者控制着消费的位置,就能够以任意顺序来消费记录。例如消费者能够从新设置偏移量来从新处理消费过的数据或者跳过最近的记录从头最新位置开始消费。工具
这些特性的结合就意味着Kafka消费者是很是cheap的,消费者的来去对于集群或者其余消费者没有太多影响。例如,可使用命令行工具来查看任何一个topic中的内容而不会对其余消费者消费的内容产生影响。性能
日志中的分区有多种用途。首先,它们容许日志扩展到超出单个服务器的大小。 每一个单独的分区必须有托管它的服务器,但topic可能有许多分区,所以它能够处理任意数量的数据。 其次,最重要的一点是它们充当了并行性的单位 。命令行
log分区分布在kafka集群的服务器上,每一个服务器处理数据并请求分区的共享。每一个分区在服务器上都有配置的副本数量来容错。
每一个分区都有一个服务器扮演者leader的角色,0个或者多个服务器扮演者followers的角色。leader处理这个分区的全部读写请求,follower被动的复制leader的数据。若是leader崩溃了,其中的follwers就会自动变成新的leader。每一个服务器都充当其某些分区的领导者和其余服务器的追随者,所以负载在群集中获得很好的平衡。
Kafka MirrorMaker 为集群提供了异地数据同步工具。使用MirrorMaker,消息能够跨多个数据中心或者云进行复制同步。也可使用主/被的方式来备份或者恢复数据;或者主/主的方式来是数据更加靠近用户。
生产者发布选择的数据到topic中。消费者负责选择记录分配到topic的那个分区中。可使用round-robin方式简单的进行负载均衡或者使用语义分区函数来作。
消费者经过consumer group name来标记,每条记录都会发布到topic中后会被投递到订阅使用者组中一个消费者实例。消费实例能够在单独的进程中或者在单独的机器上。
若是全部消费者都有一样的消费组,那么记录将有效地在消费者实例上进行负载平衡;
若是全部的消费者有不一样的消费组,那么每条记录都会广播到全部的消费者实例上;
有四个分区(P0-P3)的Kafka 集群,集群有两台服务器,有两个消费组。消费组A有两个消费者实例,消费组B有4个消费实例。
然而,更常见的是,咱们发现主题具备少许的消费者群体,每一个“逻辑订阅者”一个。 每一个组由许多用于可伸缩性和容错的消费者实例组成。 这只不过是发布 - 订阅语义,其中订阅者是消费者群集而不是单个进程。
Kafka实现的消费方式是在消费者实例上划分日志中的分区以便于每一个实例在任什么时候间点都是每一个分区公平的独占消费者。维护组中成员资格的过程由Kafka协议动态处理。 若是新实例加入该组,他们将从该组的其余成员接管一些分区; 若是实例死亡,其分区将分发给其他实例。
Kafka只能保证每一个分区的记录数是有序的,不一样分区之间不保证有序。每一个有序的分区加上使用key分区的能力对于大部分应用是足够的。然而,你须要整体有序的话可使用一个分区的topic。这就意味着每一个消费组只有一个消费进程。
能够将Kafka部署为多租户解决方案。多租户经过配置哪些topic能够生产或者消费数据来启用。也能够选择是否支持配额。管管理员能够定义和强制执行配额,以控制客户端使用的代理资源。
高级别的Kafka提供了以下的保证:
Kafka 的流概念与传统企业消息系统相好比何?
传统消息系统有两种模式:队列和发布订阅。在队列模式中,许多消费者从服务读取数据,每条记录都流向消费者之一;在发布订阅模式下数据会广播到全部消费者那里。这两种模式都有好处和坏处。队列的好处是能够把处理数据的压力分散到多个消费者实例上,这就能够扩展处理能力。然而队列不是多订阅的,一旦数据被读取了数据就没。发布订阅能够将数据广播到全部的消费者那里,缺点就是没有办法扩展处理能力因为消息会广播到每一个订阅者那里。
Kafka 消费组的概念综合了这两个概念。消费组做为队列来看是能够把处理能力分散到多个进程上,做为发布订阅,能够将数据广播到多个消费组。
Kafka 相比于传统的消息系统的另外一个优点是有更好的顺序保证。
传统队列在服务器上按照顺序保存记录,若是消费者从队列中消费数据的时候,服务器会按照存储的顺序提供记录。虽然服务器按照顺序分发记录,可是记录是异步的传递到消费者那里的,所以可能到达消费者的时候是乱序的。这就意味着在并行处理的消费上记录是乱序的。消息传递系统一般经过具备“独占消费者”的概念来解决这个问题,该概念只容许一个进程从队列中消耗,但这固然意味着处理中没有并行性。
Kafka在这方面作的会更好。经过在topic中提出了一个parallelism—the partition—within 的概念 ,Kafka 可以在消费者流程池中提供订购保证和负载平衡。这是经过将topic中的分区分配给使用者组中的使用者来实现的,以便每一个分区仅由该组中的一个使用者使用。 经过这样作,咱们确保使用者是该分区的惟一读者并按顺序使用数据。 因为有许多分区,这仍然可让许多消费者实例的实现负载均衡。 但请注意,消费者组中的消费者实例不能超过度区。
任何容许发布与消费消息分离的消息队列实际上充当了正在进行的消息的存储系统。 Kafka的不一样之处在于它是一个很是好的存储系统。
写入Kafka的数据都写入磁盘而且都有备份用来作容错。Kafka容许生产者等待确认消息以便于副本写入的完整性来确保数据仍然存在及时写入服务器宕机。
Kafka很好的使用了磁盘的接口 -- 在服务器上不管是写入50KB仍是50TB的数据,效率都是同样的。
因为是存储系统,容许客户端控制其读取位置,能够将Kafka视为一种专用于高性能,低延迟提交日志存储,复制和传播的专用分布式文件系统
只有读,写,以及存储流数据仍是不够的,目的是实现流的实时处理。
Kafka 的流处理器是从输入topic的获取流数据,在输入中执行一些处理操做,最后将处理结果输出到topic中。
例如,零售应用可能会将销量以及出货量做为输入流,而后将从新排序以及价格调整之后的数据输出到topic中。
直接使用生产者或者消费者API就能够作一些简单的处理。而后对于复杂的变换处理,kafka 提供了提供了一整套集成的Stream API。这就能够构建计算流的聚合或者流join这样不通常的应用。
这总便利帮助咱们解决了这类应用面对的难题:处理乱序数据,代码变更须要从新处理,执行有状态的计算等等。
流API创建在Kafka提供的核心原语上:使用生产者消费者API做为输入,使用Kafka做为有状态的存储,在流处理实例间使用相同组的机制进行容错。
将消息,存储以及流处理结合起来看似不是很常见,可是对于Kafka这种角色的流处理平台十分重要的。
像HDFS这样的分布式文件系统存储静态文件进行批处理。这样的系统容许存储和处理过去的历史数据。
传统的企业级消息系统能够处理订阅之后即将到来的消息,应用内建这个方式来处理即将到来的数据。
Kafka 将这些能力都融合进来,同时这种组合对于Kafka做为流媒体应用程序平台以及流数据管道的使用相当重要。
经过组合存储和低延迟订阅,流应用程序能够以相同的方式处理过去和将来的数据。 也就是说,单个应用程序能够处理历史存储的数据,而不是在它到达最后一条记录时结束,它能够在将来数据到达时继续处理。 这是包含批处理以及消息驱动应用程序的流处理的通常概念。
一样,对于流数据流水线,订阅实时事件的组合使得能够将Kafka用于极低延迟的流水线; 可是,可以可靠地存储数据使得能够将其用于必须保证数据传输的关键数据,或者与仅按期加载数据或可能长时间停机以进行维护的离线系统集成。 流处理设施能够在数据到达时对其进行转换。