从Apache Kafka 重温文件高效读写(2)

内核这里又有个动态自适应的预读策略,每次读请求会尝试预读更多的内容(反正都是一次读操作)。内核如果发现一个进程一直使用预读数据,就会增加预读窗口的大小(最小16K,最大128K),否则会关掉预读窗口。连续读的文件,明显适合预读。

2. IO调度层

如果所有读写请求都直接发给硬盘,对传统硬盘来说太残忍了。IO调度层主要做两个事情,合并和排序。 合并是将相同和相邻扇区(每个512字节)的操作合并成一个,比如我现在要读扇区1,2,3,那可以合并成一个读扇区1-3的操作。排序就是将所有操作按扇区方向排成一个队列,让磁盘的磁头可以按顺序移动,有效减少了机械硬盘寻址这个最慢最慢的操作。

排序看上去很美,但可能造成严重的不公平,比如某个应用在相邻扇区狂写盘,其他应用就都干等在那了,pdflush还好等等没所谓,读请求都是同步的,耗在那会很惨。

所有又有多种算法来解决这个问题,其中内核2.6的默认算法是CFQ(完全公正排队),把总的排序队列拆分成每个发起读写的进程自己有一条排序队列,然后以时间片轮转调度每个队列,轮流从每个进程的队列里拿出若干个请求来执行(默认是4)。

在Apache Kafka里,消息的读写都发生在内存中,真正写盘的就是那条pdflush内核线程,因为都是顺序写,即使一台服务器上有多个Partition文件,经过合并和排序后都能获得很好的性能,或者说,Partition文件的个数并不影响性能,不会出现文件多了变成随机读写的情况。

如果是SSD硬盘,没有寻址的花销,排序好像就没必要了,但合并的帮助依然良多,所以还有另一种只合并不排序的NOOP算法可供选择。

题外话

另外,硬盘上还有一块几十M的缓存,硬盘规格上的外部传输速率(总线到缓存)与内部传输速率(缓存到磁盘)的区别就在此......IO调度层以为已经写盘了,其实可能依然没写成,断电的话靠硬盘上的电池或大电容保命......

相关阅读

分布式发布订阅消息系统 Kafka 架构设计

Apache Kafka 代码实例

Apache Kafka 教程笔记

Apache kafka原理与特性(0.8V) 

Kafka部署与代码实例 

Kafka介绍和集群环境搭建 

Kafka 的详细介绍请点这里
Kafka 的下载地址请点这里

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/3fab09b7832b56f78d5a9b139449b3b7.html