磁盘性能二三事之—4k对齐

简介: 本文将从机械硬盘的原理出发,讲解4K对齐的原理以及何时需要4K对齐。

我们先来回顾一下机械硬盘的结构。

机械硬盘主要由盘片(platter)、磁头(head)和相应的控制电路等部分所组成。盘片表面镀有磁性物质,二进制位被存储在这些磁性材料上。硬盘工作时,盘片围绕着一根中心主轴(spindle)旋转,磁头在电路控制下移动到指定位置然后将数据存储或读取出来。

盘片有两个面,都可以储存数据,因此每个磁盘片对应两个读写磁头。如果有N个盘片,就有2N个面,对应2N个磁头。
以盘片中心为圆心,把盘片分成若干个同心圆,每一个划分圆的"线条",就称为磁道(track)。
所有盘面上半径相同的磁道构成了柱面(cylinder)。盘片中有多少个磁道,就有多少个柱面。
screenshot

每个磁道又被等分为若干个弧段,这些弧段便是磁盘的扇区(sector)。扇区大小是固定的,两扇区之间以间隙(gap)来分割,间隙未被磁化。由于越接近磁盘圆心,磁道就越小,因此每个磁道的扇区数可能是不同的。在一些硬盘的参数列表上可以看到描述每个磁道的扇区数的参数,它通常用一个范围标识,例如373~746,这表示,最外圈的磁道有746个扇区,而最里面的磁道有373个扇区。

screenshot

早期的磁盘规范将扇区大小定义为512字节。然而随着硬盘容量的不断扩展,这一大小已不再能满足硬盘管理和性能提升的需要。为了提高容错能力和硬盘的使用及管理效率,IDEMA(International Disk Drive Equipment and Materials Association)将原来的每个扇区512字节改为每个扇区4096个字节,也就是现在常说的“4K扇区”。支持这一标准的硬盘称为高级格式化(Advanced Format)硬盘。

4K扇区格式继承了传统512字节扇区格式的关键设计要点,比如扇区起始区域的同步(synchronization)和地址(address)标志以及扇区结尾的纠错编码ECC(error correction coding)。4K扇区通过将中间的八个数据区域结合到一个扇区,减少了扇区头尾及间隙的个数,从而磁盘利用效率更高,同时也让ECC有足够的空间可以从50字节扩展到100字节。延长后的ECC采用新的算法,使得数据错误的检测和更正都有所改善。

screenshot

选择4K而不是其他长度作为AF标准主要是为了和其他计算机领域的其他标准保持一致,比如操作系统和处理器所支持的内存管理单元-页(page)的大小,关系型数据库标准交易的大小等。

由于4K扇区标准在2010年才完成制定,所以目前大量的硬件及软件系统仍然是以512字节扇区标准来设计的,其中包括了很多芯片集,操作系统,数据库引擎,硬盘分区和镜像工具,文件备份设备等。为了向下兼容这些系统及程序, 很多硬盘制造商都在AF格式的硬盘上集成了512字节转换固件。集成了这种固件的硬盘被称为Advanced Format 512e硬盘,其中512e代表512仿真(512 emulation)。

将4K物理扇区转换成512字节虚拟扇区这一过程对系统和硬盘来说都是透明的,系统对AF格式的硬盘所以发出的读写请求跟对传统格式的硬盘发出的请求一样。
在处理读请求的过程中,AF格式硬盘会将包含了所需要的512字节数据的整个4K扇区加载到内存中,转换固件会将所需要的512字节数据提取出来然后转化成512字节格式,再将其发送到主机。这一过程通常对性能都不会有影响,或者只有很小的影响。

处理写请求的过程比读请求要复杂一些,硬盘需要将包含目标数据的整个4K扇区读到内存中,再将改写后的数据和原有数据整合到一起,最后将这4K扇区一起写回到磁盘当中。这一读-改-写的操作在4K不对齐的情况下会给系统带来明显的性能影响。

以常见的NTFS文件系统为例,在版本6以前的规范中,其引导区占用63个扇区,真正的文件分区从第63个扇区之后开始存储。依照计算,63个扇区的大小为 63×512字节=31.5K,无法被4K整除,也可以说是4K没有对齐。扇区是磁盘的硬件物理参数,是对磁盘进行读写操作的最小单元。而磁盘与主存之间进行数据传输时的逻辑单元则为簇(cluster)或者块(block),其由一个或多个扇区所组成。一个簇只存放一个文件。NTFS数据传输单元-簇的默认大小为4K,如果从31.5K开始进行数据存储,那么每个簇都会跨越两个物理扇区,占据第一个扇区的后512字节和第二个扇区的前3584字节。这样文件系统在读写某个簇的时候,硬盘都需要对两个扇区进行读-改-写操作,而在4K对齐的系统里,只要一次操作就可以了。

