kafka入门介绍

Kafka作为一个分布式的流平台,这到底意味着什么?

我们认为,一个流处理平台具有三个关键能力:

  1. 发布和订阅消息(流),在这方面,它类似于一个消息队列或企业消息系统。
  2. 容错的方式存储消息(流)。
  3. 在消息流发生时处理它们。
什么是kakfa的优势?

它应用于2大类应用:

  1. 构建实时的流数据管道,可靠地获取系统和应用程序之间的数据。
  2. 构建实时流的应用程序,对数据流进行转换或反应。

要了解kafka是如何做这些事情的,让我们从下到上深入探讨kafka的能力。

首先几个概念:
  1. kafka作为一个集群运行在一个或多个服务器上。
  2. kafka集群存储的消息是以topic为类别记录的。
  3. 每个消息(也叫记录record,我习惯叫消息)是由一个key,一个value和时间戳构成。
kafka有四个核心API:
  • 应用程序使用 Producer API 发布消息到1个或多个topic(主题)。
  • 应用程序使用 Consumer API 来订阅一个或多个topic,并处理产生的消息。
  • 应用程序使用 Streams API 充当一个流处理器,从1个或多个topic消费输入流,并生产一个输出流到1个或多个输出topic,有效地将输入流转换到输出流。
  • Connector API允许构建或运行可重复使用的生产者或消费者,将topic连接到现有的应用程序或数据系统。例如,一个关系数据库的连接器可捕获每一个变化。

screenshot

Client和Server之间的通讯,是通过一条简单、高性能并且和开发语言无关的TCP协议。并且该协议保持与老版本的兼容。Kafka提供了Java Client(客户端)。除了Java Client外,还有非常多的其它编程语言的Client

首先来了解一下Kafka所使用的基本术语:

Topic

Kafka将消息种子(Feed)分门别类,每一类的消息称之为一个主题(Topic).

Producer

发布消息的对象称之为主题生产者(Kafka topic producer)

Consumer

订阅消息并处理发布的消息的种子的对象称之为主题消费者(consumers)

Broker

已发布的消息保存在一组服务器中,称之为Kafka集群。集群中的每一个服务器都是一个代理(Broker). 消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息。

主题和日志 (Topic和Log)

让我们更深入的了解Kafka中的Topic。

Topic是发布的消息的类别或者种子Feed名。对于每一个Topic,Kafka集群维护这一个分区的log,就像下图中的示例:

screenshot

每一个分区都是一个顺序的、不可变的消息队列, 并且可以持续的添加。分区中的消息都被分了一个序列号,称之为偏移量(offset),在每个分区中此偏移量都是唯一的。

Kafka集群保持所有的消息,直到它们过期, 无论消息是否被消费了。 实际上消费者所持有的仅有的元数据就是这个偏移量,也就是消费者在这个log中的位置。 这个偏移量由消费者控制:正常情况当消费者消费消息的时候,偏移量也线性的的增加。但是实际偏移量由消费者控制,消费者可以将偏移量重置为更老的一个偏移量,重新读取消息。 可以看到这种设计对消费者来说操作自如, 一个消费者的操作不会影响其它消费者对此log的处理。 再说说分区。Kafka中采用分区的设计有几个目的。一是可以处理更多的消息,不受单台服务器的限制。Topic拥有多个分区意味着它可以不受限的处理更多的数据。第二,分区可以作为并行处理的单元,稍后会谈到这一点。
screenshot

分布式(Distribution)

Log的分区被分布到集群中的多个服务器上。每个服务器处理它分到的分区。 根据配置每个分区还可以复制到其它服务器作为备份容错。 每个分区有一个leader,零或多个follower。Leader处理此分区的所有的读写请求,而follower被动的复制数据。如果leader宕机,其它的一个follower会被推举为新的leader。 一台服务器可能同时是一个分区的leader,另一个分区的follower。 这样可以平衡负载,避免所有的请求都只让一台或者某几台服务器处理。

Geo-Replication(异地数据同步技术)

