
1/什么是kafka
kafka是一种分布式的, 高吞吐,高可用(多副本),分区,多订阅者,基于zookeeper协调的消息队列系统。
它是一种实时信息处理系统, 可以水平扩容, 在集群中多增加几台服务器, 相当于多了几个节点, 几个broker, 那么就可以容纳更多的topic和partition.
它可以处理用户在网站中的所有动作流数据(比如网页浏览,搜索,或者其他行为动作)。
上游是生产者生产的消息,存储在消息中间件中,下游拉取并处理这些数据。
2/kafka的架构
kafka的架构如下图所示,本质就是:生产
由下图可知,在kafka的架构设计里,无论是生产者,消息存储,还是消费者,都可以水平扩容,从而提高整个集群的处理能力。
另外,图中没有展示出来的kafka的另一个很重要的特性,那就是副本(有了副本,就是高可用)。
在创建topic(类似数据库中的表table)时,我们可以指定分区的数量,同时指定副本的数量。
各个副本之间只有一个leader,其他是follow,只有leader副本提供读写服务,follow副本只是冷备.
当leader副本挂掉会从follow副本中选举一个成为新的leader副本,从而达到高可用。

3/kafka消息队列系统中的几个名词介绍
producer: 生产者,即数据的发布者,该角色将消息发布到kafka的topic中的partition里.
broker: kafka集群包含一个或者多个服务器,这些服务器节点就称为broker。
topic: 每条发布到kafka集群的消息都有一个类别,这个类别就是topic(类似于mysql中的表table)
partition:topic中的数据分割为一个或者多个partition。每个topic至少有一个partion。
也就是把topic又分成一块一块的。

4/详细介绍啥是topic
从字面上理解,topic就是”话题“
下图是topic(类似于数据库中的一张表)的解剖图
一个topic可以有多个分区partition,且分区数可以动态修改,但是只允许增加不允许减少。
每个partition中的消息是有序的。
每个partiton里的新消息是生产者采用追加的方式写入的,这种顺序写入方式,使kafka的吞吐能力非常强大
一些验证表明:顺序写入磁盘的速度超过随机写入内存
例如某个用户在淘宝上买东西,订单支付成功后,发送名为TOPIC_PAYMENT_ORDER_SUCCESS的topic,积分系统可以接收这个topic,给用户送积分。会员系统可以接收这个topic,增加会员成长值,支付宝里的蚂蚁庄园还有支付成功后送饲料等。

5/详细介绍啥是consumer
生产者生产消息,就是发布消息,存在消息队列中,也就是存在kafka集群中。
生产者生产的消息,被写入到某个topic的某个分区里面,以追加的方式写入。
消费者来消费topic中某个分区示意图如下,至于消费者如何在各个topic中选择某个分区,后面的文章会提到。
由下图可知,消费者通过offset定位并读取消息,且各个消费者持有的offset是自己的消费进度。

6/consumer group
即对于都订阅了某个topic的所有consumer构成了一个消费者组consumer group,
虽然一个消费者组里可能有很多消费者,但是任意一条消息只会被其中一个consumer消费,也就是一条消息不能被消费多次,如果被消费多次,则数据就不准确了。
如果有多个消费者组,则各个消费者组之间互不干扰。
consumer group示意图如下所示:
<1>某个topic有4个分区:P0, P1, P2, P3。
<2>消费者组A中有两个消费者:C1和C2,消费者组B中有4个消费者:C3,C4,C5和C6。
<3>如果生产者发布了一条消息,那么这条消息只会被消费者组A中的C1和C2之中的一个消费者消费,
以及被消费者组B中的C3,C4,C5和C6之中的一个消费者消费。
<4>也就是说:同一个分区只能被同一个消费者组中的一个消费者消费。

消费者组,即Consumer Group,应该算是kafka比较有创意的设计了。
那么到底Consumer Group是什么呢?
用一句话概括就是:Consumer Group是kafka提供的可扩展且具有容错性的消费者机制。
既然是一个组,那么组内必然可以有多个消费者,他们共享一个公共的ID,这个ID被称为GroupID。
组内的消费者协调在一起,共同去消费订该组所订阅的topic中所有分区的消息。
当然,每个分区只能被同一个消费者组内的一个消费者消费。
Consumer Group之间批次独立,互不影响,他们能订阅相同的topic而互不干涉。
kafka仅仅使用consumer Group这一种机制,却实现了传统消息引擎系统的2大模型:
<1>如果所有实列属于同一个consumer Group,那么它实现的就是消息队列模型;
<2>如果所有实列分别属于不同的consumer Group,那么他实现的就是发布/订阅模型。
理想情况下:
<1>消费者组中的消费者实列的数量应该等于该组所有订阅主题的总分区数。
<2>Consumer Group的位移也是提交到Broker中的内部主题中的consumer_offsets
<3>topic中的一个分区只能被一个消费者消费,一个消费者可以消费多个分区。
有三种情况:
<1>消费者实列数小于分区总数:这种情况会下,一个消费者实列会消费多个分区
<2>消费者实列数等于分区数:一个消费者消费一个分区
<3>消费者实列数大于分区数:会有几个消费者处于空闲的状态下。
Rebalance机制
Rebalance本质上是一种协议,规定了一个ComsumerGroup下的所有Consumer如何达成一致,来分配订阅主题的分区。
比如某个消费者组中有20个消费者实列,订阅了一个具有100个分区的Topic。
正常情况下,kafka会平均为每个消费者分配5个分区。这个分配的过程就叫做Rebalance机制
那什么时候会触发Rebalance机制呢?一下三种情况下回触发:
<1>Group中消费者实列数量发生变化。比如有新的消费者加入Group,或者有消费者实列奔溃退出Group
<2>订阅的主题数发生变更,从而总分区数就会发生变化。ComsumerGroup可以使用正则表达式的方式订阅主题。
<3>订阅主题的分区数发生变更。kafka当前只允许增加分区数,不能减少分区数量。当分区数增加时,就会触发Rebalance。
6/基于kafka-zookeeper的分布式消息队列系统总体架构
Kafka架构说明
一个典型的Kafka集群包含若干Producer,若干Broker,若干Consumer,以及一个Zookeeper集群。
Kafka通过Zookeeper管理集群配置,选举Leader(副本,高可用),以及在Consumer Group发送变化时进行Rebalance(负载均衡)。
Producer 使用push(推)模式将消息发布到Broker;
Consumer 使用pull(拉)模式从Broker订阅并消费消息。