screenshot

根据我们对SSD 0.5T云盘的测试,发现不对齐在写性能损耗方面的影响还是比较大的:

非4k对齐 随机读 块大小4k 读带宽:61002 KB/s IOPS:15200
块大小64k 读带宽:260110 KB/s IOPS:4100
4k对齐 随机读 块大小4k 读带宽:62517 KB/s IOPS:15479
块大小64k 读带宽:263080 KB/s IOPS:4379
非4k对齐 随机写 块大小4k 写带宽:25788 KB/s IOPS:6471
块大小64k 写带宽: 227951 KB/s IOPS:3501
4k对齐 随机写 块大小4k 写带宽: 48458 KB/s IOPS:12221
块大小64k 写带宽: 261159 KB/s IOPS:4281

注:上面这组数据是用fio压测出来的结果,仅供参考。

因此只要你的硬盘是Advanced Format的,都建议进行4K对齐。否则无论是对硬盘的读写速度,还是使用寿命,都将有不利的影响。

Linux系统的磁盘4k对齐

  1. 查看系统中磁盘物理大小扇区和逻辑大小扇区

    [root@demo vdg]# cat /sys/block/vdg/queue/physical_block_size
    512
    
    [root@demo vdg]# cat /sys/block/vdg/queue/logical_block_size
    512
    

    可以看到我的这块测试磁盘的物理扇区大小是512字节,逻辑扇区大小也是512字节,这样我们物理块到逻辑块的映射都是512字节的。

  2. 对齐分区
    查看现有磁盘是否是4k对齐,可以用fdisk -l -u:
    _2017_08_13_10_21_17

  3. 如何用fdisk 对齐分区:

        fdisk /dev/vdb
    
        WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
                 switch off the mode (command 'c') and change display units to
                 sectors (command 'u').
    
        Command (m for help): n
        Command action
           e   extended
           p   primary partition (1-4)
        p
        Partition number (1-4): 1
        First cylinder (1-208050, default 1):
        Using default value 1
        Last cylinder, +cylinders or +size{K,M,G} (1-208050, default 208050):
        Using default value 208050
    
        Command (m for help): x
    
        Expert command (m for help): b
        Partition number (1-4): 1
        New beginning of data (1-209714399, default 63): 128
    
        Expert command (m for help): p
    
        Disk /dev/vdb: 16 heads, 63 sectors, 208050 cylinders
    
        Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
         1 00   1   1    0  15  63 1023        128  209714272 83
         2 00   0   0    0   0   0    0          0          0 00
         3 00   0   0    0   0   0    0          0          0 00
         4 00   0   0    0   0   0    0          0          0 00
    
        Expert command (m for help): w
        The partition table has been altered!
    
        Calling ioctl() to re-read partition table. 
    
        The kernel still uses the old table. The new table will be used at
        the next reboot or after you run partprobe(8) or kpartx(8)
        Syncing disks.
    

    这样分区之后再用fdisk -l -u查看,已经是分区对齐了。

        Disk /dev/vdb: 107.4 GB, 107374182400 bytes
        16 heads, 63 sectors/track, 208050 cylinders, total 209715200 sectors
        Units = sectors of 1 * 512 = 512 bytes
        Sector size (logical/physical): 512 bytes / 512 bytes
        I/O size (minimum/optimal): 512 bytes / 512 bytes
        Disk identifier: 0x00055dd3
    
           Device Boot      Start         End      Blocks   Id  System
        /dev/vdb1             128   209714399   104857136   83  Linux
    

    用parted也可以做到分区对齐,parted和fdisk相比,支持更多的类型(支持GPT)和更大的分区尺寸:

        parted /dev/vdb
        GNU Parted 2.1
        使用 /dev/vdb
        Welcome to GNU Parted! Type 'help' to view a list of commands.
        (parted) unit s
        (parted) p
        Model: Virtio Block Device (virtblk)
        Disk /dev/vdb: 209715200s
        Sector size (logical/physical): 512B/512B
        Partition Table: msdos
    
        Number  Start  End         Size        Type     File system  标志
         1      128s   209714399s  209714272s  primary
    
        (parted) rm 1
        (parted) mkpart primary 128 100%
        (parted) p
        Model: Virtio Block Device (virtblk)
        Disk /dev/vdb: 209715200s
        Sector size (logical/physical): 512B/512B
        Partition Table: msdos
    
        Number  Start  End         Size        Type     File system  标志
         1      128s   209715199s  209715072s  primary
    

    Window系统磁盘分区对齐

    针对widnows 分区4k对齐方法
    C:\Users\Administrator>diskpart
    DISKPART> list disk 
    磁盘 ###  状态           大小     可用     Dyn  Gpt
    --------  -------------  -------  -------  ---  ---
    磁盘 0    联机               40 GB    39 GB(需要做4k对齐的盘)
    磁盘 1    联机               40 GB      0 B(可以运行系统的磁盘)
    DISKPART> select disk 0
    磁盘 0 现在是所选磁盘。
    DISKPART> list partition
    这个磁盘上没有显示的分区。
    DISKPART> clean
    DiskPart 成功地清除了磁盘。
    DISKPART> create partition primary align=1024   (做了4k分区对齐)
    DiskPart 成功地创建了指定分区。
    DISKPART> list partition
    分区 ###       类型              大小     偏移量
    -------------  ----------------  -------  -------
    * 分区      1    主要                  39 GB  1024 KB
    DISKPART> select partition 1
    分区 1 现在是所选分区。
    DISKPART> active
    DiskPart 将当前分区标为活动。
    DISKPART> format fs=ntfs unit=4096 quick  (在系统安装时,保持现在的分区不变)
    100 百分比已完成
    DiskPart 成功格式化该卷。
    

