高可靠
生产者
1:分区的多副本机制,容灾;
2:ack机制,生产者的消息,成功的判断条件需要ack确认;
ack:0,代表生产者只管发送,性能高,可靠性差;
ack:1,代表消息只要到leader分区副本,就算成功,有安全风险,有消息丢失的可能;
ack:-1 或者all,再配上mini.synchronize.re,参数,代表ISR 至少这个这么多分区副本 同步这条消息,才算成功;安全性高,可靠性强;(还需要关掉一个参数)
消费者
1:关掉自动提交偏移量按钮,参数控制;
poll拉到消息后,先处理业务逻辑,完成后,在手动提交偏移量;防止消息丢失;
2:leader分区副本的hw,是从ISR中的follower副本最小的leo 设置成分区的hw,保证了消息的可靠性;
其他:
1:直接基于硬盘的中间件,相比其他的,基于内存的,更加安全;kafka先写到pagecache,在刷到磁盘;:
2:leader副本所在的broker 宕机后,改分区暂停读写,会从ISR中重新选出新的leader副本,就是rebalance机制;
高性能
生产者
1:容量大,相比其他基于内存的中间件,如redis,先写到内存,然后在持久化到磁盘,kafka直接写到磁盘(中间也有写到页缓存的步骤),服务器的磁盘容量比内存大的多;
2:顺序读写,kafka虽然基于磁盘读写,读写性能也不差,常说的磁盘读写是随机读写,每次都需要磁头,先找到磁道,然后在磁道上找到对应的扇区,才能找到数据,随机读写,每次都要重复这个操作 ,时间很长;顺序读写,则是找到一次后,就一直在那个磁道上操作,直到满了,换一个磁道;这样效率就高了;
3:0拷贝,操作系统中有用户态和内核态 两种状态,os 只允许内核态线程去操作硬盘io,网卡,来保证安全;用户态如果需要io,都要切换到内核态上,先将数据存到内核态的数据缓冲区,再切换到用户态,将数据从内核态的缓冲区,copy到用户态的数据缓冲区,如果数据要发送,需要在切换到 内核态,将数据从用户态的数据缓冲区,拷贝到 socket的发送缓冲区,最后丢到网卡,很麻烦;
0拷贝,基于os支持实现,能直接将磁盘的数据发送到网卡,不需要 用户态和内核态的频繁 切换,例子:消费者消费消息,broker就能直接将leader分区上的消息直接丢到网卡,返回给消费者,速度很快;
4:页缓存,生成者写数据,先写到pagecache中,速度更快,也存在安全风险,机器掉电;
5:消息生成后,会先到消息累加器中,以key为分区,value为queue<ProduceBath>形式存储,ProduceBath就是多个ProduceRecord;
消费者
1:由于kafka架构层面,消息 基于逻辑概念的 主题和分区,物理上消息过来 分区对应的就是 一个文件夹,文件夹中就是该分区的日志消息,消息由segment 组成,每个segment 由多个文件构成,命名有偏移量开始,.log文件,偏移量索引文件,时间索引文件;
消息存储到 不同的分区,分区中又有 不同segment ,消费性能也高