Kafka整理

常用消息中间件对比

  • Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache定级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。消息的消费者主动拉取消息。
  • RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。消息的消费者被动拉取(rabbitMQ 推送消息给消费者)。
  • RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。

kafka

In a very basic structure, a producer publishes messages to a Kafka topic (synonymous with “messaging queue”). A topic is also considered as a message category or feed name to which messages are published. Kafka topics are created on a Kafka broker acting as a Kafka server. Kafka brokers also store the messages if required. Consumers then subscribe to the Kafka topic (one or more) to get the messages. Here, brokers and consumers use Zookeeper to get the state information and to track message offsets, respectively
kafka整体图

apache kafka 是一种分布式的,基于发布/订阅的消息系统,由Scala语言编写而成,它具备快速,可扩展,可持久化的特点,其与如下几个主要关键特性有关:

  • Kafka具有近乎实时性的消息处理能力,即使面对海量消息也能够高效地存储消息和查询消息。Kafka将消息保存在磁盘中,在其设计理念中并不惧怕磁盘操作,它以顺序读写的方式访问磁盘,从而避免了随机读取磁盘导致的性能瓶颈。Kafka把数据以消息的形式持久化到磁盘,即使Kafka出现宕机,也可以保证数据不会丢失,为了避免磁盘上的数据不断增长,Kafka提供了日志清理,日志压缩等功能,对过时的,已经处理完成的数据进行清除。在磁盘操作中,耗时最长的就是寻道时间,这是导致磁盘的随机I/O性能很差的主要原因。
  • Kafka支持批量读写消息,并且会对消息进行批量压缩,这样既能提高了网络的利用率,也提高了压缩效率。
  • Kafka支持消息分区,每个分区中的消息保证顺序传输,而分区之间则可以并发操作,这样就提高了Kafka的并发能力。Kafka保证一个Partition内消息的有序性,但是不保证多个Partition之间的数据有顺序
  • Kafka支持在线增加分区,支持在线水平扩展。
  • Kafka支持为每个分区创建多个副本,其中只有一个Leader副本负责读写,其他副本只负责与Leader副本进行同步,这种方式提高了数据的容灾能力,Kafka会将Leader副本均匀地分布在集群的服务器上,实现性能最大化。Kafka的每个Topic(主题)都可以分为多个partition(分区),每个分区都有多个Replica(副本),实现消息冗余备份。每个分区中的消息是不同的,这类似于数据库中水平切分的思想,提高了并发读写的能力。而同一分区的不同副本中保存的是相同的消息,副本之间是一主多从的关系,其中Leader副本负责处理读写请求,Follower副本则只与Leader副本进行消息同步,当Leader副本出现故障时,则从Follower副本中重新选举Leader副本对外提供服务。
  • Kafka Consumer:Consumer使用pull方式从服务器端拉取消息,并且在Consumer端保存消费的具体位置(position),当消费者宕机后恢复上线,可以根据自己保存的消费位置重新拉取需要的消息进行消费,这就不会造成消息丢失,也就是说Kafka不决定何时,如何消费消息,而是Consumer自己决定何时,如何消费消息。
  • Consumer Group:可以将多个Consumer加入一个Consumer Group(消费组),在一个Consumer Group中,每个分区只能分配给一个Consumer消费,当Kafka服务端通过增加分区数量进行水平扩展后,可以向Consumer Group增加新的Consumer来提高整个Consumer Group的消费能力。当Consumer Group中的一个Consumer出现故障下线时,会通过Rebalance操作将下线Consumer负责处理的分区分配给其他Consumer进行处理;当下线Consumer重新上线加入Consumer Group时,会再进行一次Rebalance操作,重新分配分区。当然一个Consumer Group可以订阅多个不同Topic,每一个Consumer可以同时处理多个分区。

