优化磁盘子系统


最终,所有数据都会保存到磁盘中。磁盘访问通常是毫秒级的,而且比其它组件(例如,内存和PCI操作,都是纳秒或微秒级别的)至少慢上千倍。Linux文件系统就是数据在磁盘上存储和管理的方式。

Linux上有性能和扩展性各异的各类文件系统可以选择。除了保存和管理磁盘上的数据,文件系统还得保证数据的完整性。最新的Linux发行版都把日志文件系统作为默认组件。日志可以避免在系统崩溃的时候,数据不一致。所有对文件系统元数据的修改都保存在一个分割的日志中,在系统崩溃之后,可以用来恢复到数据一致的状态。日志还会节约恢复时间,因为系统重启的时候不用检查文件系统。和其它问题一样,你必须在性能和完整性之间做一个平衡。然而,进入到企业数据中心和商业环境的Linux服务器,会被提出高可用的要求。

作为对各类文件系统的补充,Linux内核2.6有4种I/O调度算法,可以在不同任务和场景下使用。每个I/O elevator都有不同的特性,可能只合适特定的硬件配置和任务。有些elevator采用流式I/O,通常用在多媒体或者桌面PC环境中,有些elevator则偏重于低延时需要的数据库一类工作。

在本节中,我们学习ReiserFS和Ext3这类基本文件系统的行为和优化方法,以及kernel 2.6中I/O elevator的优化潜力。

安装前的硬件考虑

在Linux发行版文档中,通常指明安装该操作系统的CPU速度要求和最小内存,以及完成安装所需的最小磁盘空间!但是没有说明如何初始化安装磁盘子系统。Linux服务器可能工作在任何环境中,所以第一个问题是:这个服务器是用来做什么事情的?

磁盘子系统会影响到整个服务器的性能,决定I/O是否会成为性能瓶颈的关键是理解服务器的用途。

在下面的例子中,I/O是最重要的子系统:

  • 文件和打印服务器需要把文件快速在用户和磁盘见转移。因为文件服务器是目的是把文件传给客户端,所以服务器必须首先从磁盘中读取所有数据。

+数据库服务器的最终目标是从磁盘上的仓库里搜索和检索数据。及时内存足够,大多数数据库服务器还是会执行把大量磁盘I/O,把数据记录读入内存或者把修改写入磁盘。

以下场景中,磁盘I/O不是最重要的系统:

  • 邮件服务器中,服务器是一个电子邮件的仓库和路由器,瓶颈通常在通信负载。网络比较重要。

  • web服务器是处理Web页面(静态,动态,或者二者皆有)的,对其影响较大的是网络和内存。

驱动器数量

磁盘驱动的数量会显著影响性能,因为每个驱动器都会增加系统的总带宽。通常大家都只考虑到磁盘的容量需求,吞吐量需求通常不那么被看重,或者直接被忽视。优化磁盘性能的关键是增加I/O请求的读写磁头数量。

在RAID(redundant array of independent disks,独立磁盘冗余阵列)技术中,你可以把I/O分散到多个磁盘。Linux下有两种RAID:软件RAID和硬件RAID。除非服务器硬件支持硬件RAID,否则你只能选择软RAID。如果需求增加,你可以进一步选择效率更高的硬件RAID方案。

如果需要实施硬件RAID阵列,首先你需要RAID控制器。在这种情况下,磁盘子系统由多块磁盘和控制器一起组成。

贴士:通常,增加驱动器是改善服务器性能的最有效办法。

记住,磁盘子系统的性能是由给定设备所能处理的输入输出请求数决定的。一旦操作系统或磁盘缓存不能容纳读写请求的数据大小,磁盘的物理主轴就开始工作。比如下面的例子。某磁盘一秒能处理200个I/O。而你的应用执行4KB的随机写操作,所以流和请求合并都不适合。磁盘的最大吞吐计算方法是:

物理磁盘每秒I/O数量 * 请求大小 = 最大吞吐量

按照这个计算方法,上面例子中的结果是:

200 * 4 KB = 800 KB

800 KB是物理最大值,改善性能的办法是增加更多磁盘或者让应用一次写入更大的数据。在DB2数据库中,可以配置使用更大的请求大小,大多数情况下这都你提升磁盘吞吐。

分区

分区是 把磁盘上一些相邻块作为独立磁盘使用。现在的Linux发行版中,默认情况下就可以通过划分逻辑卷来动态分区。

Linux中,关于最佳磁盘分区有很大的争论。只分根分区的做法可能导致问题,因为不能满足的重新定义的新需求。太多磁盘分区又可能导致文件系统管理的困难。在安装过程中,Linux会提供创建多个分区的选项。

