硬盘是用于存储数据的硬件,内存也是存储数据的,但二者不同的是内存数据是掉电不保存的而硬盘数据是可以永久保存的,在读写速度上硬盘比内存慢几个数量级。硬盘也是和程序交互比较频繁的硬件了,经常在看一些数据存储相关框架的原理时,会对一些硬盘方面的专业术语感到迷惑,不明白其中的含义。例如寻道时间,旋转时间,顺序读写,随机读写等。故整理了一下硬盘的工作原理,对于软件开发者来说,硬盘的相关操作都被封装成了系统接口,上层只管调用就行了。但了解硬件的工作原理对于软件开发还是有帮助的,本文将从硬件角度了解硬盘是如何运转的。
概述
从硬盘问世至今已经过了60多个年头,不管是容量、体积还是生产工艺都较之前有了重大革新和改进。硬盘按照其工作形式的不同分为两种,机械硬盘HDD(Hard Disk Drive)和固态硬盘SSD(Solid State Drive)。机械硬盘即传统的普通硬盘,主要由盘片、盘片转轴、磁头组件、磁头驱动机构、控制电路组成。固态硬盘类似于U盘技术,全电子结构,没有机械运动部件,采用集成电路存储技术,由控制单元和存储单元组成。
机械硬盘
机械硬盘(Hard Disk Drive)即传统普通硬盘,其构成部件主要是:磁盘、转轴及控制电机、磁头、磁头控制器、接口等几个部分构成。磁头在高速运转的磁盘上到达预先指定位置对数据进行读写操作。数据信息通过离磁性表面仅一根发丝直径大小的磁头,以电磁流改变极性方式写到磁盘上,数据信息可以通过相反的方式读取。其读写速度依赖于电机的转速,因为需要依靠电机带动磁盘高速转动使磁头找到指定位置进行读写,所以,在当下对读写速度的高要求下机械硬盘显得疲于应对。
固态硬盘
固态硬盘(Solid State Disk),简称固盘或者也称其为SSD,固态硬盘是基于固态电子存储芯片阵列制成的硬盘,由控制单元和存储单元组成。固态硬盘与机械硬盘在功能、规范和使用方式上完全相同,因其为纯芯片结构,相较于机械硬盘固态硬盘的体积和重量要小很多。从采用的存储介质来看主要分为两种,一种是选用Flash芯片作为存储介质,基于闪存设计的固态硬盘:根据闪存的不同又分为NAND闪存和NOR闪存。由于NAND闪存存储密度大,改写速度快等优点,因而在业界得到广泛应用。被制作成如体积小巧的U盘、笔记本硬盘、数码产品的存储卡等。NAND固态硬盘凭借可移动性,数据保护不受限于电源控制,更适合于个人用户在各种工况下使用。另一种固盘是采用DRAM作为存储介质,应用方式可分为SSD硬盘和SSD硬盘阵列两种。虽然它拥有较长的使用寿命,性能突出,美中不足的是为了保护数据安全需要独立的电源,一旦掉电RAM内的数据就将丢失,价格昂贵。所以目前DRAM固态硬盘应用范围较窄。
由于固态硬盘成本高,而且固态硬盘如果损坏难以恢复等原因,目前服务器广泛采用的还是机械硬盘作为数据存储媒介。需要注意的是机械硬盘驱动器磁头的飞行悬浮高度低、速度快,一旦有小的尘埃进入硬盘密封腔内,或者一旦磁头与盘体发生碰撞,就可能造成数据丢失,形成坏块,甚至造成 磁头和盘体的损坏。所以,硬盘系统的密封一定要可靠,在非专业条件下绝对不能开启硬盘密封腔,否则,灰尘进入后会加速硬盘的损坏。另外,硬盘驱动器磁头的寻道伺服电机多采用音圈式旋转或直线运动步进电机,在伺服跟踪的调节下精确地跟踪盘片的磁道,所以,硬盘工作时不要有冲击碰撞,搬动时要小心轻放。
机械磁盘结构
无论哪种机械硬盘,都主要由盘片、磁头、盘片主轴、控制电机、磁头控制器、数据转换器、接口、缓存等几个部份组成。其中所有的盘片都固定在一个旋转轴上,这个轴即盘片主轴。而所有盘片之间是绝对平行的,在每个盘片的存储面上都有一个磁头,磁头与盘片之间的距离比头发 丝的直径还小。所有的磁头连在一个磁头控制器上,由磁头控制器负责各个磁头的运动。磁头可沿盘片的半径方向动作,而盘片以每分钟数千转到上万转的速度在高速旋转,这样磁头就能对盘片上的指定位置进行数据的读写操作。因此这里也可以知道平时我们购买硬盘时,硬盘的转速就是一个很好的参考指标。转速越快说明硬盘效率越高,读写速度越快。
盘片与磁头
盘片的表面涂有磁性材料,厚度一般在0.5mm左右。碟片安装在主轴马达的转轴上,工作时所有碟片在主轴马达的带动下高速旋转。每个碟片都有正反两面,称为盘面。第1个碟片的正面称为0面,反面称为1面,第2个碟片的正面称为2面,反面称为3面…依次类推。每个盘面都有一个对应磁头负责读写该该盘面上的数据。关机时,磁头停留在硬盘的停泊区。
主轴上的盘片是绝对平行的,在每个盘片的存储面上都有一个磁头,当磁盘工作时,磁头与盘面并不会接触,硬盘工作时盘片飞速旋转产生的气流相当强,足以使磁头托起,并与盘面保持一个微小的距离。这个距离越小,磁头读写数据的灵敏度就越高,当然对硬盘各部件的要求也越高。
早期设计的磁盘驱动器使磁头保持在盘面上方几微米处飞行。稍后一些设计使磁头在盘面上的飞行高度降到约0.1μm~0.5μm,现在的水平已经达到 0.005μm~0.01μm,这只是人类头发直径的千分之一。磁头必须飞行在盘面上方,而不是接触盘面,这种位置可避免擦伤磁性涂层,但更重要的是不让磁性涂层损伤磁头。但是,磁头也不能离盘面太远,否则,就不能使盘面达到足够强的磁化,难以读出盘上的磁化翻转(磁极转换形式,是磁盘上实际记录数据的方式)所有的磁头连在一个磁头控制器上,由磁头控制器负责各个磁头的运动。磁头可沿盘片的半径方向动作,,每个磁头同一时刻也必须是同轴的,即从正上方向下看,所有磁头任何时候都是重叠的(不过目前已经有多磁头独立技术,可不受此限制)。由于每个盘片有正反两个面。每个盘面对应一个磁头用于读写数据。第一个盘面的正面的磁头称为0磁头,背面称为1磁头;第二个盘片正面的磁头称为2磁头,背面称为3磁头,以此类推。盘面数和磁头数是相等的。
磁道
磁盘在格式化时被划分成许多同心圆,这些同心圆轨迹叫做磁道(Track)。磁道从外向内从0开始顺序编号。硬盘的每一个盘面有300~1 024个磁道,新式大容量硬盘每面的磁道数更多。信息以脉冲串的形式记录在这些轨迹中,这些同心圆不是连续记录数据,而是被划分成一段段的圆弧,这些圆弧 的角速度一样。由于径向长度不一样。所以,线速度也不一样,外圈的线速度较内圈的线速度大,即同样的转速下,外圈在同样时间段里,划过的圆弧长度要比内圈 划过的圆弧长度大。每段圆弧叫做一个扇区,扇区从“1”开始编号,每个扇区中的数据作为一个单元同时读出或写入。一个标准的3。5寸硬盘盘面通常有几百到 几千条磁道。磁道是“看”不见的,只是盘面上以特殊形式磁化了的一些磁化区,在磁盘格式化时就已规划完毕。
柱面
所有盘面上的同一磁道构成一个圆柱,通常称做柱面(Cylinder),每个圆柱上的磁头由上而下从“0”开始编号。数据的读/写按柱面进行,即磁 头读/写数据时首先在同一柱面内从“0”磁头开始进行操作,依次向下在同一柱面的不同盘面即磁头上进行操作,只在同一柱面所有的磁头全部读/写完毕后磁头才转移到下一柱面,因为选取磁头只需通过电子切换即可,而选取柱面则必须通过机械切换。电子切换相当快,比在机械上磁头向邻近磁道移动快得多,所以,数据 的读/写按柱面进行,而不按盘面进行。也就是说,一个磁道写满数据后,就在同一柱面的下一个盘面来写,一个柱面写满后,才移到下一个柱面开始写数据。读数据也按照这种方式进行,这样就提高了硬盘的读/写效率。总结来说就是磁盘读写数据是按柱面进行,即在读写时磁头先寻找到数据所在的柱面(寻找磁道),然后再判断数据所在的盘面。这样大大提升了磁盘的读写效率,因为盘面的确定是电子操作速度非常快,但磁道的寻找需要电动马达带动磁头移到到指定磁道上,是机械操作。
扇区
操作系统以扇区(Sector)形式将信息存储在硬盘上,每个扇区包括512个字节的数据和一些其他信息。一个扇区有两个主要部分:存储数据地点的标识符和存储数据的数据段。扇区的第一个主要部分是标识符。标识符,就是扇区头标,包括组成扇区三维地址的三个数字:扇区所在的磁头(或盘面)、磁道(或柱面号)以及扇区在磁 道上的位置即扇区号。头标中还包括一个字段,其中有显示扇区是否能可靠存储数据,或者是否已发现某个故障因而不宜使用的标记。有些硬盘控制器在扇区头标中 还记录有指示字,可在原扇区出错时指引磁盘转到替换扇区或磁道。最后,扇区头标以循环冗余校验(CRC)值作为结束,以供控制器检验扇区头标的读出情况, 确保准确无误。扇区的第二个主要部分是存储数据的数据段,可分为数据和保护数据的纠错码(ECC)。在初始准备期间,计算机用512个虚拟信息字节(实际数据的存放地)和与这些虚拟信息字节相应的ECC数字填入这个部分。给扇区编号的最简单方法是l,2,3,4,5,6等顺序编号。如果扇区按顺序绕着磁道依次编号,那么当磁头读取完一个扇区后完全来不及定位到下一个连续的下扇区,盘面就已经旋转过了,这时只能等盘片旋转完一圈,在下一圈来时处理下一个扇区的数据,这极大浪费了时间,所以用交叉编排来解决这个问题。这是许多年前,IBM的一位杰出工程师想出的一个绝妙的办法,即对扇区不使用顺序编号,而是使用一个交叉因子(interleave)进行编号。交叉因子用比值的方法来表示。介绍了这么多,下面是硬盘工作原理的解说视频,比较详细
硬盘的性能
明白了硬盘的内部构造和工作原理后,就能大致分析出影响硬盘工作效率的原因了,其主要的性能指标有这几个。寻道时间,旋转时间和传输时间。这几个属性中旋转时间和操作时间基本由硬件决定了,唯一软件可优化的部分就只有寻道时间,Kakfa也正是利用这一点才到达了如此高的吞吐量。首先解释一下这几个指标的含义
寻道时间:读写数据时磁头首先要移到到指定磁道(柱面),这段时间称为寻道时间。一般硬盘的平均寻道时间在7.5~ 14ms,它比盘片旋转寻找扇区的时间还要长,因此,想要提高磁盘的IO读写性能,需在软件上下功夫,如何减少磁盘的随机读写。这里可以简单列举几个方法:(1).减少文件个数,使用大文件,尤其linux ext系列文件系统。(2).数据库表不要存储太大数据,可以采用分表方式减少单表容量,因为表太大数据库索引的原理就会导致磁盘随机读写增多。(3).提升每次写磁盘的数据大小,数据先缓存到buffer,等满了或超时了再写磁盘。
旋转时间:当磁头移动到指定磁道后,需要等待要操作的扇区旋转到磁头的下方,这段时间称为旋转延迟时间。这个时间取决于硬盘的转速。我们通常所说的7200转的硬盘的转就是这个,7200转的硬盘的平均旋转延迟等于1/2*120≈4.17ms。旋转延迟只和硬件有关。
传输时间:磁头进行读写传输数据所花费的时间
硬盘读写数据时间主要就花在这三个操作上,由此也可得出公式:磁盘读写时耗 = 寻道时间 + 旋转延迟时间 + 操作时耗。在聊完了硬盘的工作原理后,再来看看怎么利用硬盘的特性,提高IO的效率。以Kafka为例,首先必须了解关于硬盘读写的另外两个概念,即顺序读写和随机读写。
顺序读写:读写一个大文件。例如要写一个500M的文件到硬盘,而此时硬盘上有剩余的连续的600M大小空间。这时候写入的文件就是顺序读写。主要时间花费在了传输时间,而这个时间两种读写可以认为是一样的。在读取数据方面,磁盘会预读,预读即在读取的起始地址连续读取多个页面。提高了数据的命中,减少IO次数。
随机读写:读写多个小文件。例如要写一个500M的文件到硬盘,硬盘上还剩余不连续的600M大小空间,这是硬盘不得不将这个500M文件拆分成两个小文件,然后将它们写入到磁盘中。因为存在多次写入,就需要多次寻道和旋转延迟。而这个时间可能是传输时间的许多倍。此外因为数据没有在一起,预读也就没有作用了。
Kafka的高性能
kafka的高性能原因很多,它分布式的架构设计,数据零拷贝以及高效使用磁盘都是它如此高效的原因。不过这里只关注磁盘的利用。在官网上以及一些论坛上经常能看到kafka变态的性能和吞吐量,更为恐怖的是kafka的数据并没有通过内存来存储的,而是通过磁盘。据LINDEDIN统计,最新的数据是每天利用KAFKA处理的消息超过1万亿条,在峰值时每秒钟会发布超过百万条消息,就算是在内存和CPU都不高的情况下,Kafka的速度最高可以达到每秒十万条数据,并且还能持久化存储。我们知道现在的磁盘大多数都还是机械结构(SSD不在讨论的范围内),如果将消息以随机写的方式存入磁盘,就会按柱面、磁头、扇区的方式进行(寻址过程),缓慢的机械运动(相对内存)会消耗大量时间,导致磁盘的写入速度只能达到内存写入速度的几百万分之一,为了规避随机写带来的时间消耗,KAFKA采取顺序写的方式存储数据,如下图所示:
新来的消息只能追加到已有消息的末尾,并且已经生产的消息不支持随机删除以及随机访问,但是消费者可以通过重置offset的方式来访问已经消费过的数据。即使顺序读写,过于频繁的大量小I/O操作一样会造成磁盘的瓶颈,所以KAFKA在此处的处理是把这些消息集合在一起批量发送,这样减少对磁盘IO的过度读写,而不是一次发送单个消息。另一个是无效率的字节复制,尤其是在负载比较高的情况下影响是显着的。为了避免这种情况,KAFKA采用由Producer,broker和consumer共享的标准化二进制消息格式,这样数据块就可以在它们之间自由传输,无需转换,降低了字节复制的成本开销。