从Apache Kafka 重温文件高效读写
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 重温文件高效读写相关推荐
- 大数据技术之kafka (第 3 章 Kafka 架构深入 ) 高效读写数据
1)顺序写磁盘 Kafka 的 producer 生产数据,要写入到 log 文件中,写的过程是一直追加到文件末端, 为顺序写.官网有数据表明,同样的磁盘,顺序写能到 600M/s,而随机写只有 10 ...
- 解开Kafka神秘的面纱(二):Kafka的高效读写与消息安全
文章目录 一.前言 二.Kafka消息队列 2.1 生产者生产kafka中的消息数据 2.1.1 生产者生产kafka中的消息数据 2.1.2 kafka生产者高效写盘 2.2 消费者消费kafka中 ...
- 分布式发布订阅消息系统—Apache Kafka
1.什么是Kafka Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据. 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键 ...
- Apache Kafka: 优化部署的10个最佳实践
原文作者:Ben Bromhead 译者:江玮 原文地址:https://www.infoq.com/articles/apache-kafka-best-practices-to-opti ...
- Apache Kafka:下一代分布式消息系统
简介 Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和可复制的提交 ...
- 大数据开发hadoop核心的分布式消息系统:Apache Kafka 你知道吗
简介 Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和可复制的提交 ...
- 《Apache Kafka实战》读书笔记-调优Kafka集群
<Apache Kafka实战>读书笔记-调优Kafka集群 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.确定调优目标 1>.常见的非功能性要求 一.性能( ...
- Windows OS上安装运行Apache Kafka教程
Windows OS上安装运行Apache Kafka教程 下面是分步指南,教你如何在Windows OS上安装运行Apache Zookeeper和Apache Kafka. 简介 本文讲述了如何在 ...
- Apache Kafka
2019独角兽企业重金招聘Python工程师标准>>> 简介 Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分. ...
最新文章
- R语言将多个dataframe数据添加在列表(list)结构中并进行列表dataframe的索引:包含dataframe的列表、包含dataframe的列表的索引
- 查看Oracle数据库SQL执行历史
- Android开发之CoordinatorLayout使用详解一
- 又是Dropout两次!这次它做到了有监督任务的SOTA
- 最少预算覆盖最多应用,高性价比小企业服务器服务器榜单
- 通过JAVA对HDFS进行操作管理插件
- Linux文件与目录管理常用命令
- JBPM4.4整合SSH2项目
- Git 的origin和master解析
- 【学习笔记】网络层——IPv6:地址表示、IPv4的对比、IPv4过渡到IPv6、基本地址类型等
- oracle设为归档模式,设置oracle归档模式
- 不是我的错,也不是Atlas的!
- LVS的VS/NAT及VS/DR类型实现
- java方法不写访问权限_【JAVA小白】 问关于访问权限的问题,写接口遇到错误
- python 做网站用服务器_Python实现简单的Web服务器 Part2—支持动态网站
- codewars028: Persistent Bugger
- PRML读书笔记 第十一章 采样方法(1)
- 自考专科历练计算机实践考试,毕业感言:考过自考才晓得坚持历练和毅力
- bindingx 表达式动画
- 技术文摘9 刘 樱桃
热门文章
- asp.net 检测是否关注公众号_实木板材开裂和变形是什么情况,出现后该怎么检测?...
- 解决 org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does no
- 数据库服务器文件路径,如何在服务器中找到数据库文件路径
- 图片转svg标注_两个免费网站轻松搞定图片文件压缩转化!
- 数据结构实验之图论九:最小生成树(Prim/Kruskal)
- mfc中加logo以及背景图
- 【自动驾驶】23.相机成像究竟是成在像平面还是成在焦平面
- 【自动驾驶】7. MDC常用术语、DDS、SOME/IP
- 常用Apache Commons工具类备忘
- Java设计模式之代理模式(Proxy)