Kafka MirrorMaker为群集提供geo-replication支持。借助MirrorMaker,消息可以跨多个数据中心或云区域进行复制。 您可以在active/passive场景中用于备份和恢复; 或者在active/passive方案中将数据置于更接近用户的位置,或数据本地化。

生产者(Producers)

生产者往某个Topic上发布消息。生产者也负责选择发布到Topic上的哪一个分区。最简单的方式从分区列表中轮流选择。也可以根据某种算法依照权重选择分区。开发者负责如何选择分区的算法。

消费者(Consumers)

通常来讲,消息模型可以分为两种, 队列和发布-订阅式。 队列的处理方式是 一组消费者从服务器读取消息,一条消息只有其中的一个消费者来处理。在发布-订阅模型中,消息被广播给所有的消费者,接收到消息的消费者都可以处理此消息。Kafka为这两种模型提供了单一的消费者抽象模型: 消费者组 (consumer group)。 消费者用一个消费者组名标记自己。 一个发布在Topic上消息被分发给此消费者组中的一个消费者。 假如所有的消费者都在一个组中,那么这就变成了queue模型。 假如所有的消费者都在不同的组中,那么就完全变成了发布-订阅模型。 更通用的, 我们可以创建一些消费者组作为逻辑上的订阅者。每个组包含数目不等的消费者, 一个组内多个消费者可以用来扩展性能和容错。正如下图所示:
screenshot2个kafka集群托管4个分区(P0-P3),2个消费者组,消费组A有2个消费者实例,消费组B有4个。

正像传统的消息系统一样,Kafka保证消息的顺序不变。 再详细扯几句。传统的队列模型保持消息,并且保证它们的先后顺序不变。但是, 尽管服务器保证了消息的顺序,消息还是异步的发送给各个消费者,消费者收到消息的先后顺序不能保证了。这也意味着并行消费将不能保证消息的先后顺序。用过传统的消息系统的同学肯定清楚,消息的顺序处理很让人头痛。如果只让一个消费者处理消息,又违背了并行处理的初衷。 在这一点上Kafka做的更好,尽管并没有完全解决上述问题。 Kafka采用了一种分而治之的策略:分区。 因为Topic分区中消息只能由消费者组中的唯一一个消费者处理,所以消息肯定是按照先后顺序进行处理的。但是它也仅仅是保证Topic的一个分区顺序处理,不能保证跨分区的消息先后处理顺序。 所以,如果你想要顺序的处理Topic的所有消息,那就只提供一个分区。

Kafka的保证(Guarantees)

  • 生产者发送到一个特定的Topic的分区上,消息将会按照它们发送的顺序依次加入,也就是说,如果一个消息M1和M2使用相同的producer发送,M1先发送,那么M1将比M2的offset低,并且优先的出现在日志中。
  • 消费者收到的消息也是此顺序。
  • 如果一个Topic配置了复制因子(replication factor)为N, 那么可以允许N-1服务器宕机而不丢失任何已经提交(committed)的消息。

有关这些保证的更多详细信息,请参见文档的设计部分。

kafka作为一个消息系统

Kafka的流与传统企业消息系统相比的概念如何?

传统的消息有两种模式:队列发布订阅。 在队列模式中,消费者池从服务器读取消息(每个消息只被其中一个读取); 发布订阅模式:消息广播给所有的消费者。这两种模式都有优缺点,队列的优点是允许多个消费者瓜分处理数据,这样可以扩展处理。但是,队列不像多个订阅者,一旦消息者进程读取后故障了,那么消息就丢了。而发布和订阅允许你广播数据到多个消费者,由于每个订阅者都订阅了消息,所以没办法缩放处理。

kafka中消费者组有两个概念:队列:消费者组(consumer group)允许同名的消费者组成员瓜分处理。发布订阅:允许你广播消息给多个消费者组(不同名)。

kafka的每个topic都具有这两种模式。

kafka有比传统的消息系统更强的顺序保证。

传统的消息系统按顺序保存数据,如果多个消费者从队列消费,则服务器按存储的顺序发送消息,但是,尽管服务器按顺序发送,消息异步传递到消费者,因此消息可能乱序到达消费者。这意味着消息存在并行消费的情况,顺序就无法保证。消息系统常常通过仅设1个消费者来解决这个问题,但是这意味着没用到并行处理。

