为什么这么快
上篇 文章提到了kafka的结构,其中有3点有助于提高它的吞吐量。
- partition并行处理
多个partition承载一个topic的消息存储和传输,增加partition的数量能有效增加吞吐量。 - 写消息:消息存储采用顺序写的方式
kafka消息存储在log文件中,文件采用顺序写的方式写入消息。由于磁盘结构,顺序写要比随机写快不少。
补充:
写消息还有一点优化,生产者向broker发送消息过程会先向Page Cache里写入,再异步刷盘到log文件。
为防止消息丢失,可以采用replication备份的方式。
- 读消息:文件命名和稀疏索引
两者保证了消息的快速定位,加速消息消费。
除了以上内容,还有一个重要因素:
- 零拷贝技术
broker向消费者传递数据过程,按传统的做法会经历如下步骤:
应用程序发起读数据请求,磁盘数据经read buffer进入应用层buffer;再由应用层buffer进入socket buffer,通过网卡进行网络传输。
一份数据未做任何改变的前提下,经历了数次拷贝,期间还涉及用户态和内核态间的转换,这显然是一种浪费。
kafka利用DMA技术,实现了零拷贝。
DMA可以用在显卡、声卡等很多硬件上,这里主要用到了网卡的DMA
通过操作系统层面的sendfile函数,数据将简历read buffer到网卡的映射,然后直接发送出去。(要保证数据未做任何改变)
而java的transferTo方法底层基于操作系统的sendfile实现。
升级后的方式不再需要用户态和内核态之间的切换,同时也免去了多次拷贝。
- 其它
当然,kafka支持的批量消息和消息压缩都是其快的原因。
主从同步机制
我们知道replication是partition的副本,而ISR就是master(partition所在broker)动态维护的一个集合,用来记录有效的replication副本。
先看下如下几个概念:
- AR(Assigned Repllicas)一个partition的所有副本(就是replica,不区分leader或follower)
- ISR(In-Sync Replicas)能够和 leader 保持同步的 follower + leader本身 组成的集合。
- OSR(Out-Sync Relipcas)不能和 leader 保持同步的 follower 集合
- 公式:AR = ISR + OSR
kafka会保证ISR集合中记录的副本会同步消息。
有关同步的配置如下:
# 默认10000 即 10秒
replica.lag.time.max.ms
这个配置的意思是10秒内达成完全同步的副本,会记录在ISR集合中;未完全同步则移出集合。
好,我们来看看完全同步的意思。在这之前先引出两个概念:
- LEO(last end offset)
一个partition中,最新消息的下一个offset - HW(high watermark)
partition的所有replication中同步的最小offset。
图中的例子:
假如partition有8条消息(0-7),LEO为8;
这个partition有3个replication,其中的两个partition已经将8条消息同步了;
最后一个replication只同步了5条消息(0-4),那么HW会标记为5。
此时消息0-4对外可见(consumer可以消费),5-7不可见。同时,10秒内此replication不能将5-7消息同步,它将被移出ISR
当replication将partition的LEO之前的日志全部同步时,则认为该replication已经追赶上partion,也就是完全同步。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。