kafka原理&架构深入

目录

  • 1. 下载安装
  • 2. 命令行命令
  • 3. 概述
    • 3.1 定义
    • 3.2 基本架构
  • 4. 架构深入
    • 4.1 生产者
      • 4.1.1 分区
      • 4.1.2 数据可靠性保证
      • 4.1.3 Exactly Once语义
      • 4.1.4 发送消息流程
    • 4.2 broker
      • 4.2.1 日志结构
      • 4.2.2 存储策略
      • 4.2.3 Controller & ZooKeeper
      • 4.2.4 高效读写数据
    • 4.3 消费者
      • 4.3.1 消费方式
      • 4.3.2 分区分配策略
      • 4.3.3 offset的维护
      • 4.3.4 Eactly Once语义
    • 4.4 拦截器
  • 5. 面试题

1. 下载安装

https://www.cnblogs.com/zhangzhonghui/articles/12444070.html
kafka配置详解
若kafka运行在内网服务器允许外网访问,例如内网ip: 172.10.22.134,外网ip: 9.70.168.130
进行如下配置:

listeners=PLAINTEXT://:9092
advertised.listeners=PLAINTEXT://9.70.168.130:9092

外网访问时使用9.70.168.130:9092访问即可

2. 命令行命令

cd kafka安装目录

cd ~/kafka
  1. 后台启动
# zookeeper
bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
# kafka
bin/kafka-server-start.sh -daemon config/server.properties
  1. 停止
bin/kafka-server-stop.sh
  1. topic
#创建topic
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic your_topic
# 查看topic
bin/kafka-topics.sh --zookeeper localhost:2181 --list
# 查看特定topic
bin/kafka-topics.sh --zookeeper localhost:2181 --topic your_topic --describe
  1. producer
# 发送数据
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic your_topic
  1. 查看 consumer-groups
# 新版
bin/kafka-consumer-groups.sh --new-consumer --bootstrap-server localhost:9092 --list
# 旧版
bin/kafka-consumer-groups.sh --zookeeper localhost:2181 --list

# 新版特定consumer-groups
bin/kafka-consumer-groups.sh --new-consumer --bootstrap-server localhost:9292 --group YOUR_GROUP_ID --describe

# 旧版特定consumer-groups
bin/kafka-consumer-groups.sh --zookeeper localhost:2181 --group YOUR_GROUP_ID --describe

  1. 开启consumer消费某个topic(从头消费)
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic TOPIC --from-beginning

3. 概述

3.1 定义

Kafka是一个分布式的基于发布/订阅模式的消息队列,主要应用于大数据实时处理领域。Kafka对消息保存时根据Topic进行归类,发送消息者称为Producer,消息接受者称为Consumer,此外kafka集群有多个kafka实例组成,每个实例(server)成为broker。

3.2 基本架构

kafka原理&架构深入_第1张图片
kafka原理&架构深入_第2张图片
1)Producer :消息生产者,就是向kafka broker发消息的客户端。
2)Consumer :消息消费者,向kafka broker取消息的客户端
3)Topic :可以理解为一个队列。
4) Consumer Group (CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
5)Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。
6)Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序。
7)Replica:副本,为保证集群中的某个节点发生故障时,该节点上的partition数据不丢失,且kafka仍然能够继续工作,kafka提供了副本机制,一个topic的每个分区都有若干个副本,一个leader和若干个follower。
8)leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader。
9)follower:每个分区多个副本中的“从”,实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个follower会成为新的follower。
10)Offset:kafka的存储文件都是按照offset.kafka来命名,用offset做名字的好处是方便查找。例如你想找位于2049的位置,只要找到2048.kafka的文件即可。当然the first offset就是00000000000.kafka

4. 架构深入

4.1 生产者

4.1.1 分区

1)分区的原因

  1. 方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
  2. 可以提高并发,因为可以以Partition为单位读写了。

2)分区的原则
我们需要将producer发送的数据封装成一个ProducerRecord对象。
在这里插入图片描述

  1. 指明 partition 的情况下,直接将指明的值直接作为 partiton 值;
  2. 没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值;
  3. 既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到 partition 值,也就是常说的 round-robin 算法。