在Linux上划分多分区或者逻辑卷的好处:

  • 通过更细粒度的文件系统属性增强安全。

例如,/var和/tmp分区是系统上所有用户和进程有权限访问的,很容易发生恶意行为。如果有为他们设置单独的分区,在这些分区需要重建或者恢复的时候可能减小对系统的影响。

  • 加强数据完整性,磁盘崩溃导致的数据数据丢失只会影响相关的分区。

例如,如果系统上没有做软硬RAID,服务器磁盘崩溃了,只有坏磁盘上的分区需要替换和恢复。

  • 可以在不影响更多静态分区的情况下安装和升级系统。

例如,如果/home没有单独分区,将会在系统升级的时候被覆盖掉,会丢失存储的所有用户文件。

  • 更高效率的备份过程

在设计分区布局的时候需要充分考虑备份工具。了解备份工具是基于分区还是更细粒度,比如说文件系统。

下表中列出了可能需要从根分区独立的分区,可以提升灵活度和更好的性能。

分区 内容和服务器环境
/home 文件服务环境中最好单独给/home分区,这是系统上所有用户的home目录,这个分区上的空间很容易塞满,所以隔离这个目录,避免对整个磁盘空间造成太大影响
/tmp 如果服务器运行在高性能计算环境中,计算过程中需要很多临时空间,在计算完成后释放
/usr 该目录下存放了内核源码树和Linux文档,以及大量的可执行文件。/usr/local目录下存放了系统上所有用户都可以访问的可执行文件,也是存放自己的脚本的最佳目录。如果将/usr单独分区,在重新安装和升级的过程中只要不重新格式分区,文件都不需要重新安装。
var 在mail、Web和打印服务环境中,/var分区很重要,因为它保存了这些应用日志,以及所有的系统日志。数据会慢慢的填满这个分区。如果这个分区不是独立的,在/var被填满的时候,服务可能会受到影响。根据运行的服务不同,可以把邮件服务器的/var/spool/mail和/var/log单独划分
/opt 第三方软件,比如Oracle的数据库通常是在这个分区中。如果没有分区,会被安装到/分区,如果没有足够的空间,会安装失败

关于Linux如何处理文件系统的更多信息,查看文件系统层级的标准主页:

http://www.pathname.com/fhs

I/O elevator的调整和选择

随着Linux内核2.6新的I/O调度算法,系统在处理不同类型I/O的时候有了更高的灵活性。系统管理员要为指定的硬件和软件选择最合适的elevator。此外,每个I/O elevator有一组调优选项,可以把系统朝着特定的需求调整。

选择正确的I/O elevator

对于多数服务器负载,CFQ(Complete Fair Queuing) elevator和deadline elevator都是不错的选择,都为典型多用户、多进程服务器环境做过优化。企业发行版通常默认是CFQ elevator。在IBM System z的Linux中,默认的是deadline 调度。特定的环境应该选择特定的I/O elevator。在RHEL 5.0和Novell SUSE Linux Enterprise Server 10,可以为单独的磁盘子系统设置I/O调度器,而在它们的上一版本中,只能做系统全局设置。由于可以为每个磁盘子系统设置I/O elevator,管理员可以在磁盘子系统上隔离不同的I/O类型(例如密集型负载),并且选择合适的elevator 算法。

  • 同步文件系统访问

某些类型应用需要同步的文件系统操作。比如在数据库应用中可能用上raw文件系统,或者缓存异步磁盘访问的非常大的磁盘子系统上。在这种情况下,默认的elevator通常具有最低的吞吐和最高的时延。在大约16KB的场景下,其它三个算法的表现差不多好,之后,CFQ和NOOP开始具有比deadline更高的性能(除非磁盘访问需求竞争十分强烈),结果如下图。

各个IO Elevator的随机读性能

  • 复杂磁盘子系统

测试表明,NOOP elevator在高端服务器环境是个有意思的选择。在使用ServerRAID或TotalStorage DS等复杂的磁盘配置时,NOOP elevator的无序性成为了它的优势。企业类磁盘子系统可能包含多个SCSI或者光纤磁盘,每个都包含独立的磁盘头和数据带。在这种复杂环境中,I/O elevator很难正确预测I/O行为,所以,你可能会看到使用NOOP /IO elevator获得同等性能,只产生较少的开销。数百块磁盘的大型的基准测试,大多数使用NOOP elevator。

  • 数据库系统

由于数据库系统的自然寻址特性,选择deadline elevator可以获得较好性能。

  • 虚拟机

