Kafka基础入门知识(一)
Kafka 入门知识
Apache Kafka 是一个分布式的流平台。(大多数时候,我们认为它是只是一个分布式的消息中间件,个人以为不完全是)。根据官方的说法:一个流处理平台要具有三个关键的能力:
- 发布和订阅消息的能力。这方面与消息队列比较类似。
- 以容错的方式存储消息(流)。
- 在消息流发生时处理他们。(感觉和storm类似)。
Apache Kafka 与传统的消息系统的异同
- Kafka系统是一个分布式系统,易于向外扩展;
- 可以同时为发布和订阅高吞吐量;
- 支持多订阅者,当失败时能自动平衡消费者;
- 将消息持久化到磁盘,因此可以用于批量消费,例如ETL
kafka作为分布式消息系统的一些特点
- kafka 是作为一个集群运行在一个或者多个服务器上的。
- kafka集群存储的消息是一个topic为类别记录的。
- 每个消息(也叫record)都是由一个key,一个value和时间戳构成的。
Kafka的四个核心API:
- 应用程序使用Producer API发布消息到1个或多个topic;
- 应用程序使用Consumer API来订阅一个或多个topic,并处理订阅到的消息;
- 应用程序使用Streams API充当一个流处理器,从1个或多个topic消费输入流,并产生一个输出流到1个或多个输出topic,有效地将输入流转换到输出流;(带点流处理,ETL的味道)
- Connector API 允许构建或运行可重复使用的生产者或消费者,将topic连接到现有的应用程序或数据系统。
Kafka 专用术语
Broker:缓存代理。已发布的消息保存在一组服务器中,称为Kafka集群。而这些服务器被称为broker。(kafka支持消息持久化,因此在生产者生产出消息以后,kafka不会直接将消息传递给消费者,而是先要在broker中进行存储,这些存储的东西对应的就是kafka的日志文件)
Topic:Kafka将消息种子(Feed)分门别类,每一类的消息称之为一个主题(topic)。每条发布到Kafka集群的消息都有一个topic类别(物理上不同topic的消息分开存储,逻辑上一个topic的消息虽然保存在一个或多个broker上,但用户只需要制定消息的Topic即可生产或消费数据而不必关心数据存于何处)。
Partition:Partition 是物理上的概念,每个Topic包含一个或多个Partition。之所以会用到Partition分区,是因为消息在Broker中是通过Log 追加(即新的消息保存在文件的最后面,是有序的)的方式进行持久化存储。由于文件不可能无限制的扩大,通过分区可以将日志内容分散到多个server上来避免文件尺寸达到单机磁盘的上限。同时为了使得Kafka的吞吐率可以线性提高越多的partitions意味着可以容纳更多的consumer(因为kafka默认要求,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费)。
物理上把Topic分成一个或多个Partition,每个Partition在物理上对应一个文件夹,该文件夹下存储这个Partition的所有消息和所有索引文件。例如创建topic1和topic2两个topic,且分别有13个19个分区,则整个集群上会相应产生32个(13+19=32)个文件夹(此处replication-factor均设置为1)。
每一个分区都是一个顺序的、不可变的消息队列
,并且可以持续的添加消息。分区中的消息都被分了一个序列号,称之为偏移量(offset),在每个分区中此偏移量都是唯一的。
实际上消费者所持有的元数据就是这个偏移量,也就是消费者在这个log中的位置。这个偏移量由消费者控制:正常情况当消费者消费消息的时候,偏移量也线性的增加,但是实际偏移量由消费者控制,消费者可以任意控制偏移量,读取消息。
这里的消息可能包括已经消费过的消息。之所以能消费已经消费过的消息,是因为Kafka集群保持所有的消息,直到它们过期,无论消息是否被消费了(这点和有些消息中间件有所区别),因此Kafka消息也是有一定时效性的,并不是完全地可靠。
Distribution:Kafka的分布式其实主要就是指前面的存储日志的分区分布。Log日志被分布到集群中的多个服务器上。每个服务器服务器处理它分到的分区数据和响应对该分区的操作。根据配置每个分区可以复制到其他服务器作为备份容错。每个分区里面都有一个服务器来扮演一个Leader的角色,这个Leader负责对这个分区所有的数据的读写请求。一个Leader可以有零或多个floower。如果这个Leader failes,其他的Follower会被推举为新的leader。一台服务器可以即是一个分区的leader同时又是另外一个分区的follwer。
Producers:生产者向某个选定的Topic上发布消息。生产者也负责选择那一条消息发布到topic上的哪一个分区。最简单的方式是从分区列表中轮流选择,也可以根据某种算法依照权重选择分区。
Consumers:消费者用consumer group name 标注消费者自己。(消费者组:允许同名的消费者组成员瓜分处理)每一个发送给opoic的消息将被分配给一个预定了该消息的counsumer group的一个消费者实例。消息的发送主要有两种模型:队列式和发布-订阅式。队列的处理方式是一组消费者从服务器读取消息,一个消息只有其中的一个消费者处理。而发布-订阅式,消息被广播给所有的消费者,接收到的消费者理论上都可以处理该消息(这点有点类似于网络上的广播包的概念)。但无论是那种模式,都是采用消费者这一种模型。上面提到消费者使用消费者组名标记的子集,假如所有的消费者都在一个组中,那么就变成了队列的方式,消息将按照负载均衡的方式在消费者中消费。如果所有的消费者拥有不同的消费者组名,那么消息将广播给所有的消费者进程。
2个Kafka集群管理4个分区(P0-P3),2个消费者组,消费者组A有2个消费者实例,消费者组B有4个消费者实例。Kafka中实现消费的方式主要是将日志中的分区分发给消费者实例,以便每个实例可以“公平分享”这些分区。这个维护组成员的资格讲由Kafka协议动态的处理。如果新实例加入这个组,他们将接管来自组中其他成员的一些分区,如果一个实例dies,其分区将会被分配给其他的实例。
传统的队列模型保持消息,并且保证它们的先后顺序不变。但是, 尽管服务器保证了消息的顺序,消息还是异步的发送给各个消费者,消费者收到消息的先后顺序不能保证了。这也意味着并行消费将不能保证消息的先后顺序。用过传统的消息系统的同学肯定清楚,消息的顺序处理很让人头痛。如果只让一个消费者处理消息,又违背了并行处理的初衷。 在这一点上Kafka做的更好,尽管并没有完全解决上述问题。 Kafka采用了一种分而治之的策略:分区。 因为Topic分区中消息只能由消费者组中的唯一一个消费者处理,所以消息肯定是按照先后顺序进行处理的。但是它也仅仅是保证Topic的一个分区顺序处理,不能保证跨分区的消息先后处理顺序。 所以,如果你想要顺序的处理Topic的所有消息,那就只提供一个分区。
Kafka作为一个消息系统
传统的消息有两种模式:队列和发布订阅。队列模式中,消费者池(a pool of consumers)从服务器中读取消息(每个消息只被其中一个读取);发布订阅模式则是消息广播给所有的消费者。
队列和发布订阅模式的优劣:队列的优点是允许多个消费者瓜分处理数据,这样可以扩展处理,但是队列没有多个订阅者,一旦读取进程读取了消息,消息就没有了(Unfortunately, queues aren't multi-subscriber—once one process reads the data it's gone.)。而发布订阅模式允许你广播给多个消费者,由于每个订阅者都订阅了消息,所以没有办法缩放处理。
Kafka比传统的消息系统有更强的顺序保证
传统的消息系统按照顺序保存数据,如果多个消费者从队列消费,则服务器按存储的顺序发送消息,但是跟在消费者中描述的原因一样,尽管服务器是按照顺序发送的看,但是消息却是异步传递到消费者的,因此消息可能乱序到达消费者,但如果不并行,性能就没办法保证。为了解决这个问题,Kafka=通过将topic的partion并行化处理,来实现顺序和负载均衡。每个partition仅由同一个消费者组中的一个消费者消费到,并确保消费者是该partition的唯一消费者,并按顺序消费数据。每个topic有多个分区,则需要对多个消费者做负载均衡。但是,相同的消费者组中不能有比分区更多的消费者,否则多出的消费者一直处于空等待,不会受到消息。(说明一下:这里是针对需要顺序读写的情况,如果不需要保证严格顺序的话,当然可以多个消费者消费)。
Kafka作为一个存储系统
任何允许发布消息,解耦使用消息的消息队列,都在本质上充当传输中途消息的存储系统。写入到Kafka的数据将写到磁盘并复制到集群中,从而保证集群的容错性。Kafka允许生产者等待写入完成的确认,这样在数据完全复制之前,写入是未完成的,并且即使写入服务器失败,也保证持久写入。因此可以认为Kafka是一种专用于高性能、低延迟、提交日志存储,复制和传播特殊用户的分布式文件系统。
Kafka用于流数据处理
仅仅读取、写入和存储数据流是不够的。Kafka的目的是实现流的实时处理。在Kafka中,流处理器的定义是:任何从输入主题接收数据流,对此输入执行一些处理,并生成持续的数据流道输出主题的组件。例如,零售应用程序可能会收到销售和出货的输入流,并输出根据该数据计算的重新排序和价格调整的输出流。这种情况下,可以直接使用producer和consumer API进行简单的处理。对于复杂的转换,Kafka提供了更强大的Streams API,可构建聚合计算或连接流到一起的复杂应用程序。这些功能可以有助于解决此类应用面临的一些硬性问题:处理无序的数据,代码更改的再处理、执行状态计算等。
合并在一起
消息系统,数据存储和流处理的这种组合似乎是不寻常的,但是这些特性对于Kafka作为流媒体平台的角色至关重要。 像HDFS这样的分布式文件系统允许存储用于批处理的静态文件。 本质上,这样的系统允许存储和处理来自过去的历史数据。 传统的企业邮消息系统允许处理将在您订阅之后到达的未来消息。 以这种方式构建的应用程序在未来数据到达时即使处理。 Kafka结合了这两种功能,这种组合对于Kafka作为流应用程序和流数据管道平台来说至关重要。 通过组合存储和低延迟订阅,流式应用程序可以以相同的方式处理过去和未来的数据。 这是一个单一的应用程序可以处理历史记录数据,而不是在到达最后一个记录时结束,它可以随着将来的数据到达而继续处理。 这是一个广泛的流处理概念,其中包含批处理以及消息驱动应用程序。 同样,对于流数据流水线,订阅到实时事件的组合使得可以使用Kafka进行非常低延迟的管道传输; 可靠地存储数据的能力使得可以将其用于必须保证数据传送的关键数据,或者与仅负载数据的离线系统集成,或者可能会长时间停机以进行维护。 流处理设备可以在数据到达时转换数据 有关Kafka提供的保证