Kafka

1.Kafka基本架构

62d952b1c1684136a62c9791c791c970.png

一个topic可以有多个partition分区,并行发送和消费提高效率,每个partition可以有多个副本,提高可用性。多个消费者可以划分到一个消费者组,并行消费同个主题的消息。因此,为了不重复消费,同一消费者组的不同消费者不能消费同一主题的同一分区。

 

2.topic的分区分配策略(生产者-->Kakfa集群)

①指明partition,直接分配对应partition

②指定key,hash后取余分配

③未指定,rand-robin,随机后轮询

 

3.副本消息同步机制ISR

为了分布式环境下副本和leader的状态机保持一致,严格的做法是等所有follower同步完成后返回Ack,不过延迟高,很少使用;较为通用的方法是大多数follower同步完成后返回ack,zab和raft都是如此。

Kafka则采用了独特的ISR机制来实现:与leader通信小于10s的follower会进入ISR,默认ISR中成员全部同步完成后返回Ack。

也可以使用acks参数自定义同步策略:

①acks=0,leader收到消息后直接返回Ack,容易丢数据

②acks=1,leader落盘后不等待消息同步直接返回Ack,leader挂了丢数据

③acks=-1,ISR同步完成后返回Ack。若follower已落盘,leader挂了,生产者没收到Ack也有可能重复发送

 

4.LEO、HW和消费、存储一致性

LEO:log end offset,每个副本最大的offset

HW:high watermark,所有副本最小的LEO

为了保证消费的一致性,对consumer只有HW之前的消息可见。leader挂后,为了保证存储一致性,新leader会让其它副本截掉HW后的消息,然后将自己HW后的消息同步给其它follower。

 

5.精确一次性

配置enable.idempotence=true,此时必须acks=-1,由于acks=-1时最坏只会重复消息而不会丢失,这时会根据PID(producerID)、partition、seqNumber(每个分区的消息序号)对消息进行去重,保证精确一次。

 

6.消费者组的分区分配策略

①rand-robin,所有主题一起随机轮询,只能订阅所有主题时使用

②range,分区数对订阅该主题的消费者个数取余,前多后少,可能分配不均。

③stick,尽可能均匀分配,节点挂掉后尽量保持原分配

 

 7.消费者offset的提交

为了让kafka集群知道消费者消费到哪了,消费者挂掉重启后从哪继续发送,消费者需要告诉kafka自己的offset。通过enable.auto.commit参数开启/关闭自动提交:

①enable.auto.commit=true,自动提交,消费者挂掉时还有部分已接收消息没来得及处理,重启后会丢掉这部分数据。

②enable.auto.commit=false,在完成数据处理后手动调用commitSync和commitAsync方法同步/异步提交。处理掉一部分数据另一部分未处理时挂掉,由于没来得及提交offset,重启时已消费的部分会重复消费。

③enable.auto.commit=false,自己维护offset,与mysql事务相结合,也要维护partition挂掉后rebalance的offset,实现比较复杂。

 

8.生产者消息发送模型

9bdfe770ccbd46c59e515a6d3f15dad9.png

 

9.Kafka为什么能做到高效读写

①本身支持分布式集群,并行度高

②顺序写磁盘:磁盘的顺序读写是磁盘使用模式中最有规律的,并且操作系统也对这种模式做了大量优化,Kafka 的 message 是不断追加到本地磁盘文件末尾的,而不是随机的写入

③页缓存:不实时写入磁盘,而是通过mmap将内存数据和磁盘映射。因此最近的消息被访问时会直接访问内存,后续再flush刷写入磁盘。

④零拷贝:

(1)传统IO4次上下文切换+4次拷贝:

1.read()调用 (用户态->内核态,一次切换)

2.DMA控制器将数据读到读缓冲区 (一次拷贝)

3.CPU把数据读到应用缓冲区,read()返回(内核态->用户态,一次上下文切换+一次拷贝)

4.write()调用(用户态->内核态,一次切换)

5.CPU将应用缓冲区数据拷贝到socket缓冲区(一次拷贝)

6.DMA把数据从socket缓冲区拷贝到网卡,write()返回(内核态->用户态,一次拷贝+一次切换)

3ab9d5e60b964ca7ad905a6817b9e11f.png

 (2)mmap优化:将读缓冲和应用缓冲映射,省去③的CPU拷贝;一共3次拷贝+4次上下文切换

(3)sendfile优化:将read()和write()合并,直接由读缓冲拷贝到socket缓冲,省去两次上下文切换;一共3次拷贝+2次上下文切换

(4)sendfile+DMA scatter/gather:linux2.4后对sendfile优化,只拷贝fd和数据长度等元数据到socket缓冲,数据直接由DMA从读缓冲拷贝到网卡;一共2次拷贝+2次上下文切换,零次CPU拷贝

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值