初识Kafka

一、kafka介绍

Kafka是一种高吞吐量的分布式发布订阅消息系统,使用scala编写。

Kafka拥有作为一个消息系统应该具备的功能,有着独特的设计。它借鉴的JMS的规范思想,但未完全遵循JMS的规范。

Kafka是一个分布式的,分区的消息(commit log)服务。

二、基础的消息术语

  1、Topic

    Kafka按照topic分类来维护消息

  2、Producer

    将发布消息到topic的进程称之为生产者

  3、Consumer

    处理topic中的消息称之为消费者

  4、Broker

    Kafka以集群的方式运行,集群中的每一台机器称之为代理

  因此,从较高层面上讲,生产者通过网络将消息发布到Kafka集群,然后消费者进行消费。

                                                   

   服务端(brokers)与客户端之间(producer\consumer)的通信通过tcp协议来完成。

三、Topic与Log

  可以将Topic理解为一个类别的名称,所有的message发送到topic下面。对于每个topic,kafka按照如下方式维护一个分区(Partition)日志文件

            

  partition是一个有序的message序列,这些message按顺序添加到一个叫做commit log 的文件中。每个partition中都有一个唯一的编号,称之为offset,用来唯一标识某个分区中的message。在这里,值得一提的是,每个partition都对应一个commit-log。一个partition中的message 的offset是唯一,但是不同的partition中message的offset可能是相同的。

  kafka集群,在配置的时间范围内,维护所有由producer生成的消息,而不管这些消息有没有被消费。例如,日志保留时间被设置为两天,kafka会维护最近两天生产的消息,两天前的消息则会被丢弃。kafka的性能与保留的数据量大小没有关系,所以保存大量的数据(日志记录)不会有什么影响。

  每个consumer都是基于自己在commit-log中的消费进度(offset)来进行消费的。在kafka中,offset由consumer来维护,一般来说,我们按照顺序逐条消费commit-log中的消息。当然,我们可以通过指定offset来重复消费某些消息,或者跳过某些消息。这意味着kafka中的consumer对集群的影响是非常小的,添加一个或者减少一个consumer,都不会对集群或者其他consumer产生影响。因此,每个consumer维护各自的offset。

  对log进行分区,主要有以下目的:  

  1、当log文件大小超过系统文件限制时,可以自动拆分。每个partition对应的log都受到所在机器的系统文件大小的限制。但一个topic是有很多个分区的,因此可以处理任意数量的数据

  2、提高并行度

四、Distribution----分布式

  log的partitions分布在kafka集群中的不同broker上,每个broker可以请求备份其他broker上的partition上的数据。kafka集群支持配置一个partition备份的数量。针对每个partition,都有一个broker起到leader的作用,0个或多个broker起到follwers的作用。leader处理所有的针对这个partition的读写请求,同时follwers被动复制leader的结果。如果这个leader失效了,其中的一个follwer将会自动变为新的leader。每个broker都是自己管理的partition的leader,同时又是其他的broker所管理的partition的follwers, Kafka通过这种方式来达到负载均衡。

五、Producers

  生产者将消息发送到topic中,同时负责选择将message发送到topic中的哪个partition中。通过round-robin做简单的负载均衡,或者根据消息中的某个关键字来进行区分。通常后者使用居多。

六、Consumers

  传统的消息模式有两种:队列(queuing)、发布订阅(publish-subscribe)。f

  在queuing中,多个consumer从服务器读取数据,消息只会到达一个consumer。在publish-subscribe中,消息会广播给所有的consumer。kafka基于这两种模式提供了consumer的抽象概念---consumer group。每个consumer都要标记自己属于哪一个consumer-group。发布到tiopic中的message将会被传递到consumer-group中的consumer实例。consumer实例可以运行在不同的进程上,也可以在不同的物理机上。

  如果所有的consumer都在同一个consumer-group上,这就相当于传统的queue模式,并在众多的consumer instance之间进行负载均衡。

  如果所有的consumer都有着自己的唯一的consumer-group,这就类似于传统的publish-subscribe模式。

  更一般的情况是,通常一个topic有着几个consumer-group,每个consumer-group都是逻辑上的一个订阅者。每个consumer-group由多个consumer实例组成,从而达到可拓展、容灾的作用。这并没有特殊的地方,仅仅只是将publish-subscribe中的运行在单个进程上consumer替换成一个consumer-group。如图:

 

                

    说明:由2个broker组成的kafka集群,总共有4个Parition(P0-P3)。这个集群由2个Consumer Group, A有2个 consumer instances ,而B有四个.

七、消费顺序

  Kafka比传统的消息系统有着更加可靠的顺序保证。

  在传统的情况下,服务器按照顺序保留消息到队列中。如果有多个consumer来消费队列中的消息,服务器会按接受消息的顺序向外提供消息。但是,尽管服务器是按照顺序提供消息,但是每个消息传递到consumer是异步的。这就会存在先消费的consumer获取到消息的时间会变后一个consumer获取都消息的时间长,导致不能保证顺序性。所以当进行并行消费的时候,消息在多个consumer之间可能会失去顺序性。消息系统通常会采取一种exclusive consumer的概念来确保同一时间只有一个consumer能够从队列中进行消费,但这就意味在消息处理的过程中是不支持并行的。

  Kafka在这方面做的更好。通过topic中并行度的概念,即partition,Kafka可以同时提供顺序性保证和多个consumer同时消费时的负载均衡。实现原理就是通过一个topic中的partition分配给一个consumer-group中的不同的consumer instance。通过这种方式,我们可以保证一个partition在同一个时刻只有一个consumer instance在消费,从而保证顺序。虽然一个topic中有多个partition,但是一个consumer-group中也有多个consumer instance。通过合理的分配,依然能够保证负载均衡。需要注意的是一个consumer-group中的consumer instance数量不能比一个topic中的partition的数量多。

  kafka只在partition的范围内保证消息消费的顺序性,不能在同一个topic中的多个partition中保证顺序性。通常来说,这已经能够大部分应用的需求。但是假如真的存在需要在总体上保证顺序性,那么我们可以将topic的partition数量设置为1,consumer-group中的consumer instance数量也设置为1。

八、Guarantees

  从较高层面上来说的话,kafka提供了以下的保证:发送到一个topic的message会按照发生顺序添加到commit-log中。例如,M1、M2由同一个producer产生,M1比M2发送早,那么M1在commit-log中的offset就会比M2的小。一个consumer在commit-log按照发送顺序来消费message。

  如果一个topic的备份因子(replication-factor)设置为N,那么Kafka可以容忍N-1个服务器的失败,而存储在commit-log中的消息不会消失。  

 

posted @ 2018-08-06 23:43  SayAndDo  阅读(179)  评论(0编辑  收藏  举报