4.1.2 数据可靠性保证

为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。
kafka原理&架构深入_第3张图片
1)副本数据同步策略

方案 优点 缺点
半数以上完成同步,就发送ack 延迟低 选举新的leader时,为了容忍n台节点的故障,需要2n+1个副本
全部完成同步,才发送ack 选举新的leader时,容忍n台节点的故障,只需要n+1个副本 延迟高

Kafka选择了第二种方案,原因如下:

  1. 同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。
  2. 虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小。

2)ISR

采用第二种方案之后,设想以下情景:leader收到数据,所有follower都开始同步数据,但有一个follower,因为某种故障,迟迟不能与leader进行同步,那leader就要一直等下去,直到它完成同步,才能发送ack。这个问题怎么解决呢?

Leader维护了一个动态的in-sync replica set (ISR),即leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给follower发送ack。如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。Leader发生故障之后,就会从ISR中选举新的leader。之前旧版本还有保留 replica.lag.max.messages,但后续被删除了, 因为假如某个时刻数据量很大,follower还没反应过来就被踢了,但follower本身是健康的,这显然是不合理的。

3)ack应答机制

对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功。所以Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的配置。
acks:

  • 0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据

  • 1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据
    kafka原理&架构深入_第4张图片

  • -1(all):producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复
    kafka原理&架构深入_第5张图片
    4)故障处理细节
    kafka原理&架构深入_第6张图片
    (1)follower故障
    follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步。等该follower的LEO大于等于该Partition的HW,即follower追上leader之后,就可以重新加入ISR了。
    (2)leader故障
    leader发生故障之后,会从ISR中选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。

注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。数据的不丢失或不重复由ack来决定

4.1.3 Exactly Once语义

对于某些比较重要的消息,我们需要保证exactly once语义,即保证每条消息被发送且仅被发送一次。
在0.11版本之后,Kafka引入了幂等性机制(idempotent),配合acks = -1时的at least once语义,实现了producer到broker的exactly once语义(消费者的exactly once后续再说)。

使用时,只需将enable.idempotence属性设置为true,kafka自动将acks属性设为-1

在Kafka中幂等性指相同的多条数据只会保存一条,那如何确认是相同的数据?kafka中对于每条数据都有个id,id由producerId+SequenceNumber组成,当数据到达kafka后,id将会被暂时缓存起来,若此时producer没有收到ack会重发数据,发现数据跟缓存中的数据id是一致的则不持久化
kafka原理&架构深入_第7张图片

Properties props = new Properties();
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
props.put("acks", "all"); // 当 enable.idempotence 为 true,这里默认为 all
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
KafkaProducer producer = new KafkaProducer(props);
producer.send(new ProducerRecord(topic, "test");

4.1.4 发送消息流程

Kafka的Producer发送消息采用的是异步发送的方式。在消息发送的过程中,涉及到了两个线程——main线程和Sender线程,以及一个线程共享变量——RecordAccumulator。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker。
kafka原理&架构深入_第8张图片
相关参数:

  • batch.size:只有数据积累到batch.size之后,sender才会发送数据。
  • linger.ms:如果数据迟迟未达到batch.size,sender等待linger.time之后就会发送数据。
  • buffer.memory:RecordAccumulator缓冲区大小
package com.atguigu.kafka;

import org.apache.kafka.clients.producer.*;

import java.util.Properties;
import java.util.concurrent.ExecutionException;

public class CustomProducer {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Properties props = new Properties();
        props.put("bootstrap.servers", "hadoop102:9092");//kafka集群,broker-list
        props.put("acks", "all");
        props.put("retries", 1);//重试次数
        props.put("batch.size", 16384);//批次大小
        props.put("linger.ms", 1);//等待时间
        props.put("buffer.memory", 33554432);//RecordAccumulator缓冲区大小
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        Producer<String, String> producer = new KafkaProducer<>(props);
        for (int i = 0; i < 100; i++) {
        	// 同步方式 -- get()
        	// producer.send(new ProducerRecord("first", Integer.toString(i), Integer.toString(i))).get();
        	// 异步:不带回调函数
            // producer.send(new ProducerRecord("first", Integer.toString(i), Integer.toString(i)));
            // 异步:带回调函数
            producer.send(new ProducerRecord<String, String>("first", Integer.toString(i), Integer.toString(i)), new Callback() {

                //回调函数,该方法会在Producer收到ack时调用,为异步调用
                @Override
                public void onCompletion(RecordMetadata metadata, Exception exception) {
                    if (exception == null) {
                        System.out.println("success->" + metadata.offset());
                    } else {
                        exception.printStackTrace();
                    }
                }
            });
        }
        producer.close();
    }
}