虚拟机,无论在VMware还是System z,大多数都是通过一个虚拟层和底层硬件进行通信。所以,虚拟机意识不到分配的磁盘是单个SCSI盘还是TotalStorage DS8000上的一组光纤通道磁盘。虚拟层负责必要的I/O重排序以及和物理块设备的通信。

  • 绑定CPU的应用

有些I/O调度器可以提供卓越的吞吐的量,同时也产生更大的系统开销。CFQ和deadline所产生的开销来自于对I/O queue的聚合和排序。有时CPU、性能对系统的限制大于磁盘性能的影响。比如说在科学计算或者处理数据仓库非常复杂的查询的领域。在这种场景下,NOOP elevator比其它elevator有更多的优势,因为它只产生较少的CPU负载,如下图。但是,需要注意的是,从吞吐量和CPU负载来看,deadline和CFQ依旧是大多数异步文件系统的最好选择。

异步场景下io-elevator的CPU使用率

  • 单ATA或SATA盘子系统

如果你使用的是单个ATA或者SATA磁盘,考虑使用预期I/O elevator吧,重新排序写I/O,以适应设备的单磁头。

nr_request

内核2.6的可插拔I/O调度器实现还有增加和减少向磁盘发起请求数量的功能。nr_requests和许多其它优化参数一样,没有一个最佳的设置。正确的取值更多的是依赖于底层磁盘系统,而不是I/O负载行为。request_nr的不同取值产生的影响,也不如文不同件系统和I/O调度器所产生的影响如上面的图那样显而易见。如下图所示,nr_requests对deadline elevator的影响比对CFQ elevator的影响要小。

nr_requests对使用deadline elevator的ReiserFS随机写测试

大请求队列可能会为写入大量小文件的负载提供很高的吞吐量。如下图所示,设置8192提供最高级别性能的I/O大小是16KB。在I/O大小为64KB的时候,nr_requests值从64到8192都是差不多的性能。随着I/O大小的增加,低级别的nr_requests通常都会产生卓越性能。可以使用如下命令修改请求数:

# echo 64 > /sys/block/sdb/queue/nr_requests

Ext3上CFQ elevator在不同nr_requests下随机写

重要的是,当前企业版Linux提供了基于单个磁盘子系统的nr_requests选项。所以,可以针对不同I/O模式分别优化调整。例如在数据库系统中,日志和数据应该存放在专门的磁盘或者磁盘子系统。在这个例子中,应该给日志分区设置很大的nr_requests值,用来执行很多的小尺寸写I/O,给数据分区设置很小的nr_requests值,可能就会看到128KB大的读I/O。

贴士:衡量和计算平均I/O大小的方法,参考前面的iostat。

read_ahead_kb

在大的读I/O流中,增加提前读取缓冲的大小会提升性能。注意,因为大多数都是随机I/O的原因,所以在一般情况下,增加这个值不会增强性能。read_ahead_kb定义了预读多少数据。这个值保存在/sys/block//queue/read_ahead_kb中,单位是KB。可以使用cat或者echo命令修改:

# cat /sys/block/<disk_subsystem>/queue/read_ahead_kb
# echo 64 > /sys/block/<disk_subsystem>/queue/read_ahead_kb

文件系统的选择和优化

前面已经说过,不同类型的文件系统适用于不同的工作负载场景。如果你有选择文件系统的自由,你应该好好考察下Ext、JFS、ReiserFS、XFS,比较看哪种比较符合你的需求。一般来说,ReiserFS适用于很小的I/O请求,XFS和JFS适合很大的文件系统和很大的I/O大小。Ext3的能力恰好在ReiserFS和JFS/XFS之间,它能处理小I/O请求,并且提供很好的多处理扩展性。

JFS和XFS最适合高端数据仓库,科学计算和大的SMP服务器,以及流媒体服务器。ReiserFS和Ext3主要用在文件、Web和邮件服务器等场景。对于写频繁、而且I/O大小在64KB以下的环境,ReiserFS相比Ext3的优势在默认的日志模式上,如下图。但是,这仅仅是在同步文件操作的时候。

Ext2也是一个选择。由于不具备日志功能,无论是访问模式,还是I/O大小,Ext2在同步文件系统上的表现都优于ReiserFS和Ext3。所以,在性能比数据完整性还重要的时候,Ext2也是个不错的选择。

ext和reiserfs的随机写吞吐量比较

在大多数同步文件系统场景中,默认日志模式的ReiserFS文件系统(数据有序)通常提供比Ext3更好的性能。但是,在默认日志模式为调整为writeback的时候,Ext3和ReiserFS具有同等的性能,如下图。

同步场景ext3和reiserfs随机写吞吐量的比较

使用ionice分配I/O优先级

