1 顺序写

顺序读写,磁盘会预读,预读即在读取的起始地址连续读取多个页面,主要时间花费在了传输时间。

2 内存映射、零拷贝

2.1 写加速

内存映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。通过 mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),也不必关心内存的大。省去了用户空间到内核空间复制的开销。

但也有一个很明显的缺陷——不可靠,写到 mmap 中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用 Flush 的时候才把数据真正的写到硬盘。

Kafka 提供了一个参数 producer.type 来控制是不是主动 Flush:

如果 Kafka 写入到 mmap 之后就立即 Flush,然后再返回 Producer 叫同步 (Sync)。

如果 Kafka 写入 mmap 之后立即返回 Producer 不调用 Flush 叫异步 (Async)。

2.2 读加速

零拷贝。传统 Read/Write 方式进行网络文件传输的方式,我们可以看到,在这个过程当中,文件数据实际上是经过了四次 Copy 操作:
硬盘—>内核 buf—>用户 buf—>Socket 相关缓冲区—>协议引擎。

sendfile系统调用则提供了一种减少以上多次copy,提升文件传输性能的方法, Sendfile的引入不仅减少了数据复制,还减少了上下文切换。

相较传统 Read/Write 方式,2.1 版本内核引进的 Sendfile 已经减少了内核缓冲区到 User 缓冲区,再由 User 缓冲区到 Socket 相关缓冲区的文件 Copy。

而在内核版本 2.4 之后,文件描述符结果被改变,Sendfile 实现了更简单的方式,再次减少了一次 Copy 操作。
在 Apache、Nginx、Lighttpd 等 Web 服务器当中,都有一项 Sendfile 相关的配置,使用 Sendfile 可以大幅提升文件传输性能。

Kafka 把所有的消息都存放在一个一个的文件中,当消费者需要数据的时候 Kafka 直接把文件发送给消费者,配合 mmap 作为文件读写方式,直接把它传给 Sendfile

3 批量压缩

每个消息都压缩,但是压缩率相对很低。KAFKA使用了批量压缩,多个消息一起压缩。 降低网络带宽。
KAFKA允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压缩。KAFKA支持Gzip和Snappy压缩协议。

4 数据以分区形式存放,多分区读写

并发读写,加快读写速度;多分区的存储,利于数据的均衡;

在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,partiton序号从0开始,序号最大值为partitions数量减1。

broker–>topic–>partition–>segment file

segment file:分为index索引文件和log数据文件,分别以后缀".index"和“.log”结尾。

文件中存放的是二进制流信息。

根据Offset如何快速定位到读取的信息:

索引文件和数据文件的文件名:00000000…9999.index 存放,可通过二分法查找到文件