8/Kafka的核心概念

<1>Producers的概念
消息和数据生产者,向Kafka的一个topic发布消息的过程叫做producers
Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息归属于哪个分区partition
异步发送批量发送可以很有效的提高发送效率。kafka producer的异步发送模式允许进行批量发送,先将消息缓存到内存中,然后一次请求批量发送出去。
<2>Message组成
Message消息:是通信的基本单位,每个producer可以向一个topic发布消息。
Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的,每个topic又可以分成不同的分区,每个分区储存一部分
partion中的每条Message包含以下三个属性:

<3>Consumers的概念
消息和数据消费者,订阅topic并处理其发布的消息的过程叫做consumers.
在kafka中,我们可以认为一个group是一个“订阅者”,一个topic中的每个partions只会被一个“订阅者”中的一个consumer消费,不过一个consumer可以消费多个partitions中的消息
<4>注:Kafka的设计原理决定,对于一个topic,同一个group不能多于分区个数的消费者实例同时消费,否则将意味着某些consumer无法得到消息
9/kafka的主要2大应用场景
<1>消息队列:简历实时流数据管道
<2>数据处理:构建实时的流数据处理程序来处理数据流
10/kafka消息模型

使用队列作为消息的载体,满足生产者和消费者模式,一条消息只能被一个消费者消费,
未被消费的消息在队列中保留直到被消费或者超时。
比如生产者发送100条消息,2个消费者来消费,一般情况下2个消费者会按照发送的顺序各自消费一半(也就是你一个,我一个)

发布订阅模型使用主题topic作为信息的载体,类似与广播模式:发布者发布一条消息,该消息通过主题传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该消息的。
11/kafka重要概念解读
Kafka将生产者发布的消息发送到 Topic(主题) 中,需要这些消息的消费者可以订阅这些 Topic(主题),如下图所示:

上面这张图也为我们引出了Kafka的比较重要的几个概念:
Producer: 产生消息的一方。
Consumer:消费消息的一方。
Broker:kafka集群中的一台服务器,成为broker
同时,你一定也注意到每个 Broker 中又包含了 Topic 以及 Partition 这两个重要的概念:
Topic: Producer 将消息发送到特定的主题,消费者通过订阅特定的Topic来消费消息。
Partition:Partition 属于 Topic 的一部分。一个Topic可以有多个 Partition,并且同一Topic下的Partition可以分布在不同的Broker上,这也就表明一个Topic可以横跨多个 Broker。这正如我上面所画的图一样。
这就好比,每台服务器中都有mysql,不同服务器的mysql的表名可以是相同的。可以把数据存储在不同的服务器上,这就是跨broker
12/Kafka如何保证消息的消费顺序?
我们在使用消息队列的时候,经常有业务场景需要严格保证消息的消费顺序,比如我们同时发了 2 个消息,这 2 个消息对应的操作分别是:更改用户会员等级,然后根据会员等级计算订单价格。假如这两条消息的消费顺序不一样造成的最终结果就会截然不同。
我们知道 Kafka中Partition是真正保存消息的地方,我们发送的消息都被放在了这里。而我们的 Partition又存在于 Topic中这个概念中,并且我们可以给特定Topic指定多个Partition。

每次添加消息到Partition的时候都会采用尾加法,如上图所示。Kafka只能为我们保证Partition(分区) 中的消息有序,而不能保证Topic中的Partition的有序。
所以,我们就有一种很简单的保证消息消费顺序的方法:1个Topic只对应一个Partition这样当然可以解决问题,但破坏了Kafka的设计初衷。
总结一下,对于如何保证 Kafka 中消息消费的顺序,有了下面两种方法:
1 个 Topic 只对应一个Partition。
(推荐)发送消息的时候指定 key/Partition。
13/consumer个数与分区数有什么关系?
<1>topic下的一个分区只能被同一个consumer group中的一个consumer来消费,但反之并不成立,
<2>即一个consumer可以消费多个分区的数据,比如Kafka提供的ConsoleConsumer,默认就只是一个线程来消费所有分区的数据。
14/一般消息队列分为2种模式
<1>点对点模式
生产者发送消息到队列中,将有一个或者多个消费者来消费队列中的消息,但是一条消息只能被一个消费者消费。当一个消费者消费了队列中的某条消息之后,该条数据则从队列中删除,即使有多个消费者同时消费数据,也能保证顺序。

<2>发布-订阅模式
生产者发布消息到一个topic中,于点对点模式不同的是,消费者可以订阅一个或者多个topic,消费者可以消费该topic中的所有数据,同一条消息可以被多个消费者消费,消息被消费后不会立马被删除。
发布者发布到topic的消息,只有订阅了该topic的订阅者才能收到消息。
