上一篇Kakfa学习笔记(三)——Java API发送消费消息
这篇打算简单说一下Kafka的工作流程,加深对Kafka的理解
分区和副本
之前说过,一个topic有多个partition,实际上消息划分的最小单位是partition,每个partition都有多个replicate(副本,一般说副本也包含主副本)。一条消息从producer发出,落到一个broker上的partition,最后consumer拉取消息
每个partition都有一个leader(主副本),零个或多个follower(从副本)。每个leader和follower都是一个broker。Kafka会把所有partition的leader平均分配到broker上,所有的读写都只由leader来完成,follower只从leader同步消息,并不对外服务。
看一下这个图增强理解
producer怎么知道某个partition的leader是谁呢?我们在配置producer的时候是需要配置一个broker列表的——参数bootstrap.servers
。我们会告诉producer几个broker,producer会向其中一个broker拉取所有partition的leader列表,然后缓存起来,这样broker就可以直接向leader发送消息
之前我们说过,一个partition内的消息是有序的。这是因为producer通过自己的partition算法算出一条消息应该落到哪个partition,然后找出这个partition的leader(broker),直接把消息发给这个broker,而订阅这个partition的consumer只有一个,所以就保证了partition内的消息有序。
消息持久化
之前在概述说过,Kafka本身也是一个存储系统,broker收到消息是会持久化到磁盘的,这里就结合分区来了解一下Kafka的持久化
首先我们还是起3个broker,然后创建一个分区数3,副本数3的topic
> bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 3 --partitions 3 --topic test
复制代码
来看一下这个topic的情况
> bin/kafka-topics.sh --describe --bootstrap-server localhost:9092 --topic test
Topic:test PartitionCount:3 ReplicationFactor:3 Configs:segment.bytes=1073741824
Topic: test Partition: 0 Leader: 0 Replicas: 0,2,1 Isr: 0,2,1
Topic: test Partition: 1 Leader: 2 Replicas: 2,1,0 Isr: 2,1,0
Topic: test Partition: 2 Leader: 1 Replicas: 1,0,2 Isr: 1,0,2
复制代码
如我们预期一样,三个分区,三个leader,均摊到三个broker上,并且副本也是3个
我们在配置文件里设置了log.dirs
,这个参数指定了Kafka日志(Kafka消息数据是以日志形式落盘)存放位置。按照topic-partition
的格式,把数据放到不同的文件夹里面,例如我们上面test主题,三个分区,在log.dirs
里可以看到
> ls
test-0
test-1
test-2
复制代码
这些日志文件就是消息持久化到磁盘的载体,可能有人会问,持久化到磁盘不是比内存慢很多吗?然而,Kafka很大程度上是依赖了磁盘这一设定来达到大吞吐量的目的。现代的磁盘优化已经非常好,另外磁盘的顺序写入在某些情况下确实比内存的随机读取要快。一个比较典型的例子就是操作系统很喜欢利用磁盘作虚拟内存。另外无需在内存里维护大量的数据,Kafka不需要担心GC的问题(scala也是运行在JVM上)。另外Kafka直接通过sendfile系统调用避免了内核态和用户态之间切换以及不必要的数据复制。此外,消息系统的另一个消耗就是带宽,Kafka有压缩消息的功能,压缩算法可以进行指定。
上面的内容我都是摘自官网文档