目录
- 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
- 后台启动
# zookeeper
bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
# kafka
bin/kafka-server-start.sh -daemon config/server.properties
- 停止
bin/kafka-server-stop.sh
- 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
- producer
# 发送数据
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic your_topic
- 查看 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
- 开启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 基本架构
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)分区的原因
- 方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
- 可以提高并发,因为可以以Partition为单位读写了。
2)分区的原则
我们需要将producer发送的数据封装成一个ProducerRecord对象。
- 指明 partition 的情况下,直接将指明的值直接作为 partiton 值;
- 没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值;
- 既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到 partition 值,也就是常说的 round-robin 算法。
4.1.2 数据可靠性保证
为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。
1)副本数据同步策略
方案 | 优点 | 缺点 |
---|---|---|
半数以上完成同步,就发送ack | 延迟低 | 选举新的leader时,为了容忍n台节点的故障,需要2n+1个副本 |
全部完成同步,才发送ack | 选举新的leader时,容忍n台节点的故障,只需要n+1个副本 | 延迟高 |
Kafka选择了第二种方案,原因如下:
- 同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。
- 虽然第二种方案的网络延迟会比较高,但网络延迟对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故障,那么将会丢失数据
-
-1(all):producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复
4)故障处理细节
(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是一致的则不持久化
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。
相关参数:
- 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");
ProducerString, 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 ProducerRecordString, 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,以便出错恢复时,从上次的位置继续消费。
由于生产者生产的消息会不断追加到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命名
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选举过程:
(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)零拷贝技术
传统路径: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 ProducerInterceptorString, String> {
@Override
public void configure(MapString, ?> configs) {
}
@Override
public ProducerRecordString, String> onSend(ProducerRecordString, 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 构建拦截链
ListString> interceptors = new ArrayList>();
interceptors.add("com.atguigu.kafka.interceptor.TimeInterceptor");
props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, interceptors);
String topic = "first";
ProducerString, String> producer = new KafkaProducer>(props);
// 3 发送消息
for (int i = 0; i 10; i++) {
ProducerRecordString, String> record = new ProducerRecord>(topic, "message" + i);
producer.send(record);
}
// 4 一定要关闭producer,这样才会调用interceptor的close方法
producer.close();
}
}
5. 面试题
-
Kafka中的ISR、AR又代表什么?
ISR:与leader保持同步的follower集合
AR:分区的所有副本 -
Kafka中的HW、LEO等分别代表什么?
LEO:没个副本的最后条消息的offset
HW:一个分区中所有副本最小的offset -
Kafka中是怎么体现消息顺序性的?
每个分区内,每条消息都有一个offset,故只能保证分区内有序。 -
Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?
拦截器 -> 序列化器 -> 分区器
但拦截器中主要有两个方法,onSend() 和 onAcknowledgement(),onSend()是在消息被序列化以及计算分区前调用该方法,onAcknowledgement()成功发送到Kafka Broker之后,或者在发送过程中失败时调用 -
Kafka生产者客户端的整体结构是什么样子的?使用了几个线程来处理?分别是什么?
两个线程:主线程和sender线程 -
“消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?
正确 -
消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?
offset+1 -
有哪些情形会造成重复消费?
生产者:ack=-1时,leader和follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复。
消费者:先消费后提交offset -
那些情景会造成消息漏消费?
生产者:ack=0,broker还没完成写入 或 ack=-1,leader落盘返回ack,但follower还没完成同步leader就挂了
消费者:先提交offset,后消费,有可能造成数据的重复 -
当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑?
1)会在zookeeper中的/brokers/topics节点下创建一个新的topic节点,如:/brokers/topics/first
2)触发Controller的监听程序
3)kafka Controller 负责topic的创建工作,并更新metadata cache -
topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么?
可以增加
bin/kafka-topics.sh –zookeeper localhost:2181/kafka –alter –topic topic-config –partitions 3 -
topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么?
不可以减少,被删除的分区数据难以处理(该分区的数据该如何被其他分区消费?如何分配?从哪里开始消费?等一系列难以处理的问题,所以kafka不支持)。 -
Kafka有内部的topic吗?如果有是什么?有什么所用?
__consumer_offsets,保存消费者offset -
Kafka分区分配的概念?
一个topic多个分区,一个消费者组多个消费者,故需要将分区分配个消费者(roundrobin、range、Sticky) -
简述Kafka的日志目录结构?
每个分区对应一个文件夹,文件夹的命名为topic-0,topic-1,内部为.log和.index文件 -
聊一聊Kafka Controller的作用?
负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作。 -
Kafka中有那些地方需要选举?这些地方的选举策略又有哪些?
partition leader(ISR),controller(先到先得) -
失效副本是指什么?有那些应对措施?
不能及时与leader同步,暂时踢出ISR,恢复后读取磁盘中持久化的HW,从HW开始消费,等其追上leader之后再重新加入 -
Kafka的那些设计让它有如此高的性能?
分区,顺序写磁盘,0-copy -
Kafka如何保证Exactly Once语义
生产者:ack=-1并且开启幂等性,enable.idempotence属性设置为true(该选项会自动将ack设置为-1)
消费者:保证消费和提交offset是原子性的
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
rodert教你学FFmpeg实战这一篇就够了 建议收藏,以备查阅 pdf阅读版: 链接:pan.baidu.com/s/11kIaq5V6… 提取码:java [toc] 前言 todo 有人问rodert哥这篇文章干货有多干,问就是,硌牙。 ffmpeg有…