4.2 broker

4.2.1 日志结构

Kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的。
topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据。Producer生产的数据会被不断追加到该log文件末端,且每条数据都有自己的offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个offset,以便出错恢复时,从上次的位置继续消费。

kafka原理&架构深入_第9张图片

由于生产者生产的消息会不断追加到log文件末尾,为防止log文件过大导致数据定位效率低下,Kafka采取了分片和索引机制,将每个partition分为多个segment。每个segment对应两个文件——“.index”文件和“.log”文件。这些文件位于一个文件夹下,该文件夹的命名规则为:topic名称+分区序号。例如,first这个topic有三个分区,则其对应的文件夹为first-0,first-1,first-2,每个文件夹下有如下文件:

00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log

“.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元数据指向对应数据文件中message的物理偏移地址,index和log文件以当前segment的第一条消息的offset命名
kafka原理&架构深入_第10张图片

4.2.2 存储策略

无论消息是否被消费,kafka都会保留所有消息,当然可对消息进行压缩或者删除。
有两种策略可以删除旧数据:
1)基于时间:log.retention.hours=168
2)基于大小:log.retention.bytes=1073741824
需要注意的是,因为Kafka读取特定消息的时间复杂度为O(1),即与文件大小无关,所以这里删除过期文件与提高 Kafka 性能无关。

4.2.3 Controller & ZooKeeper

Kafka集群中有一个broker会被选举为Controller(先到先得),负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作,Controller的管理工作都是依赖于Zookeeper的。
以下为partition的leader选举过程:
kafka原理&架构深入_第11张图片
(1) 到zookeeper中的brokers/ids/注册节点信息 [0,1,2]
(2) 从ISR中获取选取leader 0,到/brokers/topics/first/partitions/0/state更新 topic的partition信息
(3) leader 0发生故障,通知 /brokers/ids/节点,更新为 [1,2]
(4) Controller监听到节点发生变化,则重新获取ISD,选举新leader,再更新leader及ISR

4.2.4 高效读写数据

1)顺序写磁盘
Kafka的producer生产数据,要写入到log文件中,写的过程是一直追加到文件末端,为顺序写。官网有数据表明,同样的磁盘,顺序写能到到600M/s,而随机写只有100k/s。这与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间。

2) Page Cache
为了优化读写性能,Kafka 利用了操作系统本身的 Page Cache。数据通过mmap内存映射的方式直接写入page cache,定时刷新脏页到磁盘。消费者拉取消息时,如果数据在page cache中,甚至能不需要去读磁盘io。读操作可直接在 Page Cache 内进行。如果消费和生产速度相当,甚至不需要通过物理磁盘(直接通过 Page Cache)交换数据。

3)零拷贝技术
kafka原理&架构深入_第12张图片
传统路径:File -> Page Cache -> Application Cache -> Socket Cache -> NIC
Kafka零拷贝过程:File -> Page Cache -> NIC
为啥可以进行零拷贝?因为kafka写进去.log文件的数据就是经过序列化的,读取出来的数据就不要经过用户空间的处理了,减少了不必要的拷贝次数和用户态和内核态的切换,大大减少读取的时延

参考:kafka的零拷贝

4) 分区分段+稀疏索引
Kafka 的 message 是按 topic分 类存储的,topic 中的数据又是按照一个一个的 partition 即分区存储到不同 broker 节点。每个 partition 对应了操作系统上的一个文件夹,partition 实际上又是按照segment分段存储的。通过这种分区分段的设计,Kafka 的 message 消息实际上是分布式存储在一个一个小的 segment 中的,每次文件操作也是直接操作的 segment。为了进一步的查询优化,Kafka 又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。

