原文地址:https://kafka.apache.org/documentation.html#semantics

  1、开始

  1.1 引言

  Kafka是一个分布式,分区队列,冗余备份的消息存储服务。它是一个有独特设计的消息系统。

  这是什么意思呢?

  首先我们介绍下相关的基本通信概念:

  1.Kafka按主题分布消息。

  2.生产者发布消息给Kafka主题。

  3.消费者订阅并处理被提供的发布出的信息。

  4.Kafka作为由一个或多个中介服务的集群运行。

  然后,深入一些,生产者通过网络发送消息给用于提供给消费者服务的Kafka集群,如图:

                        Kafka 文档引言-LMLPHP

  在客户端和服务器之间只是进行高性能,与语言无关的TCP协议通信。

  主题和消息存储

  让我们先看看Kafka上层的概念---主题

  主题是消息被发布到的分类或空间。对于每个主题,Kafka集群都维护一个如下图的分段空间:

                        Kafka 文档引言-LMLPHP

  每个分段空间都是有序的,消息按固定的顺序不停的附加到消息存储位置。分段空间中的所有消息都会分配一个顺序ID用来在分段中唯一标示每一条消息。

  无论发布的消息是否被消费,它们都会被Kafka集群根据配置保留一段时间。比如,消息保留设置为两天,那么从发布时开始到被丢弃释放空间,有两天时间消息对消费者都是可用的。数据的大小对Kafka性能的稳定没有太大影响,保持大量数据也不会造成问题。

  事实上,消费者仅持有基本的描述存储的消费指向的元数据---偏移量。偏移量由消费者控制:一般情况下,消费者读取消息时偏移量也会线性增加,但事实上是否线性是由消费者控制的,它可以按照它希望的任何顺序消费消息。例如,消费者可以重置偏移量来重新消费消息。

  这些设计使得Kafka的消费者负担很小,它们运行几乎不会受到集群或其他消费者的影响。例如,你可以在不影响现有消费者消费的情况下,在命令行工具中跟踪任何主题的内容。

  分布式

  存储消息的分区分布在Kafka的服务器集群上,集群中的每个服务器处理分配给它的数据和请求。同时,用于容错,每个分区的数据都可以配置在一定数量的服务器上做备份。

  每个分区都是由一个中心服务器和不定数量的从服务器组成。中心服务器处理所有对分区的读写请求并分发给从服务器。如果中心服务器挂了,从服务器中会自动选举一个成为新的中心服务器。通过这种方式,将集群中的中心服务器和从服务器负载均衡。

  生产者

  生产者发布消息到选定的主题。它负责选取消息分配到所选主题的分区中。分配的方式可以是循环的平均分配,也可能是通过一些分区函数(常说的基于消息中的一些KEY)。更常见的是通过权重。

  消费者

  消息通讯通常有两种模式:消息队列和发布订阅。消息队列的方式,有一个消费者池从服务器读取消息,每个消息最终都会被池中的某一个消费者消费。发布订阅方式,消息会广播给所有消费者。Kafka中充当消费者的是消费者组,它同时支持这两种模式。

  消费者使用消费者组名订阅消息,每个发布给主题的消息都会发送给已订阅的消费者组中的一个消费者实例。消费者实例可以在独立的进程或独立的机器中。

  如果所有的消费者都在一个消费者组中,那就如普通的消息队列对所有消费者做了负载均衡一样。

  如果所有的消费者都在不同的消费者组中,结果就如发布订阅方式相同,消息被广播给所有的消费者。

  相比这两种情况,更常见的是,每个主题都有少量消费者组作为逻辑订阅者。考虑到扩展和容错,每个组由多个消费者实例组成。其实,这只是订阅发布过程中的订阅方从单一变为了由消费者集群组成而已。

                      Kafka 文档引言-LMLPHP

                一个两台服务器的Kafka 集群分4个分段(P0-P3)带两个消费者组。消费者组A有两个消费者实例组B有4个。

Kafka 比传统消息系统在消息顺序的保障上更健壮。

  传统的消息队列维持消息在服务器端有序,多个消费者从服务器端维持有序存储消息的队列中消费。虽然服务器端有序的维护消息,单消息被异步发送给消费者,于是消息难以有序的到达不同的消费者。这意味着在并行消费的过程中,消息的有序性被破坏了。消息系统通常处理这种情况是以独占消费的方式在单个过程中只允许从一个队列消费,只是这样就不能并发处理消息了。

  Kafka 在这点上做的更好。主题内分区本身就带有并行的意味。Kafka 既可以保证消息的顺序又可以为消费者进程池做负载均衡。通过将主题中的分区分配给消费者组中的消费者可以做到每一个分区能准确的被消费者组中的一个消费者消费。通过这种方式,我们确保分区只能被一个消费者按顺序读取并消费。多个分区会均衡的负载给多个消费者实例。然而,值得注意的是,消费者实例不能比分区的数量多。

  Kafka 只提供一个分区内消息的绝对顺序,而不是一个主题中不同分区的。分区通过索引结合KEY的方式提供分区数据来满足更多的应用。也就是说,想在一个主题内保证消息顺序,那就只能有一个分区,同时也意味着只能有一个消费者进程。

  保证声明

  Kafka 可以确保下列情况:

  消息被生产者发送给特定的主题分区,然后会按照发送的顺序被加入分区中。

  消费者实例按照存储也就是加入顺序获取到消息。

  对于一个有N个节点的主题,可以支持宕掉N-1个服务器而不丢失任何被提交的信息。

  更多保证信息会在文档的设计部分列出。

  待续。。。

05-11 08:48