kafka做的更好。通过并行topic的parition —— kafka提供了顺序保证和负载均衡。每个partition仅由同一个消费者组中的一个消费者消费到。并确保消费者是该partition的唯一消费者,并按顺序消费数据。每个topic有多个分区,则需要对多个消费者做负载均衡,但请注意,相同的消费者组中不能有比分区更多的消费者,否则多出的消费者一直处于空等待,不会收到消息

kafka作为一个存储系统

所有发布消息到消息队列和消费分离的系统,实际上都充当了一个存储系统(发布的消息先存储起来)。Kafka比别的系统的优势是它是一个非常高性能的存储系统

写入到kafka的数据将写到磁盘并复制到集群中保证容错性。并允许生产者等待消息应答,直到消息完全写入。

kafka的磁盘结构 - 无论你服务器上有50KB或50TB,执行是相同的。

client来控制读取数据的位置。你还可以认为kafka是一种专用于高性能,低延迟,提交日志存储,复制,和传播特殊用途的分布式文件系统

kafka的流处理

仅仅读,写和存储是不够的,kafka的目标是实时的流处理。

在kafka中,流处理持续获取输入topic的数据,进行处理加工,然后写入输出topic。例如,一个零售APP,接收销售和出货的输入流,统计数量或调整价格后输出。

可以直接使用producer和consumer API进行简单的处理。对于复杂的转换,Kafka提供了更强大的Streams API。可构建聚合计算连接流到一起的复杂应用程序。

助于解决此类应用面临的硬性问题:处理无序的数据,代码更改的再处理,执行状态计算等。

Sterams API在Kafka中的核心:使用producer和consumer API作为输入,利用Kafka做状态存储,使用相同的组机制在stream处理器实例之间进行容错保障。

拼在一起

消息传递,存储和流处理的组合看似反常,但对于Kafka作为流式处理平台的作用至关重要。

像HDFS这样的分布式文件系统允许存储静态文件来进行批处理。这样系统可以有效地存储和处理来自过去的历史数据。

传统企业的消息系统允许在你订阅之后处理未来的消息:在未来数据到达时处理它。

Kafka结合了这两种能力,这种组合对于kafka作为流处理应用和流数据管道平台是至关重要的。

批处理以及消息驱动应用程序的流处理的概念:通过组合存储和低延迟订阅,流处理应用可以用相同的方式对待过去和未来的数据。它是一个单一的应用程序,它可以处理历史的存储数据,当它处理到最后一个消息时,它进入等待未来的数据到达,而不是结束。

同样,对于流数据管道(pipeline),订阅实时事件的组合使得可以将Kafka用于非常低延迟的管道;但是,可靠地存储数据的能力使得它可以将其用于必须保证传递的关键数据,或与仅定期加载数据或长时间维护的离线系统集成在一起。流处理可以在数据到达时转换它。

有关Kafka提供的保证,api和功能的更多信息,可继续查阅本网






