天天看点

使用说明-Kafka

  • Kafka名词解释
  1. Broker:Kafka节点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群。
  2. Topic:一类消息,消息存放的目录即主题,例如page view日志、click日志等都可以以topic的形式存在,Kafka集群能够同时负责多个topic的分发。
  3. Partition:topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列
  4. Producer : 生产message发送到topic
  5. Consumer : 订阅topic消费message, consumer作为一个线程来消费
  6. Consumer Group:一个Consumer Group包含多个consumer, 这个是预先在配置文件中配置好的。各个consumer(consumer 线程)可以组成一个组(Consumer group ),partition中的每个message只能被组(Consumer group ) 中的一个consumer(consumer 线程 )消费,如果一个message可以被多个consumer(consumer 线程 ) 消费的话,那么这些consumer必须在不同的组。
  • Kafka集群概览
使用说明-Kafka
  • 剖析一个Topic的生产与消费
使用说明-Kafka
  1. 生产者

集群模式下,ProducerA和ProducerB都是“my topic”的生产者,即2个实例

  1. 消费者

在集群模式下,ConsumerA、ConsumerB和ConsumerC都是“my topic”的消费者,即3个实例,它们都在一个ConsumerGroup中

  1. My Topic

一个主题,如:用户点击事件

Partition1、Partition2、Partition3是对My Topic按照特定规则的分解,例如

P1存放: key mod 3 = 0

P2存放: key mod 3 = 1

P3存放: key mod 3 = 2

一个topic,在kafka集群里的物理存储怎样?-----Partition & Replication

  1. Partition在broker中的分布

举例:在一个含有4个broker节点的集群中,每个主题3个分区,每个分区3个备份

bin/kafka-topics.sh --create --zookeeper 192.168.102.197:2181 --replication-factor 3 --partitions 3 --topic topic1

使用说明-Kafka
  1. 创建过程

Step1:创建一个topic

Step2:将这个topic逻辑分3个区

Step3:将这3个区,分到每个broker上(分区数量可以大于broker数量吗?)

Step4:为每个分区,创建对应数量的副本(副本数量可以大于broker数量吗?)

  1. 消息分配规则:

P0存放: key mod 3 = 0(只有3个分区,每个消息必须落在其中一个分区)

P1存放: key mod 3 = 1

P2存放: key mod 3 = 2

主题名称 Key Payload负载 所在分区 目标Broker
MyTopic 1 Data1 Part1 Broker2
MyTopic 2 Data2 Part2 Broker4
MyTopic 3 Data3 Part0 Broker1
MyTopic 4 Data4 Part1 Broker2
MyTopic 5 Data5 Part2 Broker4
MyTopic 6 Data6 Part0 Broker1
MyTopic 7 Data7 Part1 Broker2
MyTopic 8 Data8 Part2 Broker4
  1. 结论:

同一个Partition可能会有多个Replica,需要保证同一个Partition的多个Replica之间的数据一致性。而这时需要在这些Replication之间选出一个Leader(红色背景),Producer和Consumer只与这个Leader交互,其它Replica作为Follower从Leader中复制数据

  1. Producer发送消息到Kafka集群的过程分析
使用说明-Kafka

选择分区

我们从创建一个ProducerRecord 对象开始, Producer Record 对象需要包含目标主题和要发送的内容。我们还可以指定键或分区。在发送ProducerRecord 对象时,生产者要先把键和值对象序列化成字节数组,这样它们才能够在网络上传输。

接下来,数据被传给分区器。如果之前在ProducerRecord 对象里指定了分区,那么分区器就不会再做任何事情,直接把指定的分区返回。如果没有指定分区,那么分区器会根据ProducerRecord 对象的键来选择一个分区。选好分区以后,生产者就知道该往哪个主题和分区发送这条记录了。紧接着,这条记录被添加到一个记录批次里,这个批次里的所有消息会被发送到相同的主题和分区上。有一个独立的线程负责把这些记录批次发送到相应的broker 上。

接收写入结果

服务器在收到这些消息时会返回一个响应。如果消息成功写入Kafka ,就返回一个RecordMetaData 对象,它包含了主题和分区信息,以及记录在分区里的偏移量。如果写入失败, 则会返回一个错误。生产者在收到错误之后会尝试重新发送消息,几次之后如果还

是失败,就返回错误信息。

同步发送消息---通过调用Future.get()方法阻塞,等待结果返回

异步发送消息---回调函数

生产者如何保证消息写入的高可用?

acks 参数指定了必须要有多少个分区副本收到消息,生产者才会认为消息写入是成功的。这个参数对消息丢失的可能性有重要影响。

如果acks=0 ,生产者在成功写入消息之前不会等待任何来自服务器的响应。

如果acks=1 ,只要集群的首领节点收到消息,生产者就会收到一个来自服务器的成功

响应。

如果acks=all ,只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自

服务器的成功响应。

  1. Consumer从Kafka集群消费消息的过程分析

主题分区和消费者群组的多种分配方式

使用说明-Kafka
使用说明-Kafka
使用说明-Kafka
使用说明-Kafka
使用说明-Kafka

消费者群组和分区再均衡

一个新的悄费者加入群组时,它读取的是原本由其他消费者读取的消息。当一个消费者被关闭或发生崩愤时,它就离开群组,原本由它读取的分区将由群组里的其他消费者来读取。在主题发生变化时, 比如管理员添加了新的分区,会发生分区重分配。当消费者要加入群组时,它会向群组协调器发送一个Join Gro up 请求。第一个加入群组的消费者将成为“群主”。群主从协调器那里获得群组的成员列表(列表中包含了所有最近发送过心跳的消费者,它们被认为是活跃的),并负责给每一个悄费者分配分区。它使用一个实现了P a 「ti.ti.onAssi. gn o 「接口的类来决定哪些分区应该被分配给哪个消费者。Kafka 内置了两种分配策略,在后面的配置参数小节我们将深入讨论。分配完毕之后,群主把分配情况列表发送给群组协调器,协调器再把这些信息发送给所有消费者。每个消费者只能看到自己的分配信息,只有群主知道群组里所有消费者的分配信息。这个过程会在每次再均衡时重复发生。

消费者读取消息

使用说明-Kafka

poll () 方能返回一个记录列表。每条记录都包含了记录所属主题的信息、记录所在分

区的信息、记录在分区里的偏移量,以及记录的键值对。我们一般会遍历这个列表,逐

条处理这些记录。

消费者指定偏移量进行消费

我们知道了如何使用poll () 方告从各个分区的最新偏移量处开始处理消息。不过,有时候我们也需要从特定的偏移量处开始读取悄息。如果你想从分区的起始位置开始读取消息,或者直接跳到分区的末尾开始读取消息, 可以使用seekToBeginning(Collection<TopicPartition> tp ) 和seekToEnd (Collection < TopicPartition >

tp ) 这两个方法。

消费者提交分区消息偏移量

消费者往一个叫作_consumer_offset 的特殊主题发送消息,消息里包含每个分区的偏移量。如果消费者一直处于运行状态,那么偏移量就没有什么用处。不过,如果悄费者发生崩愤或者有新的消费者加入群组,就会触发再均衡,完成再均衡之后,每个消费者可能分配到新的分区,而不是之前处理的那个。为了能够继续之前的工作,消费者需要读取每个分区最后一次提交的偏移量,然后从偏移量指定的地方继续处理。

提交方式:

自动提交consumerProps.put("enable.auto.commit", "true")

手动提交consumer.commitSync();或consumer.commitAsync();

提交特定的偏移量:边处理边提交

  • 安装kafka
  • Kafka常用命令

继续阅读