曾经遇到过两起案例,都是由于在使用SSD云盘的时候没有做到对齐分区,而造成磁盘性能不佳,所以当遇到磁盘IO性能不佳的问题的时候,除了观察后台IO负载是否很高,不妨也先来看一下你的磁盘分区是否做到了4k对齐?

目录
相关文章
|
存储 缓存 Oracle
常识四堆外内存
常识系列,作为一名互联网门外汉的科普系列 堆外内存除了在像netty开源框架中,在平常项目中使用的比较少,在现前的项目中,QPS要求高的系统中,堆外内存作为其中一级缓存是相当有成效的。所以来学习一下,文中主要涉及到这三分部内容 1. 堆外内存是什么?与堆内内存的区别 2. 怎么分配,与GC的影响 3. 开源框架使用 这篇文章写到最后,发现还只是回答了开源框架OHC的Why not use ByteBuffer.allocateDirect()?
1370 1
常识四堆外内存
|
8月前
|
存储 人工智能 程序员
【重学C++】【内存】关于C++内存分区,你可能忽视的那些细节
【重学C++】【内存】关于C++内存分区,你可能忽视的那些细节
186 1
|
存储 关系型数据库 MySQL
太强了!三种方案优化 2000w 数据大表!
太强了!三种方案优化 2000w 数据大表!
175 0
【读paper】比kmer更省空间的minimizer
【读paper】比kmer更省空间的minimizer
545 1
【读paper】比kmer更省空间的minimizer
|
存储 C语言
把玩数据在内存中的存储
前言:时光如梭,今天到了C语言进阶啦,基础知识我们已经有了初步认识, 是时候该拔高拔高自己了。 目标:掌握浮点数在内存的存储,整形在内存的存储。 鸡汤:时光易过,岁月蹉跎。
128 0
|
网络协议 Java 关系型数据库
分库分表就能无限扩容吗,解释得太好了!
前言 像我这样的菜鸟,总会有各种疑问,刚开始是对 JDK API 的疑问,对 NIO 的疑问,对 JVM 的疑问,当工作几年后,对服务的可用性,可扩展性也有了新的疑问,什么疑问呢?其实是老生常谈的话题:服务的扩容问题。
分库分表就能无限扩容吗,解释得太好了!
|
机器学习/深度学习 存储 算法
「错位算法时空」,让你彻底学会「时间」与「空间」复杂度
「错位算法时空」,让你彻底学会「时间」与「空间」复杂度
244 0
「错位算法时空」,让你彻底学会「时间」与「空间」复杂度
这就是多媒体开发 视频竟然比连续图片更省带宽
多媒体开发技术不仅技术栈庞大,许多技术需要深度钻研,学习起来并不容易。
1546 0