2019独角兽企业重金招聘Python工程师标准>>>

从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

转载于:https://my.oschina.net/xiaominmin/blog/1599057

从Apache Kafka 重温文件高效读写相关推荐

  1. 大数据技术之kafka (第 3 章 Kafka 架构深入 ) 高效读写数据

    1)顺序写磁盘 Kafka 的 producer 生产数据,要写入到 log 文件中,写的过程是一直追加到文件末端, 为顺序写.官网有数据表明,同样的磁盘,顺序写能到 600M/s,而随机写只有 10 ...

  2. 解开Kafka神秘的面纱(二):Kafka的高效读写与消息安全

    文章目录 一.前言 二.Kafka消息队列 2.1 生产者生产kafka中的消息数据 2.1.1 生产者生产kafka中的消息数据 2.1.2 kafka生产者高效写盘 2.2 消费者消费kafka中 ...

  3. 分布式发布订阅消息系统—Apache Kafka

    1.什么是Kafka Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据. 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键 ...

  4. Apache Kafka: 优化部署的10个最佳实践

    原文作者:Ben Bromhead      译者:江玮 原文地址:https://www.infoq.com/articles/apache-kafka-best-practices-to-opti ...

  5. Apache Kafka:下一代分布式消息系统

    简介 Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和可复制的提交 ...

  6. 大数据开发hadoop核心的分布式消息系统:Apache Kafka 你知道吗

    简介 Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和可复制的提交 ...

  7. 《Apache Kafka实战》读书笔记-调优Kafka集群

    <Apache Kafka实战>读书笔记-调优Kafka集群 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.确定调优目标 1>.常见的非功能性要求 一.性能( ...

  8. Windows OS上安装运行Apache Kafka教程

    Windows OS上安装运行Apache Kafka教程 下面是分步指南,教你如何在Windows OS上安装运行Apache Zookeeper和Apache Kafka. 简介 本文讲述了如何在 ...

  9. Apache Kafka

    2019独角兽企业重金招聘Python工程师标准>>> 简介 Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分. ...

最新文章

  1. R语言将多个dataframe数据添加在列表(list)结构中并进行列表dataframe的索引:包含dataframe的列表、包含dataframe的列表的索引
  2. 查看Oracle数据库SQL执行历史
  3. Android开发之CoordinatorLayout使用详解一
  4. 又是Dropout两次!这次它做到了有监督任务的SOTA
  5. 最少预算覆盖最多应用,高性价比小企业服务器服务器榜单
  6. 通过JAVA对HDFS进行操作管理插件
  7. Linux文件与目录管理常用命令
  8. JBPM4.4整合SSH2项目
  9. Git 的origin和master解析
  10. 【学习笔记】网络层——IPv6:地址表示、IPv4的对比、IPv4过渡到IPv6、基本地址类型等
  11. oracle设为归档模式,设置oracle归档模式
  12. 不是我的错,也不是Atlas的!
  13. LVS的VS/NAT及VS/DR类型实现
  14. java方法不写访问权限_【JAVA小白】 问关于访问权限的问题,写接口遇到错误
  15. python 做网站用服务器_Python实现简单的Web服务器 Part2—支持动态网站
  16. codewars028: Persistent Bugger
  17. PRML读书笔记 第十一章 采样方法(1)
  18. 自考专科历练计算机实践考试,毕业感言:考过自考才晓得坚持历练和毅力
  19. bindingx 表达式动画
  20. 技术文摘9 刘 樱桃

热门文章

  1. asp.net 检测是否关注公众号_实木板材开裂和变形是什么情况,出现后该怎么检测?...
  2. 解决 org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does no
  3. 数据库服务器文件路径,如何在服务器中找到数据库文件路径
  4. 图片转svg标注_两个免费网站轻松搞定图片文件压缩转化!
  5. 数据结构实验之图论九:最小生成树(Prim/Kruskal)
  6. mfc中加logo以及背景图
  7. 【自动驾驶】23.相机成像究竟是成在像平面还是成在焦平面
  8. 【自动驾驶】7. MDC常用术语、DDS、SOME/IP
  9. 常用Apache Commons工具类备忘
  10. Java设计模式之代理模式(Proxy)