从磁盘原理理解文件读写优化
目录
案例背景
磁盘结构
盘面
磁道
柱面
启停区或着陆区(LandingZone)
扇区
读写过程
磁盘碎片的产生(1)
希捷硬盘读写性能测试报告
文件碎片
文件碎片定义
产生 原因
文件碎片和连续文件读取性能对比(100M相同内容的文件)
解决方案
避免随机读 写
随机读写危害
随机读写解决方案
异步刷盘和同步刷盘
同步刷盘
异步刷盘
小文件性能影响及解决方案
小文件性能影响
小文件解决方案
并发写提高数据入盘性能
广义并发写
狭义并发写
读写分离
读写分离的必要性
读写分离的解决方案
业界优秀案例
K afka的log文件系统
topic中partition存储分布
采用优化策略
数据过期删除及log大小固定策略
小文件合并增大吞吐量
案例背景
目前影响文件读写性能的点在于文件碎片,大量小文件,文件刷盘方式,随即读写等。基于上述几类瓶颈点给于解决方案。以便解决业务线现场大量的语音文件接入。
磁盘结构
硬盘在逻辑上被划分为磁道、柱面以及扇区.如下图所示:
数据的读/写按柱面进行,而不按盘面进行。也就是说,一个磁道写满数据后,就在同一柱面的下一个盘面来写,一个柱面写满后,才移到下一个扇区开始写数据。读数据也按照这种方式进行,这样就提高了硬盘的读/写效率。
盘面
硬盘的盘片一般用铝合金材料做基片,高速硬盘也可能用玻璃做基片。硬盘的每一个盘片都有两个盘面(Side),即上、下盘面,一般每个盘面都会利用,都可以存储数据,成为有效盘片,也有极个别的硬盘盘面数为单数。每一个这样的有效盘面都有一个盘面号,按顺序从上至下从“0”开始依次编号。在硬盘系统中,盘面号又叫磁头号,因为每一个有效盘面都有一个对应的读写磁头。硬盘的盘片组在2~14片不等,通常有2~3个盘片,故盘面号(磁头号)为0~3或 0~5。
磁道
磁盘在格式化时被划分成许多同心圆,这些同心圆轨迹叫做磁道(Track)。磁道从外向内从0开始顺序编号。硬盘的每一个盘面有300~1 024个磁道,新式大容量硬盘每面的磁道数更多。信息以脉冲串的形式记录在这些轨迹中,这些同心圆不是连续记录数据,而是被划分成一段段的圆弧,这些圆弧的角速度一样。由于径向长度不一样,所以,线速度也不一样,外圈的线速度较内圈的线速度大,即同样的转速下,外圈在同样时间段里,划过的圆弧长度要比内圈 划过的圆弧长度大。每段圆弧叫做一个扇区,扇区从“1”开始编号,每个扇区中的数据作为一个单元同时读出或写入。一个标准的3.5寸硬盘盘面通常有几百到几千条磁道。磁道是“看”不见的,只是盘面上以特殊形式磁化了的一些磁化区,在磁盘格式化时就已规划完毕。
柱面
所有盘面上的同一磁道构成一个圆柱,通常称做柱面(Cylinder),每个圆柱上的磁头由上而下从“0”开始编号。数据的读/写按柱面进行,即磁 头读/写数据时首先在同一柱面内从“0”磁头开始进行操作,依次向下在同一柱面的不同盘面即磁头上进行操作,只在同一柱面所有的磁头全部读/写完毕后磁头 才转移到下一柱面(同心圆的再往里的柱面),因为选取磁头只需通过电子切换即可,而选取柱面则必须通过机械切换。电子切换相当快,比在机械上磁头向邻近磁道移动快得多,所以,数据的读/写按柱面进行,而不按盘面进行。也就是说,一个磁道写满数据后,就在同一柱面的下一个盘面来写,一个柱面写满后,才移到下一个扇区开始写数据。读数据也按照这种方式进行,这样就提高了硬盘的读/写效率。一块硬盘驱动器的圆柱数(或每个盘面的磁道数)既取决于每条磁道的宽窄(同样,也与磁头的大小有关),也取决于定位机构所决定的磁道间步距的大小。
启停区或着陆区(LandingZone)
磁头靠近主轴接触的表面,即线速度最小的地方,是一个特殊的区域,它不存放任何数据
扇区
操作系统以扇区(Sector)形式将信息存储在硬盘上,每个扇区包括512个字节的数据和一些其他信息。一个扇区有两个主要部分:存储数据地点的标识符和存储数据的数据段。
读写过程
即一次访盘请求(读/写)完成过程由三个动作组成:
1)寻道(时间):磁头移动定位到指定磁道 ,经验值在3~15ms
2)旋转延迟(时间):等待指定扇区从磁头下旋转经过 ,60*1000/7200/2 = 4.17ms(7200rpm硬盘)
3)数据传输(时间):数据在磁盘与内存之间的实际传输(200M/S,希捷4TB硬盘)
因此在磁盘上读取扇区数据(一块数据)所需时间:
Ti/o=tseek +tla + n *twm
其中:
tseek 为寻道时间
tla为旋转时间
twm 为传输时间
磁盘碎片的产生(1)
俗话说一图胜千言,先用一张ACSII码图来解释为什么会产生磁盘碎片。
这里所说的方法二就像是我们的windows系统的存储方式,每个文件都是紧挨着的,但如果其中某个文件要更改的话,那么就意味着接下来的数据将会被放在磁盘其他的空余的地方。
如果这个文件被删除了,那么就会在系统中留下空格,久而久之,我们的文件系统就会变得支离破碎,碎片就是这么产生的。
Linux文件碎片基本很少,Linux的ext2,ext3,ext4文件系统——ext4是Ubuntu和目前大多发行版所采用的文件系统——会以一种更加智能的方式来放置文件。Linux的文件系统会将文件分散在整个磁盘,在文件之间留有大量的自由空间,而不是像Windows那样将文件一个接一个的放置。当一个文件被编辑了并且变大了,一般都会有足够的自由空间来保存文件。如果碎片真的产生了,文件系统就会尝试在日常使用中将文件移动来减少碎片,所以不需要专门的碎片整理程序。
希捷硬盘读写性能测试报告
硬盘规格:希捷新酷鱼2TB硬盘(3碟版)的HD Tune读取
上述出现原因,从磁盘结构上看,角速度一致,线速度由于半径越来越小,导致读写速度下降。
文件碎片
文件碎片定义
文件碎片是因为文件被分散保存到整个磁盘的不同地方,而不是连续地保存在磁盘连续的簇中形成的
产生 原因
(1)在文件操作过程中,Windows系统可能会调用虚拟内存来同步管理程序,这样就会导致各个程序对硬盘频繁读写,从而产生文件碎片。
(2)还有一种情况就是当中间的一个扇区内容被删除后,新写入一个较小的文件,这样在这个文件两边就会出现一些空间,这时候再写入一个文件,两段空间的任意一部分都不能容纳该文件,这时候就需要将文件分割成两个部分,碎片再次产生了。
(3)最常见的就是下载电影之类的大文件,这期间大家一般都会处理一下其它事情,而下载下来的电影文件被迫分割成若干个碎片存储于硬盘中。因此下载是产生碎片的一个重要源头。还有就是经常删除、添加文件,这时候如果文件空间不够大,就会产生大量的文件碎片,随着文件的删改频繁,这种情况会日益严重。
文件碎片和连续文件读取性能对比(100M相同内容的文件)
从上图看出,在采用nio读取文件的时候,buffer的大小设置为512kb,读取性能最高,文件碎片读取为80ms,连续文件读取60ms,得知,文件碎片严重影响读写性能。
解决方案
在我们目前开发的文件存储系统,由于各种原因,很难避免文件碎片的产生。基于迅雷下载思想的启发,我们在从小文件读取数据写入大文件的时候,可以事先分配好大文件的尺寸,占据固定大小的连续的磁盘分区。这样在采用修改的方式,把每个字节修改成指定的数据,会得到连续完整的文件,避免磁盘碎片的产生。
分配尺寸方式:RandomAccessFile raf = new RandomAccessFile(file, “rw”);
Raf.setLength(1024*1024*1024);
这样可以分配1G大小的文件,经测试1ms左右的时间可以完成上述分配。
避免随机读 写
随机读写危害
由磁盘结构一节可知,数据写入和读取时间由寻址,磁头旋转,数据传输组成,如果随即读写的话,每一次数据读写时间=寻址(12ms)+磁头旋转(3ms)+数据传输(1ms,小文件),如果是顺序读写时间=数据传输。
随机读写解决方案
磁盘分区循环写入数据,先将一块磁盘分成3个分区,1分区写完,写2分区,2分区写完,写3分区,3分区写完,将1分区快速格式化,然后将数据写入1分区。
异步刷盘和同步刷盘
同步刷盘
采用零拷贝的方式,采用nio的强制刷盘策略,等待文件真正落盘后,才会继续代码流程,小文件性能大概在2~3M/s左右。
异步刷盘
javaIo的普通刷盘方式,就是一种异步刷盘,当调用文件IO的flush的方式时,其实是向内核发送一条刷盘指令,直接返回。小文件性能在13M/S左右。
小文件性能影响及解决方案
小文件性能影响
文件读写时间=寻址+旋转延迟+数据传输,小文件读写的性能瓶颈在寻址上。
小文件200kb:寻址时间=12ms
旋转延迟=3ms
数据传输=1ms
上述读写性能在0.2M * (1/0.016)=12.5M/S,IOPS=62次/s
大文件 20GB: 寻址时间=12ms
旋转延迟=3ms
数据传输=20*1024/200=102400ms
上述读写性能在 20*1024M *(1/102415) = 200M/s,基本可以发挥文件读写极致,瓶颈在数据传输上,这是我们想要的效果。
小文件解决方案
将小文件合并成大文件进行存储,这样读取性能就会大大提高,目前kafka的log存储和读取原理采用的就是此种方式。
数据块定义:起始字符,版本标识,chunkSize,subChunkId, subChunkSize,Data,结束标记。
存储:存储小文件的时候,首先抽取一个可存入大文件路径, 封装小文件的元数据和数据信息,追加到大文件的尾部。返回一个加密后的ID,这个id包含小文件的位置和基本信息。
读取:读取根据id进行读取,也可遍历读取。
删除:在元数据中加标记,不真正删除文件,避免文件碎片, 后期统一格式化处理。
并发写提高数据入盘性能
广义并发写
一块磁盘启用多个线程进行写数据,根据硬盘知识可知,一块硬盘有很多磁头,但是只有一个有效磁头在运作,多个线程会造成磁头争夺,导致写入性能下降。
狭义并发写
一台linux机器可以多块硬盘,比如4块,为了避免争夺磁头,每块硬盘最多只能由一个线程操作,这样就可以同时写入4个数据分别落到不同的硬盘中,实现方式架构如下图:
Queue:数据硬盘目录,四块硬盘,四个目录,阻塞队列
线程池:根据硬盘数量分配线程池线程数量,四块硬盘,四个线程。
流程:当数据准备入库,获取线程,线程从队列中请求入库硬盘,根据请求地址入库。
读写分离
读写分离的必要性
根据硬盘知识可知,一块硬盘有很多磁头,但是只有一个有效磁头在运作,如果同时有数据进行读和写操作,就会造成磁头争夺,导致性能下降。
读写分离的解决方案
目前同一进程读写分离可以实现,不同进程的读写分离无法实现。
业界优秀案例
K afka的log文件系统
topic中partition存储分布
Kafka集群只有一个broker,xxx/message-folder为数据文件存储根目录,在Kafka broker中server.properties文件配置(参数log.dirs=xxx/message-folder),例如创建2个topic名 称分别为report_push、launch_info, partitions数量都为partitions=4
存储路径和目录规则为:
xxx/message-folder
|--report_push-0
|--report_push-1
|--report_push-2
|--report_push-3
|--launch_info-0
|--launch_info-1
|--launch_info-2
|--launch_info-3
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。
采用优化策略
kafka是一个高吞吐量分布式消息系统,并且提供了持久化。其高性能的有两个重要特点:1、并发,2、连续读写性能远高于随机读写。
优化着重于并发策略,下面举两个案例说明:
一个topic分成多个patition,磁盘总数是一块,这样多个分区会往同一块磁盘写入数据,造成广义并发写,磁头争夺,性能急剧下降。
一个topic分成多个patition,磁盘总数是多块,这样每一个分区会写一块硬盘,造成狭义并发写,性能得到保障。
数据过期删除及log大小固定策略
Kafka并未提供删除数据的api,可以设置过期时间,kafka根据过期时间自动删除。
Kafka的log大小固定,所以一块盘中的log数据基本上都是一样大,根据文件写入规则,基本上不会产生文件碎片。
小文件合并增大吞吐量
众所周知,kafka 是一个消息中间件,存储采用固定大小的log系统,当我们将小文件数据或者是一条条日志存储到kafka中,都会被写到指定的log文件,这样小文件就会被组合成大文件。
每个log entry格式为"4个字节的数字N表示消息的长度" + "N个字节的消息内容";每个日志都有一个offset来唯一的标记一条消息,offset的值为8个字节的数字,表示此消息在此partition中所处的起始位置..每个partition在物理存储层面,有多个log file组成(称为segment).segment file的命名为"最小offset".kafka.例如"00000000000.kafka";其中"最小offset"表示此segment中起始消息的offset.
获取消息时,需要指定offset和最大chunk尺寸,offset用来表示消息的起始位置,chunk size用来表示最大获取消息的总长度(间接的表示消息的条数).根据offset,可以找到此消息所在segment文件,然后根据segment的最小offset取差值,得到它在file中的相对位置,直接读取输出即可。
从磁盘原理理解文件读写优化相关推荐
- 大文件读写优化问题。现有两个文件,一个837M的order.tbl,一个3.62G的lineitem.tbl,对这两个表进行嵌套连接
在做数据库作业时遇到的优化问题! 作业要求: 实现一个基于嵌套循环策略的两表连接算法 • 算法原理: FOR EACH CHUNK c1 OF t1 {IF c1 NOT IN MEMORY READ ...
- python中io.textio_Python文件读写概述(IO操作、文件读写、stringiobytesio、序列化),python,的,小,总结,StringIOBytesIO...
IO操作 在进行文件的读写之前,需要说明几点.首先,运行的程序和读取的数据都会在内存中缓存. 进入到 程序或数据 内存 其次,用python程序进行文件的读写,需要创建一个小工具–文件流,用来处理数据 ...
- Go语言学习笔记(十八)之文件读写
25.文件读写 1.文件打开和读 A.文件分类:文本和二进制文件 B.文件存取方式:随机存取和顺序存取 文件打开代码示例: 1: package main 2: 3: import ( 4: &quo ...
- python-- 模拟淘宝自动回复--文件读写的问题//记录用户的登录日志(记录登录时间)
记录用户的登录日志(记录登录时间)--磁盘的操作--文件读写的操作 import time #使用函数 --使用时间 #显示日志 def show_info():print('输入提示数字,执行相应的 ...
- python文件读写原理的一些理解:r,r+,w,w+,a,a+,以及seek()方法
理解文件中的读取或者写入顺序要先知道对文件进行读写时它的工作模式:在python中对文件进行读写时,是依据文件中光标的位置进行读写的. 这里就要引入seek()方法: seek(offset, whe ...
- Linux文件读写机制及优化方式
本文只讨论Linux下文件的读写机制,不涉及不同读取方式如read,fread,cin等的对比,这些读取方式本质上都是调用系统api read,只是做了不同封装.以下所有测试均使用open, read ...
- linux 文件缓存大小设置,Linux文件读写机制及优化方式
导读 Linux是一个可控性强的,安全高效的操作系统.本文只讨论Linux下文件的读写机制,不涉及不同读取方式如read,fread,cin等的对比,这些读取方式本质上都是调用系统api read,只 ...
- (13)web安全|渗透测试|网络安全 注入/跨库查询/文件读写/常见的防护原理 详细图解
目录 高权限注入及低权限注入 跨库查询: 文件读写操作 流程: 找路径: 方法一: 方法二: 方法三: 方法四: 方法五: 方法六: 方法七: 知道路径后,再执行文件的读写操作 文件的写入: 可能遇到 ...
- 【Python 基础教程 20】全面掌握Python3输入输出:从入门到高级的实用指南(文件读写,Excel读写,Markdowm文件读写)
目录标题 1. 简介 1.1 Python3 输入输出的定义 1.2 输入输出的重要性和常见应用场景 2. 标准输入输出 2.1 介绍标准输入(stdin) 2.2 介绍标准输出(stdout) 2. ...
最新文章
- 你听说过反摩尔定律吗?
- h桥控制电机刹车_控制直流电机正反转以及刹车电路设计 (转载)
- php的安装配置,PHP 安装/配置
- ios 自己创建的动态frameworks 怎么发布_iPadOS/iOS 13.1 正式发布,这才是真正的 iOS 13 系统...
- Android_Exynos4412_iROM_Secure_Booting_Guide_Ver.1.00.00
- OpenCASCADE绘制测试线束:拓扑命令之历史命令
- 十八般武艺玩转GaussDB(DWS)性能调优(二):坏味道SQL识别
- dedeampz-php环境整合套件,DedeAMPZ官方下载
- html云文件系统,一种HTML5云文件系统
- Linux Autofs自动挂载服务详解
- python快速示例_python实现快速排序的示例(二分法思想)
- 2020高压电工考试及高压电工复审模拟考试
- 使用matlab导入excel表格带有时间的数据并绘制曲线
- Jsp四种变量作用范围
- SpringBoot生命周期
- WIN10 系统重新安装 WIN7 系统步骤
- 中文分词-转载3_一个北京程序员
- python open encoding=utf-8_Python 文件操作中的读写模式:open(path, '-模式-',encoding='UTF-8')...
- 挺着肚皮的小淘气 蒙语版铃声 挺着肚皮的小淘气 蒙语版手机铃...
- 如何设计产品的引流诱饵?如何控制引流产品的成本呢?