Kafka学习笔记1——概述和名词解释

 

Kafka 设计解析(一):Kafka 背景及架构介绍》学习笔记

 

 MQ的作用:

 1.解耦:将数据生产方和数据消费方解耦。数据生产方Pruducer只需要关心数据生产;数据消费放Consumer只需要关心数据消费。而不必关心其中的传输过程,该过程交给MQ保证。

    试想,Producer生产出数据后使用Http请求将数据发送Consumer,如果发送失败,那么是生产方的责任还是消费方的责任?如果生产方保证消息发送失败的重试机制,那么相当于

    将不属于数据生产的逻辑加入了Producer。

 2.削峰:当Producer(不一定是内部系统,可能是外部系统,例如开放给外部的http接口,接口访问量暴增)生产的数据量突然暴增,Consumer的吞吐量无法满足数据量的升高。因此,

  必然会导致数据的堆积,慢慢会压垮整个系统。因此,需要引入MQ对Producer生产的数据进行排队,Consumer无法及时消费掉的数据会堆积在MQ中,而不至于直接压垮Consumer。

 3.异步:Consumer和Producer之间可能吞吐量存在不同。因此,数据的生产和消费可以不同步。引入MQ可以使得数据生产和消费的流程异步化。

 

 文章中的:

  4.可恢复性: 系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

  5.顺序性:在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka 保证一个 Partition 内的消息的有序性。

     Http请求由于网络延迟的影响,导致先发送的请求不一定先到达目标服务,更不一定先获得目标服务的响应。如果把请求生产到MQ中,则能保证请求的顺序性。

Kafka名词解释:

  1.Broker:Kafka结点

  2.Controller:在Kafka集群中会有一个或者多个broker,其中有一个broker会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态。当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。

              当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。当使用kafka-topics.sh脚本为某个topic增加分区数量时,同样还是由控制器负责分区的重新分配。
         Controller选举机制:所有Broker结点一起去ZK注册临时结点/Controller,由于只有一个Broker会注册成功,因此注册成功的这个Broker会成为Controller,其他失败的Broker会根据失败信息判断出集群中已经存在Controller。

  3. Topic:每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic,Topic中的数据不保证顺序,除非Parition为1。(物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处)

  4. Partition:一个Topic的数据物理上被划分多1个或多个Partition,分布在不同Broker上,单个Partition内部数据是顺序的。随着Partition数量的增多,Topic的吞吐量会变大。

  5.Producer:数据生产者,将生产的数据推送至Kafka集群。

  6.Consumer:数据消费者,从Kafka集群拉取数据进行消费。

  7. Consumer Group:消费组,Kafka保证在整个集群稳定运行的情况下(不发生Reblance),每个Partition中的数据只会被Consumer Group中的一个Consumer消费。可为每个 Consumer 指定 group name,若不指定 group name 则属于默认的 group。

  8. Offset:每个Consumer Group在每个Partition中都有一个Offset值,记录该CG消费到了Parititon中的哪个数据。 offset记录在一个名为 __consumer_offsets 的Topic中。

  9. Parittion Replication:由于每个Topic被划分成1个货多个Partition,因此一个Topic的数据被划分成多份分别存储在不同Kafka Broker上,如果某个Broker出现故障,会导致存储在该Broker的这部分数据丢失。

                                         因此,Kafka提出了Replication概念。每个Topic可以设置1个或多个Replication,对Partition的数据进行冗余备份。若Replication数量被设为3,则代表每个Parititon的数据在Kafka集群中

                                         存在3份;如果Replication数量被设为1,则代表每个Parititon的数据在Kafka集群中只存在一份。

  10. Partition Leader:由于Replication的存在,因此每个Partittion的数据存在于多个Broker结点。因此,需要选出Parittion Leader,Producer和Consumer对该Parititon的数据的读、写只和Paritition Leader交互,第一个收到Producer数据的Broker会成为该Partition。

                                     其他Replication的Broker只作为该Partition的Follower,Leader会向Follower不断同步数据。如果当Leader挂掉后,Controller会指定新的Partition Leader;而到Leader恢复后,会默认成为Follower。

  11. ISR:​ 分区中的所有副本统称为AR(Assigned Repllicas)。所有与leader副本保持一定程度同步的副本(包括Leader)组成ISR(In-Sync Replicas),ISR集合是AR集合中的一个子集。消息会先发送到leader副本,然后follower副本才能从leader副本中拉取消息进行     同步,同步期间内follower副本相对于leader副本而言会有一定程度的滞后。前面所说的“一定程度”是指可以忍受的滞后范围,这个范围可以通过参数进行配置。与leader副本同步滞后过多的副本(不包括leader)副本,组成OSR(Out-Sync Relipcas), 由此可       见——AR=ISR+OSR。当Follower数据同步又追上了Leader后,又会将其从OSR移入ISR。Leader 会跟踪与其保持同步的 Replica 列表,该列表称为 ISR(即 in-sync Replica)。如果一个 Follower 宕机,或者落后太多,Leader 将把它从 ISR 中移除。这里所描述的“落后太多”指 Follower 复制的消息落后于 Leader 后的条数超过预定值(该值可在 $KAFKA_HOME/config/server.properties 中通过replica.lag.max.messages配置,其默认值是 4000)或者 Follower 超过一定时间(该值可在 $KAFKA_HOME/config/server.properties 中通过replica.lag.time.max.ms来配置,其默认值是 10000)未向 Leader 发送 fetch 请求。

  12. High WaterMark(HW):小于HW值的所有消息都被认为是“已备份”的(replicated)。Consumer无法消费大于High WaterMark比较的数据。

  13. 脑裂(split-brain):Kafka集群只能存在一个Controller,当Controller DOWN机后,Kafka集群选举出了另一个Controller。这是原Controller恢复过来后,仍然以为自己的Controller,对其他Broker进行指挥。这就是脑裂现象,Kafka集群 通过类似“乐观锁”的方法

                                         处理脑裂。ZK会在/Controller_Epoch结点记录Controller的“Version”——Epoch。Controller向其他Broker发送指令时,需要携带自己的Epoch,如果Epoch小于/Controller_Epoch中记录的Epoch值,说明该Broker是过期的Controller。

  14.Coordinator:管理Consumer Group。选举策略——consumerCoordinator发送findCoordinator给任何一个broker broker接收到后计算groupID.hash % 50 ==> __consumer_offsets对应分区,此分区所在broker就是此groupID对应的groupCoordinator

