Kafka 架构

Kafka基础架构

  1. Kafka架构中涉及到 Kafka集群(多个Broker)、 生产者(生产消息) 、 消费者(消费消息) 、 zookeeper(注册消息)

  2. Kafka集群

    • Kafka集群由多个broker组成,每个broker都有唯一的id。
    • Kafka内部维护Topics,每个topic可以有多个分区partition,每个partition是一个有序的队列。
    • 为了提高可靠性,每个分区可以有多个副本replication,每个副本有各自的角色 'leader/follower',所有的读写都是由leader负责。
    说明:
    • 每个topic在逻辑上为一个队列,但在物理上被划分为了多个分区,每个消息队列的分区会分布在多个集群上,但集群的各个节点吞吐能力可能不同,此时可以根据不同节点消费的不同分区数据去处理各自区内的吞吐,从而提高吞吐量。
    • 每个topic的多个分区可以存在到一个broker。
    • 每个Topic的一个分区的多个副本必须在不同的broker。
    • 每个Partition 是一个有序的队列。
    • Replia 副本: Kafka 提供了副本机制,每个topic的每个分区都有若干个副本,一个leader和若干个follower,用来保证集群某个节点故障时,该节点上的partition数据不丢失。
  3. 生产者-Producer

    • 生产者的主要作用就是面向Topic生产数据,将生产的数据发送给Broker中的Topic。
  4. 消费者-Consumer

    • 消费者主要是以消费者组的名义面向topic进行消息的消费。
    说明:
    • 每个消费者组中的一个消费者可以同时消费一个topic中的多个分区的数据,但每个topic的一个分区只能被一个消费者组中的一个消费者消费。
    • 消费者在消费数据的过程中需要实时记录offset(消费的位置), 记录的方式为: 'group + topic + partition',而offiset在kafka中有一个topic用于专门维护offset,该topic比较特殊,有50个分区和1个副本。
    • 消费者组本质上是一个消费者,当一个消费者组中的一个消费者对应一个分区,单个消费者组正好消费完一个topic时效率最高。
  5. Zookeeper

    • Kafka中topic之间的协调依赖于zookeeper运行,Zookeeper主要的作用就是让kafka去注册消息。

      例如:每个broker启动后会在zookeeper中注册,并 "选举controller" ,实际上就是抢,谁抢到谁是爹,先起的服务器有优势。在低版本0.9之前,消费者维护的offset存储在zk中。在0.9版本之后,消费者维护的offset存储在kafka本地. 注:这与SparkStreaming消费kafka数据的API版本对应。

消费者消费数据的两种模式

  1. 消息队列推送的方式:
    • 该模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。推送的方式只能按照消费者消费速率最小的为准,由于消息队列不清楚每个消费者的消费水平,不方便推送。
  2. 消费者主动拉取的方式:
    • 通过消费者自己主动来拉取,但消费者并不知道消息队列是否有消息,所以以长轮询的方式不停的拉取,但是若消息队列中始终没有消息,则会不停的去拉取,效率会很低,所以维护了一个时长参数timeout,如果当前没有数据可供消费,Consumer 会等待一段时间之后再返回,这段时长即为timeout。

Kafka工作流程及文件存储

  • Kafka中消息是以topic进行分类的,生产和消费面向的都是topic,以及用来记录消费者消费信息的位置的offset也是以topic形式。

    而topic是逻辑上的概念,实际上是以partition存储的,每个partition对应一个log文件,用来存储生产者生产的数据,生产者生产的数据会被不断的的追加到该文件末尾,并且每条数据有自己的offset,用来记录消费者消费到了那条消息,以便出错时恢复到上次消费的位置继续消费消息。但是由于不断的向log文件中追加消息,会导致该文件过大造成效率变低,所以Kafka采用了分片加索引的机制,将每个分区分为多个segment,每个segment默认1个G, 由index和log文件组成, log 文件用来存储消息信息,index 用来存储 offset 以及消息在文件中的物理偏移量。

  • segment:文件命名规则为topic名称+分区序号

  • log、index:文件以当前segment的第一条消息的offset命名,这样将文件划分为不同的区间可以快速定位到某个消息所在的文件。

说明:

为了避免offset过长导致所占文件空间很大的情况下,每个index的offset都是从0开始的,然后用offset-文件名序号即可。而消息的索引并不是每条消息都有索引,实际上采用的是松散索引,定位了一个范围,每次消费的时候会多查一小部分。

posted @ 2021-05-26 22:12  yuexiuping  阅读(95)  评论(0编辑  收藏  举报