5) 批量读写
生产者可以借助累加器,批量发送消息,消费者也可以批量拉取消费

4.3 消费者

4.3.1 消费方式

push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而pull模式则可以根据consumer的消费能力以适当的速率消费消息。
所以consumer采用pull(拉)模式从broker中读取数据。
pull模式不足之处是,如果kafka没有数据,消费者可能会陷入循环中,一直返回空数据。针对这一点,Kafka的消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可供消费,consumer会等待一段时间之后再返回,这段时长即为timeout。

4.3.2 分区分配策略

一个consumer group中有多个consumer,一个 topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消费。
Kafka有三种消费者分区分配策略:
1.RoundRobin
2.Range
3.Sticky

kafka在0.11版本引入了Sticky分区分配策略,它的两个主要目的是:

  • 分区的分配要尽可能的均匀,分配给消费者者的主题分区数最多相差一个;
  • 分区的分配尽可能的与上次分配的保持相同。

当两者发生冲突时,第一个目标优先于第二个目标。

参考:kafka的消费者分区分配策略

4.3.3 offset的维护

由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费。
Kafka 0.9版本之前,consumer默认将offset保存在Zookeeper中,从0.9版本开始,consumer默认将offset保存在Kafka一个内置的topic中,该topic为__consumer_offsets

4.3.4 Eactly Once语义

需要保证消费数据和提交offset是原子性的

4.4 拦截器

Producer拦截器(interceptor)是在Kafka 0.10版本被引入的,主要用于实现clients端的定制化控制逻辑。
对于producer而言,interceptor使得用户在消息发送前以及producer回调逻辑前有机会对消息做一些定制化需求,比如修改消息等。同时,producer允许用户指定多个interceptor按序作用于同一条消息从而形成一个拦截链(interceptor chain)。Intercetpor的实现接口是org.apache.kafka.clients.producer.ProducerInterceptor,其定义的方法包括:

(1)configure(configs)
获取配置信息和初始化数据时调用。
(2)onSend(ProducerRecord):
该方法封装进KafkaProducer.send方法中,即它运行在用户主线程中。Producer确保在消息被序列化以及计算分区前调用该方法。用户可以在该方法中对消息做任何操作,但最好保证不要修改消息所属的topic和分区,否则会影响目标分区的计算。
(3)onAcknowledgement(RecordMetadata, Exception):
该方法会在消息从RecordAccumulator成功发送到Kafka Broker之后,或者在发送过程中失败时调用。并且通常都是在producer回调逻辑触发之前。onAcknowledgement运行在producer的IO线程中,因此不要在该方法中放入很重的逻辑,否则会拖慢producer的消息发送效率。
(4)close:
关闭interceptor,主要用于执行一些资源清理工作
如前所述,interceptor可能被运行在多个线程中,因此在具体实现时用户需要自行确保线程安全。另外倘若指定了多个interceptor,则producer将按照指定顺序调用它们,并仅仅是捕获每个interceptor可能抛出的异常记录到错误日志中而非在向上传递。这在使用过程中要特别留意。

案例:
在消息发送前将时间戳信息加到消息value的最前部

package com.atguigu.kafka.interceptor;
import java.util.Map;
import org.apache.kafka.clients.producer.ProducerInterceptor;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;

public class TimeInterceptor implements ProducerInterceptor<String, String> {

	@Override
	public void configure(Map<String, ?> configs) {

	}

	@Override
	public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
		// 创建一个新的record,把时间戳写入消息体的最前部
		return new ProducerRecord(record.topic(), record.partition(), record.timestamp(), record.key(),
				System.currentTimeMillis() + "," + record.value().toString());
	}
	@Override
	public void onAcknowledgement(RecordMetadata metadata, Exception exception) {

	}

	@Override
	public void close() {

	}
}

主程序

package com.atguigu.kafka.interceptor;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;

public class InterceptorProducer {