Partition:

Producer 发送消息到 broker 时,会根据 Paritition 机制选择将其存储到哪一个 Partition。如果 Partition 机制设置合理,所有消息可以均匀分布到不同的 Partition 里,这样就实现了负载均衡。如果一个 Topic 对应一个文件,那这个文件所在的机器 I/O 将会成为这个 Topic 的性能瓶颈,而有了 Partition 后,不同的消息可以并行写入不同 broker 的不同 Partition 里,极大的提高了吞吐率。可以在 $KAFKA_HOME/config/server.properties 中通过配置项 num.partitions 来指定新建 Topic 的默认 Partition 数量,也可在创建 Topic 时通过参数指定,同时也可以在 Topic 创建之后通过 Kafka 提供的工具修改。

在发送一条消息时,可以指定这条消息的 key,Producer 根据这个 key 和 Partition 机制来判断应该将这条消息发送到哪个 Parition。相同key的消息会被发送到同一个Partition中,但不保证Partition只存在一个Key的数据(这一点是个人猜测)

至少一次消费、至多一次消费、仅有一次消费:

至少一次消费:1、接收数据 2、处理数据 3、提交Offset

之多一次消费:1、接收数据 2、提交Offset 3、处理数据

仅有一次消费:1、接收数据 2、处理数据但处理结果不落库 3、落库和Offset一起提交(分布式事务)

Controller选举过程:

 

Kafka中的控制器选举的工作依赖于Zookeeper,成功竞选为控制器的broker会在Zookeeper中创建/controller这个临时(EPHEMERAL)节点,此临时节点的内容参考如下:

 

{"version":1,"brokerid":0,
"timestamp":"1529210278988"}

 

其中version在目前版本中固定为1,brokerid表示称为控制器的broker的id编号,timestamp表示竞选称为控制器时的时间戳。

 

在任意时刻,集群中有且仅有一个控制器。每个broker启动的时候会去尝试去读取/controller节点的brokerid的值,如果读取到brokerid的值不为-1,则表示已经有其它broker节点成功竞选为控制器,所以当前broker就会放弃竞选;如果Zookeeper中不存在/controller这个节点,或者这个节点中的数据异常,那么就会尝试去创建/controller这个节点,当前broker去创建节点的时候,也有可能其他broker同时去尝试创建这个节点,只有创建成功的那个broker才会成为控制器,而创建失败的broker则表示竞选失败。每个broker都会在内存中保存当前控制器的brokerid值,这个值可以标识为activeControllerId。

当/controller节点的数据发生变化时,每个broker都会更新自身内存中保存的activeControllerId。如果broker在数据变更前是控制器,那么如果在数据变更后自身的brokerid值与新的activeControllerId值不一致的话,那么就需要“退位”,关闭相应的资源,比如关闭状态机、注销相应的监听器等。有可能控制器由于异常而下线,造成/controller这个临时节点会被自动删除;也有可能是其他原因将此节点删除了。

 

 

 

 

posted on 2019-11-07 21:39  ybonfire  阅读(375)  评论(0)    收藏  举报

导航