CFQ I/O elevator的一个新特性是可以在进程级别分配优先级。ionice可以限制特定进程的磁盘利用率。在撰写本文的时候,可以使用ionice分配三种优先级:

  • Idle: 分配Idle优先级的进程只有在没有其它进程被分配best-effort或者更高访问级别的时候,才能访问磁盘。对某些进程,只有在系统有空闲资源的时候才能运行,如updatedb,这个设置就很有用。

  • Best-effort:所有没有指定I/O优先级的进程,默认都会分配这个优先级。有8(0~7)种有限级别,数值越小,级别越高。

  • Real time:最高的I/O优先级是real time,意味着进程总是可以有限访问磁盘子系统。real time也有8个级别。需要注意的是,给某个进程分配了real time级别之后,可能导致其它进程处于饥饿状态。

ionice有如下的选项:

-c <#> I/O 优先级1是real time,2是best-effort,3是idle

-n <#> I/O 优先级别从0到7

-p <#> 正在运行进程的进程号,不使用-p,开启一个使用该优先级的任务

下面的例子中,给PID为113的进程分配idle I/O优先级。

# ionice -c3 -p113

更新访问时间

Linux文件系统会记录文件何时被创建、更新和访问。在读写文件的时候会更新last-time-read的属性。由于写操作很浪费,取消不必要的I/O可以提升整体性能。但是,在大多数情况下,禁用文件访问时间更新只会带来很小的性能提升,

使用noatime选项挂载文件系统可以取消更新inode访问时间。如果文件或者目录的更新时间不是很重要,比如在web服务器上,管理员可能会在/etc/fstab挂载选项中添加noatime标志。禁用访问时间更新可以获得0%~10%的性能提升,可以减轻3%的文件服务器负载。

/dev/sdb1 /mountlocation ext3 defaults,noatime 1 2

注意:通常,给/var独立分区,并且设置noatime极好的做法。

选择文件系统的日志模式

大多数文件系统都支持如下三种和日志相关的参数,也就是mount中的data选项。但是,由于日志模式对Ext3文件系统的性能影响最大,所以我们建议对Red Hat的默认文件系统参数做调整:

  • data=jounal

这个日志选项通过记录数据和元数据,提供给最高的数据一致性。也带来最大的性能损耗。

  • data=ordered (default)

在这个模式下,只会记录元数据。文件数据优先写入。这是默认的设置。

  • data=writeback

该选项以数据一致性为代价,提供了最快的数据访问。虽然,通过记录元数据来保证数据一致性。但是,没有对真正的文件数据做任何处理,如果系统崩溃,旧数据可能出现在文件在文件中。使用writeback模式的元数据日志记录方式,可以和默认的ReiserFS、JFS、XFS相媲美。writeback日志模式增强了Ext3的性能,尤其是对小I/O,如下图所示。随着I/O大小的增长,回写模式的优势变小。注意,日志模式只影响写入性能。如果主要是读数据的负载(如web服务器),那么修改日志模式也没有用。

data=writeback时随机写性能影响

有三种修改日志模式的办法:

  • 在mount中指定:
mount -o data=writeback /dev/sdb1 /mnt/mountpoint
  • 在/etc/fstab文件中指定:
/dev/sdb1 /testfs ext3 defaults,data=writeback 0 0
  • 如果你想修改根分区默认的data=ordered选项,先在/etc/fstab中做上面的修改,然后执行mkinitrd命令扫描/etc/fstab文件中的修改,创建新的镜像。更新grub或者lilo指向新的镜像。

块大小

块大小是读写到磁盘的最小单位,会直接影响到服务器性能。如果你的服务器是需要处理很多小文件的,那么,把块大小设置小一点,效率会比较高。如果服务器是用来处理大文件的,就应该把块大小设置大一点,性能会比较高。不能对正在运行的服务器设置块大小,只能在重新格式化的时候修改。大多数Linux发行版允许块大小为1K、2K和4K。测试表明,修改块大小并不能给文件系统带来多少性能的提升,所以,一般保持为默认的4K就好了。

如果使用了硬件RAID方案,一定要仔细考虑阵列的条带大小(在光纤通道中是段)。stripe-unit size是在数据被存储在阵列中的一个驱动器,后续数据被存储在阵列的下一个驱动器上的间隔。选择正确的条带大小需要理解特定应用的请求大小。硬件阵列的条带大小和文件系统的块大小一样,都会限制影响整体磁盘性能。

流和连续内容通常会比较倾向于大的条带大小,可以减少磁头寻址时间,提升吞吐量。但是在数据库这类随机活动中,条带大小设置成和记录大小一致,可以获得较好的性能。

results matching ""

    No results matching ""