	public static void main(String[] args) throws Exception {
		// 1 设置配置信息
		Properties props = new Properties();
		props.put("bootstrap.servers", "hadoop102:9092");
		props.put("acks", "all");
		props.put("retries", 0);
		props.put("batch.size", 16384);
		props.put("linger.ms", 1);
		props.put("buffer.memory", 33554432);
		props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
		props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
		
		// 2 构建拦截链
		List<String> interceptors = new ArrayList<>();
		interceptors.add("com.atguigu.kafka.interceptor.TimeInterceptor");
		props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, interceptors);
		 
		String topic = "first";
		Producer<String, String> producer = new KafkaProducer<>(props);
		
		// 3 发送消息
		for (int i = 0; i < 10; i++) {
			
		    ProducerRecord<String, String> record = new ProducerRecord<>(topic, "message" + i);
		    producer.send(record);
		}
		 
		// 4 一定要关闭producer,这样才会调用interceptor的close方法
		producer.close();
	}
}

5. 面试题

  1. Kafka中的ISR、AR又代表什么?
    ISR:与leader保持同步的follower集合
    AR:分区的所有副本

  2. Kafka中的HW、LEO等分别代表什么?
    LEO:没个副本的最后条消息的offset
    HW:一个分区中所有副本最小的offset

  3. Kafka中是怎么体现消息顺序性的?
    每个分区内,每条消息都有一个offset,故只能保证分区内有序。

  4. Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?
    拦截器 -> 序列化器 -> 分区器
    但拦截器中主要有两个方法,onSend() 和 onAcknowledgement(),onSend()是在消息被序列化以及计算分区前调用该方法,onAcknowledgement()成功发送到Kafka Broker之后,或者在发送过程中失败时调用

  5. Kafka生产者客户端的整体结构是什么样子的?使用了几个线程来处理?分别是什么?
    两个线程:主线程和sender线程

  6. “消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?
    正确

  7. 消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?
    offset+1

  8. 有哪些情形会造成重复消费?
    生产者:ack=-1时,leader和follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复。
    消费者:先消费后提交offset

  9. 那些情景会造成消息漏消费?
    生产者:ack=0,broker还没完成写入 或 ack=-1,leader落盘返回ack,但follower还没完成同步leader就挂了
    消费者:先提交offset,后消费,有可能造成数据的重复

  10. 当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑?
    1)会在zookeeper中的/brokers/topics节点下创建一个新的topic节点,如:/brokers/topics/first
    2)触发Controller的监听程序
    3)kafka Controller 负责topic的创建工作,并更新metadata cache

  11. topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么?
    可以增加
    bin/kafka-topics.sh --zookeeper localhost:2181/kafka --alter --topic topic-config --partitions 3

  12. topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么?
    不可以减少,被删除的分区数据难以处理(该分区的数据该如何被其他分区消费?如何分配?从哪里开始消费?等一系列难以处理的问题,所以kafka不支持)。

  13. Kafka有内部的topic吗?如果有是什么?有什么所用?
    __consumer_offsets,保存消费者offset

  14. Kafka分区分配的概念?
    一个topic多个分区,一个消费者组多个消费者,故需要将分区分配个消费者(roundrobin、range、Sticky)

  15. 简述Kafka的日志目录结构?
    每个分区对应一个文件夹,文件夹的命名为topic-0,topic-1,内部为.log和.index文件

  16. 聊一聊Kafka Controller的作用?
    负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作。

  17. Kafka中有那些地方需要选举?这些地方的选举策略又有哪些?
    partition leader(ISR),controller(先到先得)

  18. 失效副本是指什么?有那些应对措施?
    不能及时与leader同步,暂时踢出ISR,恢复后读取磁盘中持久化的HW,从HW开始消费,等其追上leader之后再重新加入

  19. Kafka的那些设计让它有如此高的性能?
    分区,顺序写磁盘,0-copy

  20. Kafka如何保证Exactly Once语义
    生产者:ack=-1并且开启幂等性,enable.idempotence属性设置为true(该选项会自动将ack设置为-1)
    消费者:保证消费和提交offset是原子性的

你可能感兴趣的:(大数据,kafka,架构,java,big,data)