kafka介绍
1、ApacheKafka是一个分布式流平台。这到底是什么意思呢?
流媒体平台有三个关键功能:
- 发布和订阅记录流,类似于消息队列或企业消息系统。
- 以容错持久的方式存储记录流。
- 当记录流产生的时候可以即时处理。
kafka通常用于两大类应用:
- 构建可在系统或应用程序之间可靠获取数据的实时流数据管道
- 构建实时流应用程序,用于转换或实时响应数据流
要了解kafka如何做这些事情,让我们深入探索kafka的能力。
首先有几个概念:
- Kafka作为一个集群运行在一台或多台可以跨越多个数据中心的服务器上。
- Kafka集群在称为topic的类别中存储记录流。
- 每个记录由一个key,一个value和一个timeStamp组成。
kafka有四个核心API:
- Producer API允许应用程序将记录流发布到一个或多个Kafka topic。
- Consumer API允许应用程序订阅一个或多个topic并处理为他们生成的记录流。
- Streams API允许应用程序充当流处理器,从一个或多个topic消费输入流,并将输出流输出到一个或多个输出topic,从而将输入流有效地转换为输出流。
- Connector API允许构建和运行可重复使用的生产者或消费者,这些生产者或消费者可以将Kafka topic连接到现有的应用程序或数据系统。例如,连接到关系数据库的connector可以会捕获对表的每个更改然后发送到topic。
在Kafka中,客户端和服务器之间的通信是通过一种简单的,高性能的,语言无关的TCP协议完成的。该协议是版本控制的,并保持与旧版本的向后兼容性。我们为Kafka提供Java客户端,但客户端可以使用多种语言。
2、Topics and Logs
让我们首先深入Kafka提供的核心抽象 - topic。
topic是记录发布到的类别。kafka的topic始终是多订阅者的;也就是说,一个topic可以有零个,一个或多个订阅消费者,这些消费者订阅写入topic的数据。
对于每个topic,Kafka集群都维护一个partitioned log,如下所示:
每个partition 都是一个有序的,不可变的记录序列,不断追加到结构化的提交日志中。partition 中的记录每个分配一个连续的id号,称为offset,用于唯一标识分区内的每条记录。
Kafka集群使用可配置的保留时间持续保留所有已发布的记录 - 不管它们是否已被消费。例如,如果保留策略设置为两天,则在记录发布后的两天内,保留策略可用于消费,之后将被丢弃以释放空间。kafka的性能和数据大小是无关的,因此长时间存储数据不成问题。
实际上,消费者维护的基础的唯一元数据是该消费者在log中的offset。这个offset是由消费者控制的:消费者通常会在读取记录时线性地推进其offset,但实际上,由于offset由消费者控制,因此它可以按照喜欢的任何顺序消费记录。例如,消费者可以重置为较旧的偏移量以重新处理之前的数据,或者跳至最近的记录并从“now”开始消费。
这种功能的组合意味着kafka消费者非常灵活 - 他们可以反复消费记录,但是对集群或其他消费者没有太大影响。例如,您可以使用我们的命令行工具来“tail”任何topic的内容,而无需更改任何现有消费者消费的内容。
log中的分区有多种用途。首先,它们允许日志的大小超出服务器限制的单个文件大小。虽然每个单独的分区必须满足服务器的限制,但是一个topic可能有很多分区,因此topic可以处理任意数量的数据。其次,也是最主要的一点,分区还可以作为并行处理的单位 。
3、Distribution
log的partitions分布在kafka集群中的服务器上,集群中每个服务器都处理共享分区的数据和请求。每个分区都可以复制到N个服务器上以实现容错,N是可以配置的。
每个分区有一个服务器充当“leader”,零个或多个服务器充当“follower”。leader处理分区的所有读取和写入请求,而follower被动地复制leader。如果leader挂了,其中一个follower将自动成为新leader。每个服务器都会充当其中一些分区的leader,同时也会充当其它分区的follower,因此在集群内的机器的负载会比较均衡。
4、Geo-Replication(地理复制)
kafka mirrormaker为您的集群提供地理复制支持。通过MirrorMaker,消息被复制到多个数据中心或云区域。您可以在主备场景中将其用于备份和恢复;或者在主主方案中将数据放置得更靠近用户,或者支持数据本地化要求。
5、Producers
生产者将数据发布到他们选择的topic上。Producers负责选择将哪个记录分配给topic中的哪个分区。这可以以循环方式分配给不同分区的方式实现,只是为了平衡负载,或者可以根据某些语义分区功能(例如基于记录中的某个键)来完成。
6、Consumers
消费者用consumer group name标记自己,并且发布到topic的每个记录都被传送到每个订阅consumer group中的一个消费者实例。消费者实例可以在单独的进程中或在单独的机器上。
如果所有消费者实例具有相同的消费者组,则记录将有效地在消费者实例上进行负载均衡。
如果所有消费者实例具有不同的消费者组,则每个记录将被广播给所有消费者组中的一个消费者实例。
两个服务器组成的kafka集群托管四个分区(p0-p3)和两个消费者组。消费者组a有两个消费者实例,而b组有四个消费者实例。
然而,更普遍的是,我们发现topics有几个的消费群体,每个消费者组消费一个topic。每个组由许多消费者实例组成,具有可扩展性和容错性。这只不过是publish-subscribe语义,其中用户是一群消费者而不是一个进程。
在kafka中消费的方式是将日志中的分区划分到消费者实例上,以便每个实例在任何时间点都是分区的独占消费者。维护组中成员的过程是由kafka协议动态地处理的。如果新实例加入该组,则这些新实例i将接管来自该组的其他成员的一些分区;如果一个实例挂掉,其分区将分配给组内的其余实例。
kafka仅保证分区内记录的顺序,而不保证topic中不同分区之间的记录总顺序。每个分区的排序以及按键分区数据的能力对于大多数应用程序来说已经足够。但是,如果您需要全部记录的总顺序,则可以通过仅有一个分区的topic来实现,但这意味着每个消费者组只有一个消费者进程。
7、多租户
您可以将Kafka部署为多租户解决方案。通过配置哪些topic可以产生或使用数据来启用多租户。还有配额操作支持。管理员可以为不同的请求定义和执行配额以控制客户端使用的代理资源。
8、保证
- 由producer发送到特定topic分区的消息将按照它们发送的顺序附加。也就是说,如果记录M1和M2由同一个生产者发送,并且M1被首先发送,则M1将具有比M2更低的offset并且出现在日志中较早的地方。
- 消费者实例按照记录存储在日志中的顺序消费记录。
- 对于具有replication factor(复制因子)N的主题,kafka将容忍多达N-1个服务器故障,而不会丢失任何提交给日志的记录。
有关这些保证的更多详细信息在documentation的design部分给出。
9、Kafka as a Messaging System
kafka的流概念如何与传统的企业消息传递系统相比较?
传统消息系统有两种模式:队列模式和发布 - 订阅模式。在队列模式中,消费者池可以从服务器读取记录,并且每条记录都只会被其中的一个消费者消费;在发布 - 订阅模式中,记录被广播给所有消费者。这两种模式都有优势和劣势。队列的优势在于它允许您数据交给多个多个consumer实例中处理,从而扩展您的处理能力。不幸的是,队列不是多订阅者的 - 一旦一个记录被消费了,那么这个数据就会消失。发布 - 订阅模式允许您将数据广播到多个进程,但无法进行扩展处理,因为每条消息都发送给每个订阅者。
kafka的consumer group概念包括了这两个概念。与队列一样,consumer group允许您把记录分发给不同的consumer group消费。与发布 - 订阅一样,kafka允许您向多个consumer group广播消息。
kafka的优点是每个topic都有这些属性 - 它既可以扩展处理,也可以是多用户。
Kafka也比传统的消息系统有更强大的顺序保证。
传统队列在服务器上按顺序保存记录,并且如果多个消费者从队列中消耗,则服务器按照它们存储的顺序提供记录。但是,尽管服务器按顺序提供记录,但是记录是异步传递给消费者的,因此这些记录针对不同的消费者会乱序。这实际上意味着在并行消费的情况下记录的排序会丢失。消息传递系统通常会采用“排他消费者”的方式解决这个问题,只允许一个进程从队列中消费,但这当然意味着处理中没有并行性。
kafka做得更好。在topic内部有一个并行概念 - 分区概念,Kafka能够在消费者处理池中提供顺序保证和负载均衡。这是通过将topic中的分区分配给consumer group中的唯一的consumer来实现的,以便每个分区仅由组中的一位consumer使用。通过这样做,我们确保消费者是该分区的唯一读者,并按顺序使用数据。由于有很多分区,这仍然可以平衡许多消费者实例的负载。但请注意,consumer group中的消费者实例不能多于分区,否则会多余的消费者会浪费,最好的做法是保持消费者实例和分区数相同。
10、Kafka as a Storage System
任何允许发布消息与消费消息分离的消息队列都可以充当存储流动消息的存储系统。kafka的不同之处在于它是一个非常好的存储系统。
写入Kafka的数据写入磁盘并进行复制以实现容错。Kafka允许生产者等待确认,记录被完全复制之后才算确认发送成功,并且即使写入的服务器失败也能保证写入持续。
Kafka使用的磁盘结构伸缩性很大 - 无论您在服务器上有50 KB还是50 TB的持久性数据,Kafka的性能都不会受影响。
因为kafka良好的存储结构并允许客户端控制其读取位置,所以您可以将Kafka视为一种专用于高性能,低延迟提交日志存储,复制和传播的专用分布式文件系统。
有关Kafka提交日志存储和集群设计的详细信息,请阅读本页。
11、Kafka for Stream Processing
仅仅读取,写入和存储数据流是不够的,最终目的是启用流的实时处理。
在Kafka中,stream processor(流处理器)是指从input topic获取连续数据流,对该输入执行一些处理并生成连续数据流输出到output topic。
例如,零售应用程序可能会接受销售和装运的输入流,并输出一系列重新排序和对这些数据计算出的价格调整。
可以直接使用producer API和consumer API进行简单的处理。然而,对于更复杂的转换,Kafka提供完全集成的Streams API。这允许构建进行复杂处理的应用程序,从而计算流的聚合结果或将流连接在一起。
这个工具有助于解决这类应用程序面临的难题:处理无序数据,重新处理输入就像更改代码一样,执行有状态的计算等。
stream API基于Kafka提供的核心原语构建:它使用producer API和consumer API当做输入参数,使用Kafka进行有状态存储,并在流处理器实例之间使用相同的group机制来实现容错。
12、Putting the Pieces Together
消息传递,存储和流处理的这种组合可能看起来很不寻常,但对于Kafka作为流式传输平台的角色来说,这是非常重要的。像HDFS这样的分布式文件系统允许存储用于批处理的静态文件。这样的系统能够有效地存储和处理过去的历史数据。传统的企业消息传递系统只允许处理订阅后来的消息。以这种方式构建的应用程序处理后来的数据。Kafka结合了这两种功能,而且这两种组合对于Kafka用作流式传输应用平台和流式数据管道都非常重要。通过将存储和低延迟订阅相结合,流式应用程序可以以同样的方式处理过去和未来的数据。也就是说,使用kafka可以实现一个单一的应用程序可以处理历史的,存储的数据,而不是在它达到最后一个记录时结束,它可以在后来的数据到达时继续处理。这是流处理的一般概念,包括批处理以及消息驱动的应用程序。同样,对于流式数据流水线,订阅实时事件的组合使得可以将Kafka用于非常低延迟的流水线;而且可靠地存储数据的能力可以将其用于必须保证数据交付的关键数据,或者与只能定期加载数据的离线系统集成,或者可能在较长时间内停机进行维护。流处理组件可以在数据到达时进行转换。