`
m635674608
  • 浏览: 5041829 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

从Apache Kafka 重温文件高效读写

    博客分类:
  • MQ
 
阅读更多

0. Overview

卡夫卡说:不要害怕文件系统

它就那么简简单单地用顺序写的普通文件,借力于Linux内核的Page Cache,不(显式)用内存,胜用内存,完全没有别家那样要同时维护内存中数据、持久化数据的烦恼——只要内存足够,生产者与消费者的速度也没有差上太多,读写便都发生在Page Cache中,完全没有同步的磁盘访问。

整个IO过程,从上到下分成文件系统层(VFS+ ext3)、 Page Cache 层、通用数据块层、 IO调度层、块设备驱动层。 这里借着Apache Kafka的由头,将Page Cache层与IO调度层重温一遍,记一篇针对Linux kernel 2.6的科普文。

1. Page Cache

1.1 读写空中接力

Linux总会把系统中还没被应用使用的内存挪来给Page Cache,在命令行输入free,或者cat /proc/meminfo,"Cached"的部分就是Page Cache。

Page Cache中每个文件是一棵Radix树(基树),节点由4k大小的Page组成,可以通过文件的偏移量快速定位Page。

当写操作发生时,它只是将数据写入Page Cache中,并将该页置上dirty标志。

当读操作发生时,它会首先在Page Cache中查找内容,如果有就直接返回了,没有的话就会从磁盘读取文件再写回Page Cache。

可见,只要生产者与消费者的速度相差不大,消费者会直接读取之前生产者写入Page Cache的数据,大家在内存里完成接力,根本没有磁盘访问。

而比起在内存中维护一份消息数据的传统做法,这既不会重复浪费一倍的内存,Page Cache又不需要GC(可以放心使用60G内存了),而且即使Kafka重启了,Page Cache还依然在。

 

1.2 后台异步flush的策略

这是大家最需要关心的,因为不能及时flush的话,OS crash(不是应用crash) 可能引起数据丢失,Page Cache瞬间从朋友变魔鬼。

当然,Kafka不怕丢,因为它的持久性是靠replicate保证,重启后会从原来的replicate follower中拉缺失的数据。

内核线程pdflush负责将有dirty标记的页面,发送给IO调度层。内核会为每个磁盘起一条pdflush线程,每5秒(/proc/sys/vm/dirty_writeback_centisecs)唤醒一次,根据下面三个参数来决定行为:

1. 如果page dirty的时间超过了30秒(/proc/sys/vm/dirty_expire_centiseconds,单位是百分之一秒),就会被刷到磁盘,所以crash时最多丢30秒左右的数据。

2. 如果dirty page的总大小已经超过了10%(/proc/sys/vm/dirty_background_ratio)的可用内存(cat /proc/meminfo里 MemFree+ Cached - Mapped),则会在后台启动pdflush 线程写盘,但不影响当前的write(2)操作。增减这个值是最主要的flush策略里调优手段。

3. 如果wrte(2)的速度太快,比pdflush还快,dirty page 迅速涨到 20%(/proc/sys/vm/dirty_ratio)的总内存(cat /proc/meminfo里的MemTotal),则此时所有应用的写操作都会被block,各自在自己的时间片里去执行flush,因为操作系统认为现在已经来不及写盘了,如果crash会丢太多数据,要让大家都冷静点。这个代价有点大,要尽量避免。在Redis2.8以前,Rewrite AOF就经常导致这个大面积阻塞,现在已经改为Redis每32Mb先主动flush()一下了。

详细的文章可以看: The Linux Page Cache and pdflush
 

1.3 主动flush的方式

对于重要数据,应用需要自己触发flush保证写盘。

1. 系统调用fsync() 和 fdatasync()

fsync(fd)将属于该文件描述符的所有dirty page的写入请求发送给IO调度层。

fsync()总是同时flush文件内容与文件元数据, 而fdatasync()只flush文件内容与后续操作必须的文件元数据。元数据含时间戳,大小等,大小可能是后续操作必须,而时间戳就不是必须的。因为文件的元数据保存在另一个地方,所以fsync()总是触发两次IO,性能要差一点。

2. 打开文件时设置O_SYNC,O_DSYNC标志或O_DIRECT标志

O_SYNC、O_DSYNC标志表示每次write后要等到flush完成才返回,效果等同于write()后紧接一个fsync()或fdatasync(),不过按APUE里的测试,因为OS做了优化,性能会比自己调write() + fsync()好一点,但与只是write相比就慢很多了。

O_DIRECT标志表示直接IO,完全跳过Page Cache。不过这也放弃了读文件时的Cache,必须每次读取磁盘文件。而且要求所有IO请求长度,偏移都必须是底层扇区大小的整数倍。所以使用直接IO的时候一定要在应用层做好Cache。
 

1.4 Page Cache的清理策略

当内存满了,就需要清理Page Cache,或把应用占的内存swap到文件去。有一个swappiness的参数(/proc/sys/vm/swappiness)决定是swap还是清理page cache,值在0到100之间,设为0表示尽量不要用swap,这也是很多优化指南让你做的事情,因为默认值居然是60,Linux认为Page Cache更重要。

Page Cache的清理策略是LRU的升级版。如果简单用LRU,一些新读出来的但可能只用一次的数据会占满了LRU的头端。因此将原来一条LRU队列拆成了两条,一条放新的Page,一条放已经访问过好几次的Page。Page刚访问时放在新LRU队列里,访问几轮了才升级到旧LRU队列(想想JVM Heap的新生代老生代)。清理时就从新LRU队列的尾端开始清理,直到清理出足够的内存。

 

1.5 预读策略

根据清理策略,Apache Kafka里如果消费者太慢,堆积了几十G的内容,Cache还是会被清理掉的。这时消费者就需要读盘了。

内核这里又有个动态自适应的预读策略,每次读请求会尝试预读更多的内容(反正都是一次读操作)。内核如果发现一个进程一直使用预读数据,就会增加预读窗口的大小(最小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 架构设计 http://www.linuxidc.com/Linux/2013-11/92751.htm

Apache Kafka 代码实例 http://www.linuxidc.com/Linux/2013-11/92754.htm

Apache Kafka 教程笔记 http://www.linuxidc.com/Linux/2014-01/94682.htm

Apache kafka原理与特性(0.8V)  http://www.linuxidc.com/Linux/2014-09/107388.htm

Kafka部署与代码实例  http://www.linuxidc.com/Linux/2014-09/107387.htm

Kafka介绍和集群环境搭建  http://www.linuxidc.com/Linux/2014-09/107382.htm

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

本文永久更新链接地址http://www.linuxidc.com/Linux/2015-05/117022.htm

 

http://www.linuxidc.com/Linux/2015-05/117022.htm

分享到:
评论

相关推荐

    Apache Kafka实战.pdf

    《Apache Kafka实战》这本书深入浅出地介绍了...通过阅读《Apache Kafka实战》这本书,你可以深入了解Kafka的工作原理,学习如何设计、部署和维护一个高效、可靠的Kafka集群,并利用其强大的功能构建实时数据处理系统。

    Spring for Apache Kafka API(Spring for Apache Kafka 开发文档).CHM

    Spring for Apache Kafka API。 Spring for Apache Kafka 开发文档。

    Learning Apache Kafka 2nd Edition

    This book is here to help you get familiar with Apache Kafka and to solve your challenges related to the consumption of millions of messages in publisher-subscriber architectures. It is aimed at ...

    Streaming Architecture New Designs Using Apache Kafka and MapR Streams

    本文将深入探讨"Streaming Architecture New Designs Using Apache Kafka and MapR Streams"这一主题,阐述如何利用这两种强大的工具构建高效、可扩展的流处理系统。 Apache Kafka是一种分布式流处理平台,由...

    Learning Apache Kafka, 2nd Edition

    Learning Apache Kafka Second Edition provides you with step-by-step, practical examples that help you take advantage of the real power of Kafka and handle hundreds of megabytes of messages per second ...

    Building Data Streaming Applications with Apache Kafka

    Apache Kafka is a popular distributed streaming platform that acts as a messaging queue or an enterprise messaging system. It lets you publish and subscribe to a stream of records and process them in ...

    Apache Kafka Cookbook(PACKT,2015)

    《Apache Kafka Cookbook》是由PACKT在2015年出版的一本专著,专注于介绍Apache Kafka这一分布式流处理平台的实战技巧和最佳实践。Apache Kafka是一个高性能、可扩展且容错性强的消息中间件,它被广泛应用于大数据...

    apache kafka pdf下载

    书籍的结构和内容涵盖了从基础设置到高级应用的各个方面,适合那些想要深入学习和使用Apache Kafka的开发者。书中不仅包括了Kafka的基本概念和操作,还可能包含了性能优化、安全性、监控等方面的内容。此外,书籍还...

    Building Data Streaming Applications with Apache Kafka azw3

    Building Data Streaming Applications with Apache Kafka 英文azw3 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    Apache Kafka.pdf

    综上所述,Apache Kafka 是一个强大而灵活的流处理平台,通过其丰富的功能和高度可定制化的配置选项,可以在多种场景下提供高效的实时数据处理能力。无论是日志聚合、消息传递还是流式处理,Kafka 都能发挥出色的...

    Apache Kafka(带书签)

    Apache Kafka提供了强大的API来帮助开发者构建高效的消息生产和消费系统。下面是一些关键步骤: 1. **创建生产者**:要向Kafka集群发送消息,首先需要创建一个Producer实例。这通常涉及配置必要的属性,如Broker...

    Apache Kafka实战epu.rar

    《Apache Kafka实战》一书是针对分布式流处理平台Apache Kafka的专业指南,旨在帮助读者深入理解和应用Kafka在实际项目中的各种场景。Kafka是一个高吞吐量、低延迟的消息发布订阅系统,最初由LinkedIn开发,后来成为...

    apache kafka

    Kafka是一个对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。 1.Kafka集群包含一个或多个服务器,这种服务器被称为broker 2.Partition是物理上的概念,每个Topic...

    Apache Kafka设计解析

    Kafka 是由 LinkedIn 开发的一个分布式的消息系统, 使用 Scala 编写, 它以可水平扩展和高吞吐率而被广泛使用。 目前越来越多的开源分布式处理系统如Cloudera、 Apache Storm、Spark 都支持与 Kafka 集成。

    Apache Jmeter Kafka Jar包

    【Apache Jmeter Kafka Jar包】是Apache JMeter的扩展组件,专为测试和性能评估Apache Kafka消息系统设计。这个jar包允许用户在JMeter测试计划中直接发送和接收Kafka消息,从而对Kafka集群的性能进行深入分析。 ...

    《Apache Kafka源码剖析》.part5.rar

    Apache Kafka源码剖析 PDF较大,分5份上传!一起解压即可。

Global site tag (gtag.js) - Google Analytics