kafka 相关概念

  • 消息: 消息是Kafka中最基本的数据单元,消息由一串字节构成,其中主要由key和value构成,key和value也都是byte数组。key的主要作用是根据一定的策略,将此消息路由到指定的分区中,这样就可以保证包含同一个key的消息全部写入同一分区中,key可以是null。消息的真正有效负载是value部分的数据,为了提高网络和存储的利用率,生产者会批量发送消息到Kafka,并在发送之前对消息进行压缩。

  • Topic: A topic is a category or feed name to which messages are published by the message producers. In Kafka, topics are partitioned and each partition is represented by the ordered immutable sequence of messages. A Kafka cluster maintains the partitioned log for each topic. Each message in the partition is assigned a unique sequential ID called the offset.Topic是用于存储消息的逻辑概念,可以看做一个消息集合,每个Topic可以有多个生产者和消费者。每个Topic可以划分为多个分区(至少一个分区),每个消息在被添加到分区时,都会被分配一个offset,它是消息在此分区中的唯一编号,Kafka通过offset保证消息在分区内的顺序,offset的顺序性不跨分区。

    topic 分区 offset

  • Log: 分区在逻辑上对应着一个Log,当生产者将消息写入分区时,实际上是写入到分区对应的Log中,Log是一个逻辑概念,可以对应到磁盘上的一个文件夹,Log由多个Segment组成,每个Segment对应一个日志文件和索引文件,在面对海量数据时,为避免出现超大文件,每个日志文件的大小是有限制的,当超出限制后则会创建新的Segment,继续对外提供服务。这里要注意,因为Kafka采用顺序IO,所以只能向最新的Segment追加数据。为了权衡文件大小,索引速度,占用内存大小等多方面因素,索引文件采用稀疏索引的方式,大小并不会很大,在运行时会将其内容映射到内存中,提高索引速度。

  • 保留策略Retention Policy: 无论消费者是否已经消费了消息,Kafka都会一直保存这些消息,但并不会像数据库那样长期保存。为了避免磁盘被占满,Kafka都会配置相应的保留策略,以实现周期性地删除陈旧的消息,有如下两种保留策略
    (1)根据消息保留时间:当消息在Kafka中保存的时间超过了指定时间,就可以被删除;
    (2)根据Topic存储数据的大小:当Topic所占的日志文件大小大于一个阈值,则可以开始删除最旧的消息。
    Kafka会启动一个后台线程,定期检查是否存在可以删除的消息。保留策略的配置既可以全局配置也可以在Topic级别进行配置。

  • 日志压缩Log Compaction: Kafka会在后台启动一个线程,定期将相同key的消息进行合并,只保留最新的value值,如下图所示:

    日志压缩

  • Broker: A Kafka cluster consists of one or more servers where each one may have one or more server processes running and is called the broker. Topics are created within the context of broker processes. 一个单独的Kafka server就是一个Broker,Broker的主要工作就是接收生产者发过来的消息,分配offset,之后保存到磁盘中;同时接收消费者,其他Broker的请求,根据请求类型进行相应处理并返回响应。

  • 副本 Replica:

    副本
    kafka副本机制

  • ISR(IN-Sync Replica):

    ISR

  • HW(high watermark): HW标记了一个特殊的offset,当消费者处理消息的时候,只能拉取到HW之前的消息,HW之后的消息对消费者来说是不可见的,与ISR集合类似,HW也是由Leader副本管理的,当ISR集合中全部的Follower副本都拉取HW指定消息进行同步后,Leader副本会递增HW的值。Kafka官网将HW之前的消息状态称为“commit”,其含义是这些消息在多个副本中同时存在,即使此时Leader副本损坏,也不会出现数据丢失。

  • LEO(Log End Offset): LEO是所有的副本都会有的一个offset标记,它指向追加到当前副本的最后一个消息的offset,当生产者向Leader副本追加消息的时候,Leader副本的LEO标记会递增;当Follower副本成功从Leader副本拉取消息并更新到本地的时候,Follower副本的LEO就会增加。

    HW & LEO例子

  • 同步复制Synchronous replication: In synchronous replication, a producer first identifies the lead replica from ZooKeeper and publishes the message. As soon as the message is published, it is written to the log of the lead replica and all the followers of the lead start pulling the message; by using a single channel, the order of messages is ensured. Each follower replica sends an acknowledgement to the lead replica once the message is written to its respective logs. Once replications are complete and all expected acknowledgements are received, the lead replica sends an acknowledgement to the producer. On the consumer’s side, all the pulling of messages is done from the lead replica.

  • 异步复制Asynchronous replication: The only difference in this mode is that, as soon as a lead replica writes the message to its local log, it sends the acknowledgement to the message client and does not wait for acknowledgements from follower replicas. But, as a downside, this mode does not ensure message delivery in case of a broker failure.

    通过ISR解决同步复制和异步复制的缺点

  • Zookeeper: ZooKeeper serves as the coordination interface between the Kafka broker and consumers. The ZooKeeper overview given on the Hadoop Wiki site is as follows (http://wiki.apache.org/hadoop/ZooKeeper/ProjectDescription):
ZooKeeper allows distributed processes to coordinate with each other through a shared hierarchical name space of data registers (we call these registers znodes), much like a file system.

The main differences between ZooKeeper and standard filesystems are that every znode can have data associated with it and znodes are limited to the amount of data that they can have. ZooKeeper was designed to store coordination data: status information, configuration, location information, and so on.

  • Producers: Producers publish data to the topics by choosing the appropriate partition within the topic. For load balancing, the allocation of messages to the topic partition can be done in a round-robin fashion or using a custom defined function.生产者的主要工作是生产消息,并将消息按照一定的规则推送到Topic的分区中,其中规则可以是根据消息的key的hash值选择分区,或按序轮询全部分区的方式等。
  • Consumer: Consumers are the applications or processes that subscribe to topics and process the feed of published messages
    消费者
  • Cluster和Controller: 多个Broker可以做成一个Cluster(集群)对外提供服务,每个Cluster当中会选举出一个Broker来担任Controller,Controller是kafka集群的指挥中心,而其他Broker则听从Controller指挥实现相应的功能,Controller负责管理分区的状态,管理每个分区的副本状态,监听Zookeeper中数据的变化等工作。Controller也是一主多从的实现,所有Broker都会监听Controller Leader的状态,当Leader Controller出现故障的时则重新选举新的Controller Leader.

kafka 设计

kafka自定义了一套网络协议,只要遵守这套协议格式,就可以向Kafka发送消息,也可以从Kafka拉取消息。

kafka producer

kafka producer整理处理流程

kafka server

kafka server整体流程

kafka 日志存储

  kafka使用日志文件的方式保存生产者发送的消息,每条消息都有一个offset值来表示它在分区中的偏移量,这个offset值是逻辑值,并不是消息实际存储的物理地址。offset值类似于数据库表中的主键,主键唯一确定了数据库表中的一条记录,offset唯一确定了分区中的一条消息,Kafka对应的逻辑存储机制如下图:

kafka 逻辑存储图
 为了提高写入的性能,同一个分区中的消息是顺序写入的,这就避免了随机写入带来的性能问题。一个Topic可以分成多个分区,每一个分区可以有多个副本,当一个分区副本(无论是Leader副本还是Follower副本)被划分到某个Broker上时,Kafka就要在此Broker上为此分区建立相应的Log,而生产者发送的消息会存储在Log中,供消费者拉取后消费。
 Kafka中存储的一般是海量消息数据,为了避免日志文件过大,Log并不是直接对应于磁盘上的一个日志文件,而是磁盘上的一个目录,这个命令的命名规则是_,Log与分区之间的关系是一一对应的,对应分区中的全部消息都存储在此目录下的日志文件中。
 Kafka通过分段的方式将Log分为多个LogSegment,LogSegment是一个逻辑上的概念,一个LogSegment对应磁盘上的一个日志文件和一个索引文件,其中日志文件用于记录消息,索引文件用于保存消息的索引;随着消息的不断写入,日志文件的大小到达一个阈值时,就创建新的日志文件和索引文件继续写入后续的消息和索引信息,日志文件的命名规则是[baseOffset].log,baseOffset是日志文件中第一条消息的offset,如下图所示:
Log日志存储

 为了提高查询消息的效率,每个日志文件都对应一个索引文件,这个索引文件并没有为每天消息都建立索引项,而是使用稀疏索引方式为日志文件汇总的部分消息建立索引,如下图所示:
Log 日志对应的索引

kafka命令行工具

  • kafka代理启动:
>>>bin/kafka-server-start.sh config/server.properties
  • 创建kafka Topic:
>>>bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic kafkatopic
  • 生产者投递消息:
>>>bin/kafka-console-producer.sh --broker-list localhost:9092 --topic kafkatopic
  • 消费者消费消息:
>>>bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic kafkatopic --from-beginning

参考

  1. Apache kafka源码书籍
  2. Learing apache kafka 书籍

你可能感兴趣的:(Kafka整理)