发表于: 4年前   最后更新时间: 1年前   游览量:136072
上一条: Apache Kafka下载
下一条: Kafka的使用场景

  • 请问下,我的kafka服务 一个broker,一个分区,一条消息发送到topic成功后,消费者隔了很久(大概十几秒)才能接收到消息,感觉这延迟有点长,这是怎么回事呢?
    请教一下,如果有个topic 有两个 分区A,B 只有一个消费者C去消费这两个分区,如果C这次拉取了分区A的消息,那么下次是一定会从B拉取消息吗(如果这段时间内分区B有新的数据进来)
    • 再问一下,如果某个消费组-A曾经消费过topic-T, 后来程序停止后过了比较长一段时间,这个消费组-A会被删掉吗, 比如说我重新起用这个进程用同样的消费组-A去消费这个topic-T,那这个A的offset是从上次消费的点开始,还是算新加进来的consumer 从最早或最新开始消费
        大佬,如果可以的话,可以帮我解答下我的疑问吗?多谢~
        一、分区
        1.如果一个topic分为3个分区,生成者发送消息的时候,是不是选择一个分区并发送?
        意思是三个分区的消息是不同,而不是一个消息发送到三个分区?

        2.如果一个topic分为3个分区,一个消费者组有两个消费者,一个消费者对应一个分区。那么剩余的一个分区的消息
        是不是没消费者消费?还是消费者组的两个消费者中的一个去消费?如果是这样,那么一个消费者岂不是对应两个分区了?

        3.如果一个topic分为3个分区,一个消费者组有两个消费者,一个消费者对应一个分区。那么消费者维护的offset 。是不是
        其对应分区的offset.而不是对topic的offset?

        4.一个消费者对应一个分区,是不是可以这样理解:
        (1).一个消费者只能固定消费一个分区的数据,并且不可改变消费的分区?
        如果是这样理解。那么一个topic有三个分区,一个消费者组有两个消费者,那么岂不是另外的一个分区的消息
        没消费者消费?
        (2).还有另外一种理解:一个topic有三个分区(A,B,C三个分区),一个消费者组有两个消费者(X,Y消费者)。
        那么一个消费者组的两个消费者消费三个分区的消息。那么同一个分区的消息只能随机被同一个的消费者组
        的一个消费者消费。但是如果这样理解。那么消费者维护的offset是什么呢?
        或者说一个消费者组维护三个分区的offset,如果X消费者消费了A分区的消息,A分区对应的offset+1.
        如果Y消费者消费者了A分区的消息,A分区的offset 也 +1 ?

        二、消费者(队列和发布-订阅式)
        1。生产者发送一个消息到broker,假设这个消息对应的topic有三个分区。这个消息存到三个分区的某一个。
        那么消息被广播给所有订阅该topic的消费者/消费者组。消费者/消费者组收到该消息后然后通过pull方式从服务器拉取消息并消费?
        • 一、
          1、均匀的发到这3个分区中。
          2、2个消费者中的一个去消费剩余的分区。
          3、是的
          4
          1)重启或故障则会被组中的其他成员消费,消费者数 <= 分区数,消费者多的话就会有消费者空闲着,少的话一个消费者会多消费几个分区。
          2)消费者组中的成员(X,Y),比如X分到了(A,B),Y分到了(C),那么X就维护A和B的offset,Y则维护C的offset。topic的分区在同一时刻只属于一个消费者。
          二、
          嗯,kafka的消费者是主动拉取消息的。
            • 如果一个topic有A,B,C三个分区,一个消费者组有X,Y两个消费者,假设刚开始的时候X分到了(A,B),Y分到了(C),当X消费者没有挂掉,那么
              就会一直保持X分到了(A,B),Y分到了(C)这种状态?直到X消费者挂掉,然后Y消费者维护A,B,C三个分区的offset?
                您好,请教下,我看文章然后又看了评论,忽而明白忽而糊涂啊。
                您说过 “当消费者宕掉的时候,其他的消费者才能消费,始终是1个分区对应1个消费者。” 这里明确了1个分区对应1个消费者。
                然后又看到您说 “广播只是概念名词,简单来说,kafka中有10条消息,消费者组A,组B,组C 。。等,会同时拿到这10条消息,消息组A中的消费者们会瓜分这10条消息。消费者是主动拉取的,长轮询。” 那消费组A中既然瓜分了消息,那么A中可能所有消费者都对应具体的某一个分区啊,这与您说的“1个分区对应1个消费者” 相违背啊。请指教,感谢。
                正常情况当消费者消费消息的时候,偏移量也线性的的增加;请问这个怎么理解 是说当发布者发布消息到队列后是没偏移量的 只有消费者消费了才会增加?
                请问你为何如此优秀?
                受教了!一直想找一篇关于kafaka的比较完整又比较新的技术文档,现在终于找到了。希望大佬能持续更新,供我们这些菜鸟学习,非常感谢!!
                您好,看你有个特别标注的红色部分不是很明白。
                “假如所有的消费者都在一个组中,那么这就变成了queue模型”,“相同的消费者组中不能有比分区更多的消费者,否则多出的消费者一直处于空等待,不会收到消息”
                ---------
                假设一个topic下有两个分区p0 p1,三个消费者c0 c1 c2在同一个组里。按第一句中应该没有提到partition的概念,也就是消息会逐个丢给c0 c1 c2,类似queue模式----也就是c0 c1 c2都有可能消费到对吧?但是按你第二句里说法,会有一个消费者空等待?感觉跟第一句矛盾了啊。
                求指教。
                • 也就是一旦一个消费者消费了一个partition,就会一直固定消费的,对吧?想想好像也是,要维护offset,如果在不同的partition似乎也不好实现了?
                    您好,请教下,若一个topic有3个分区:partition0,partition1,partition2;如果一个consumer group中有多个consumer,对于partition0中的消息,在没有给consumer指定分区的情况下,是随机分配给一个consumer,还是会一直分配一个固定的一个consumer。若是随机的话,默认分配策略是平均分配么?   若partition0中消息可由同组的多个consumer消费,那么如何保证一个分区的消息是被顺序消费的?该分区消息的offset是每个consumer都维护一个吗,若是的话,多个consumer是如何保证消息不被重复消费的?谢谢
                    • consumer组内的成员平分消息,如果你有3个分区,A消费组有4个消费者,那么将有一个消费者永远拿不到消息。 每个分区都是顺序的,但是因为你的消费者程序处理消息的速度不一样,所以最终无法保证顺序,如果你想保证顺序,那只能1个分区。
                        • 一个分区的话,消息也是平均分配给A消费者组的3个consumer是吗?
                          我看文章中写到“每个partition仅由同一个消费者组中的一个消费者消费到。并确保消费者是该partition的唯一消费者,并按顺序消费数据。”这里说的是“唯一消费者”,也就是说对于一个topic中的一个分区中的数据,是被订阅该topic的消费者组中固定的一个consumer消费是吗?是不能改变的?
                            请教一下,kakfa每次消费拉取数据的时候,如何确定去哪一个partition拉取数据,是系统随机指定,还是根据什么规则来分配
                            • 如果一个topic 有3个分区(A1,A2,A3),订阅该topic的一个消费者组有三个消费者(B1,B2,B3).一个分区对应一个消费者,假如分区A1对应B1消费者,
                              分区A2对应B2消费者,分区A3对应B3消费者。如果一个生产者发送消息存到A分区里面。如上面所说,去哪一个partition拉取数据,系统随机指定,
                              假设系统去B分区拉取数据,岂不是拉取不到数据?
                                • 如果一个生产者发送消息存到A分区里面。然后广播给消费者组,假如消费者去随机去B分区拉取数据。那么拉取不到数据。但是生产者发送到A分区的消息啥时候能被消费者消费啊?难不成等下一个生产者发送该topic的消息。然后A分区的消息才有几率被消费,但不是100%?
                                    • 大佬,我的意思是:如果一个生产者发送消息存到A分区里面。然后广播给消费者组,只广播一次吗?然后消费者组只拉取一次数据吗?
                                      还是这种说法:如果一个topic 有3个分区(A1,A2,A3),订阅该topic的一个消费者组有三个消费者(B1,B2).一个分区对应一个消费者。B1维护(A1,A2)分区,B2维护(A3)分区。如果一个生产者发送消息存到A分区里面。消费者组收到广播的消息后,B1,B2消费者同时去其维护的分区拉取数据并消费。
                                      B1去(A1,A2)分区拉取数据,B2去(A3)分区拉取数据,
                                      此时,由于生产者发送消息存到A分区里面,那么只有B1能消费消息?

                                        • 也就是说当消费者组收到广播的消息后,然后通知消费者B1,B2分别去其维护的分区拉取数据。如果有消息就消费。也就是一个消费者组收到广播消息后,是去三个分区去数据,而不是随机选择一个分区去拉取数据?
                                            • 你误会“随机”了,我的随机指的是消费者和分区分配的随机。
                                              比如,消费者组(X,Y),X可能分到(B、C),也可能分到(A、C)、一旦分配好后,就各自维护自己的消费了。