1、kafka的设计
消息的生产者producer
消息的消费者consumer
kafka服务节点broker
kafka消息类型 topic
每个topic可以有多个分区 partition
每个topic的分区都有备份 replication
消费者组 consumer group
每个分区和其多个备份间 leader follower
2、ZooKeeper在Kafka中的作用
-
broker注册
/brokers/ids/[0-N]
临时节点 - 宕机自动删除 -
topic注册
/borkers/topics/[topic_key]
/brokers/topics/login_topic/3->2
标识id为3的broker为该topic总共提供了2个分区 -
生产者负载均衡
1、四层负载均衡
根据生产者的ip和端口,为其确定唯一的一个broker连接
好处:只用与一个broker建立tcp连接,减小开销
坏处:如果生产者生产能力差异很大,会导致broker的负载差异很大,负载均衡效果减弱
2、使用ZooKeeper负载均衡
生产者通过ZooKeeper获取broker的列表,并监听节点变化。进行负载均衡 -
分区与消费者的关系
consumer group 会分配唯一id,topic下的某个分区只能分配给group_id下一个consumer。(所以group下consumer不要超过分区数,会出现有的consumer无法消费到消息)
/consumers/[group_id]/owners/[topic]/[broker_id-partition_id]
[broker_id-partition_id]就是一个消息分区的标识,该节点内容就是消费者的consumer_id -
记录消费进度offset
/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]
节点内容记录的就是该分区的offset -
消费者注册
image.png
/consumers/[group_id]/ids/[consumer_id]
消费者启动后注册consumer_id,节点内容是订阅的topics
每个消费者都需要监听/consumers/[group_id]/ids
节点的子节点变化,用来触发消费者的负载均衡
3、Kafka消息如何保证消费的顺序性
- topic下只创建一个分区,同一分区内的消费是有顺序性的
- 生产者负载均衡的设计。比如如果使用对key的hash值进行负载均衡发送消息,那我们可以根据业务,需要保证顺序性的业务使用相同的key,如用户id 也可以代码指定需要发送的partition
4、如何保证消息的不丢失
生产者有个参数acks设置
0 标识只管发送,不用等待response,性能高,吞吐强
1 标识leader写入完成就返回,不需要等待ISR 吞吐量高 默认值
-1或者all 标识需要等待leader写入完成和ISR副本备份完成,才返回。 吞吐量低
消费者 设置是否自动提交
enable.auto.commit
consumer是批量拉取消息的,自动提交开启,会在拉取到消息后就立马提交offset,不管消息是否已经都消费了
关闭后,你可以在每次消费完当前消息就提交当前消息的offset,可以确保不丢失消费消息
5、Kafka如何加快消息消费速度
- 增加consumer消费者个数,存在一个问题不能超过分区数
- consumer内使用多线程消费,如拉取到一堆消息,将消息丢到线程池进行消费,消费完后提交offset。然后再拉取消息
6、Kafka如何加快生产
producer 需要设置批量发送,减少网络开销。
batch.size
消息达到多少时(字节数,不是条数),触发一次发送
linger.ms
缓存时间超过多少时,触发一次发送
如果消息设置了key,默认情况producer会根据key的hash值选取分区发送,而如果没有设置key,默认是轮训分区发送到每个分区
无key的情况下,很容易造成消息分散,batch发送无法达成。针对这个情况出现了粘性分区策略,也即某个短时间内的消息都发到一个分区上,过了这个时间段,然后换个分区。轮训的时间段版本
7、Kafka消费者语义at least once,如何处理重复消费问题
发送消息时,传入key作为唯一流水ID
消费消息时,判断是否已经已经消费过该ID消息
业务上做幂等
8、Kafka ISR机制
in sync replicate
这些机制都是针对acks=0或者1的情况
follower与leader不同步的原因:
- 1.速度跟不上 leader写入速度过快,而follower因为网络IO等问题,拉取写入速度慢与leader速度
- 2.进程卡主 follower一段时间内卡主未向leader拉取新消息FetchRequest,如太过频繁的GC等
- 3.新增备份因子 factor扩大 刚启动的follower肯定慢与leader
replica.lag.max.messages
落后消息数大余这个值时,剔除出ISR列表,适合上诉场景的1
该参数已经被删除了,原因是这个值的设置需要根据具体业务数据量进行设置,而这个设置值是全局的,针对所有topic的。如果设置值过大,相当于无效设置,如果设置值过小,会导致不断触发剔除与加入,性能降低。
replica.lag.time.max.ms
超过这个时间没向leader请求数据FetchRequest,剔除出ISR列表。适合剔除上诉场景的2,3
9、Kafka文件存储机制 吞吐量为啥大
题外:
- 磁盘随机读写慢 寻址耗时
- linux pagecache 在内存上缓存了部分磁盘上的数据,免除用户访问每次都对磁盘进行直接操作
预读
回写 - 普通IO
读取网络数据写入磁盘过程 :
DMA IO读取到内核socket缓冲区 -》 内核socket缓冲区读取到用户内存 -》用户内存写入内核磁盘缓冲区 -》 DMA内核缓冲区刷新存储到磁盘
读取磁盘数据发送网络过程 :
DMA磁盘读取到内核磁盘缓冲区 -》 内核磁盘缓冲区读取到用户内存 -》用户内存写入到内核socket缓冲区 -》DMA内核socket缓冲区写入到网络IO
Kafka文件存储
一个topic可以分多个partition存储到不同的broker,一个partition由多个segment组成,每个segment有.index和.log文件组成。segment的文件名由起始的offset定义,第一个segment文件从0开始。 .index 文件存储元数据,如(3,349)标识这个segment中的第3条消息在.log文件的物理偏移位置是349,
image.png
示例:查找offset为368776的消息
1、通过文件名列表排序后进行二分查找,定位到该消息在00000000000000368769.index|log这个segment中,
2、通过368769.index文件查找第7条元数据,定位到消息在.log中的偏移量,然后对368769.log文件进行顺序查找,找到该偏移量处的消息
.index这个文件 叫稀疏索引存储 降低索引文件存储空间占用
吞吐量高的原因:
- 顺序读写 Kafka的message信息,是不断追加到本地磁盘末尾,而不是随机写入。对应到上面即为.log文件末尾写入,引起的问题是,不允许中间删除消息或修改消息。kafka提供了基于时间和空间的自动删除策略,删除是已segment为单位的整文件删除。
- 使用PageCache 利用的是内核内存而不是jvm内存,避免了虚拟机内存开销及垃圾回收机制和构建Object的开销。服务重启PageCache也还在,缓存重建快速。
- 零拷贝机制 系统的sendfile方法,可以直接将内核缓冲区数据PageCache 发送到 内核socket缓冲区,避免了向用户内存的2次拷贝。 mmap 直接操作内核缓冲区数据。
java FileChannel 的支持
// 将当前 FileChannel 的字节传输到给定的可写 channel 中
public abstract long transferTo(long position, long count, WritableByteChannel target) throws IOException;
// 将一个可读 channel 的字节传输到当前 FileChannel中
public abstract long transferFrom(ReadableByteChannel src, long position, long count) throws IOException;
// 对 Channel 做 mmap 映射
public abstract MappedByteBuffer map(MapMode mode, long position, long size) throws IOException;
- 分partition分segment
- 批量写和批量读
10、kafka消费分区策略
- 默认 Range 每个topic都按其消费者数连续分配等量的分区数,多余的优先分配到前面的消费者
如 T1 消息有7个分区T1-0,T1-1..T1-6,T2 消息有4个分区 有3个消费者C0,C1,C1
则:
C0 :T1-0,T1-1,T1-2,T2-0,T2-1
C1: T1-3,T1-4,T2-2
C2: T1-5,T1-6,T2-3
缺陷:排号靠前的消费者,会分配到更多的分区,压力更大 - RoundRobin
1、如果组内消费者订阅的topic都相同,最终分配是均匀的
如T0,T1都有3个分区,C0,C1都订阅了T0,T1
则:
C0:T0-0,T0-2,T1-1
C1:T0-1,T1-0,T1-2
2、组内消费者订阅topic不同时
如T0,T1,T2都有3个分区, 消费者C0订阅的是主题T0,消费者C1订阅的是主题T0和T1,消费者C2订阅的是主题T0、T1和T2 会出现分配不均
C0:T0-0
C1:T1-0
C2:T1-1,T2-0,T2-1,T2-3 - StickyAssignor
11、消息队列
优点:解耦、异步、削峰
缺点:系统复杂性增加 (如一致性,重复消费,消息丢失等)、系统可用性降低
网友评论