Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2573958
  • 博文数量: 323
  • 博客积分: 10211
  • 博客等级: 上将
  • 技术积分: 4934
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-27 14:56
文章分类

全部博文(323)

文章存档

2012年(5)

2011年(3)

2010年(6)

2009年(140)

2008年(169)

分类: 系统运维

2008-05-30 13:23:57

AIX 5L v5.2.0.10(或称作AIX 5L v5.2 ML01)在增强的日志文件系统(JFS2)上引入了并行I/O(Concurrent I/O)的新的功能。在许多应用环境下,这一新的功能可提高文件系统访问的性能,尤其对于关系型数据库的应用。在JFS2的文件系统上采用并行I/O
(Concurrent I/O)技术后,可以得到与采用裸设备相似的性能。本文将对并行I/O
(Concurrent I/O)做一个简要的介绍并给出在Oracle 9i数据库上进行性能比较的结果。

1. 简介

文件系统长久以来一直是UNIX存储管理的核心,UNIX的用户通过系统命令和系统接口对存储在文件系统上的数据进行操作和管理.文件系统的使用提供了对数据进行存储的有效手段。

如同使用其它方式一样,文件系统的使用是对于性能与易用性平衡的结果。在应用和磁盘之间传输数据最快的方式是直接进行访问,如使用裸设备。而使用文件系统来存数数据会产生很多额外开销,如串行访问,缓存和数据拷贝。这些都将对性能产生影响。使用裸设备进行数据的存储虽然能减少这些额外开销,但对用户的技术水平要求较高,而且不同应用程序对裸设备的使用方式也不同,需要对用户进行额外的培训。但由于对裸设备进行访问的高性能,传统上来说,数据库的应用程序更希望使用裸设备而不是文件系统。在JFS2文件系统上采用并行I/O(Concurrent I/O)技术后,数据库用应用可以得到与采用裸设备相似的性能。

2. 数据库应用

对于数据库应用来说,之所以采用裸设备比采用文件系统具有更好的I/O性能,主要是由于文件系统的一些特性:
* 文件缓存
* 文件写保护锁或inode锁
* 系统的sync进程
这些文件系统的特性可以帮助保护数据的一致性,提高容错能力,事实上在许多情况下提高系统的性能。然而这些特性却经常对于数据库的应用的性能产生负面的影响。本文将解释文件系统中这些特性的作用,并介绍在JFS2上的新功能如何消除它们对性能的影响。

2.1 文件缓存

从最基本的层面来说,文件就是在介质上所存储一些二进制位的集合,当一个进程需要从某个文件访问数据的时候,操作系统将这些数据读入内存,然后此进程可以对数据进行操作,最后将处理完的数据写入磁盘。操作系统能够从磁盘上直接读出或写入数据,但是由于磁盘较慢的访问速度,这些操作的响应速度和吞吐率都较差。因此操作系统试图通过文件缓存的技术,即在内存中缓存数据的方法,来减少对磁盘的访问频率。当进程需要从文件中读取数据的时候,操作系统首先试图从文件缓存中读取所需要的数据,如果这些数据不在文件缓存中,那么从磁盘上文件系统的文件中读取,同时将这些数据缓存在文件缓存中。如图1和图2所示:
image
图1 读操作-数据在文件缓存中(命中)
image
图2 读操作-数据不在文件缓存中(没有命中)
与读数据相似,当写数据时数据写入文件缓存,因此将来需要再读取这些数据时,不需要访问磁盘,同时也降低了写磁盘的频率。当缓存的命中率高时,使用文件缓存将是非常有效的。并且可以采用预先读取和延迟写的技术来减少磁盘访问的频率。文件缓存所带来的另一个好处是,以异步的方式进行写操作,这使得应用可以继续运行,而不用等待数据写入磁盘操作的完成,如图3所示。

虽然文件缓存提高了I/O的性能,但是它消耗了大量的系统内存。AIX JFS2文件系统允许系统管理员控制可以作为文件缓存的最大内存数。这种控制通过maxclient%参数控制。系统管理员可以使用vmo命令来调整maxclient%参数。maxclient%的却省值是80,其含义是80% 的物理内存能够作为文件缓存。maxclient%参数的取值可在1至100之间变动。如可以采用以下命令设置最多50%的系统物理内存能够作为文件缓存:vmo –o maxclient%=50。
image
图3 写操作
于此相对应,裸设备不使用系统内存来缓存应用的数据,所以没有以上图示的操作。

2.1.1 直接存取(Direct I/O)

一些应用程序并不能从文件缓存中得到好处,如有些进行大量科学运算的程序,从不访问以前访问过的数据,而且由于他们对数据进行顺序访问,这使得文件缓存的命中率非常低。数据库的应用通常在应用层上有自己的数据缓存技术,所以不需要操作系统进行文件缓存。在这种情况下,使用文件缓存会产生很多额外开销,因为数据首先从磁盘被读入系统的文件缓存,然后从文件缓存拷贝到应用的缓存中,这被称为“重复拷贝”(double-copying),重复拷贝增加了额外的CPU开销,并且相同的数据同时在文件缓存和应用的缓存中,增加了内存的消耗。

JFS2的直接存取(Direct I/O)技术可以使应用程序的数据被系统的文件缓存忽略。当使用Direct I/O时,数据直接从磁盘读取到应用程序的缓存中,而不是用系统的文件缓存。图4和图5说明了在Direct I/O下的读、写操作。
imageimage
图4 Direct I/O的读操作

图5 Direct I/O的写操作
2.1.1.1 Direct I/O的设置方法

Direct I/O可以通过两种方式实现,一是通过在mount文件系统时加 –o dio的参数,即 mount –o dio /fs。二是在调用open()函数打开一个文件时加O_DIRECT参数。当一个文件系统在mount时使用了–o dio的参数,此文件系统的所有文件缺省都会使用Direct I/O,你也可以通过namefs使得Direct I/O只对文件系统中某个子目录中的文件起作用。例如:文件系统somefs中有一些文件希望使用Direct I/O功能,但是其它文件并不希望使用,你可以创建一个子目录subsomefs,将所有希望使用Direct I/O功能的文件放入这个子目录,在mount somefs时不使用-o dio参数,然后用mount –v namefs –o dio /somefs/subsomefs /somefs命令mount subsomefs。

Direct I/O对应用程序I/O的边界(alignment)和块大小(length)有限制,表1列出了JFS2对此的要求,如果应用的I/O不满足此要求,所有的I/O操作会按传统的方式(文件缓存)的方式进行,但当数据被传输到应用的缓存后,系统缓存中的拷贝会被抛弃。当使用Direct I/O时,文件系统的预读功能将不会起作用。

文件系统的类型
I/O的边界(alignmnet) I/O块大小(agblksize)
JFS2(AIX 5.2 ML01前)
4K bytes 4K bytes
JFS2(AIX 5.2 ML01后)
agblksize
( 创建文件系统时的参数)
agblksize
(创建文件系统时的参数)表
表1 JFS对Direct I/O的限制
为了避免一致性的问题,当有多个进程同时打开一个文件,而其中有一个或多个进程没有使用O_DIRECT参数,而其它进程使用了此参数时,文件会按传统的方式(文件缓存)的方式打开,当没有使用O_DIRECT参数的进程关闭后,文件会转变成Direct I/O 的方式。从文件缓存的方式转变成Direct I/O的方式有时会产生很大的开销,因为所有在内存中被改变的数据将会被立即写入磁盘。

2.1.1.2 Direct I/O对性能的影响

Direct I/O对性能的好处,一是降低了CPU的负载,二是避免数据被拷贝两次(第一次从磁盘到文件缓存,第二次从文件缓存到应用缓存)。但是其它的一些因素会对Direct I/O的性能产生影响。

每一次Direct I/O的读请求会产生对磁盘的一次同步的读操作。而传统的方式首先从系统的文件缓存中读取数据。如果数据可能存在于系统的文件缓存中,那么采用Direct I/O的方式性能较差。

Direct I/O也不使用JFS2的预读功能。文件系统的预读功能能够提高顺序读取文件时的系统性能。使用预读功能时,当发现应用程序顺序的访问一个文件时,操作系统试图预测此应用将要读取几个文件页,而预先将其读出,这将减少系统I/O的次数。预读功能由两个参数控制:
* j2-minPageReadAhead
当操作系统发现应用顺序读取文件时,所预读的文件页数,却省值为 2
* j2-maxPageReadAhead
操作系统最多预读的文件页数,却省值为 8
这些参数可通过ioo命令调整。

表2 对Direct I/O和传统缓存的方式在三种不同情况下的性能做了比较,这些测试中文件页的大小为4K bytes,j2-minPageReadAhead=2,而 j2-maxPageReadAhead=8

Read Increment Total File Size Cached I/O Direct I/O
Elapsed Time(sec) Total KB Read Elapsed Time Total KB Read
1 byte 1 MB 1.59 1,036 185.27 4,194,320
4 KB 1 GB 21.18 1,045,982 104.31 1,045,986
10 MB 1 GB 20.59 1,048,592 6.81 1,048,596
表2 Direct I/O vs. cached I/O
表2 中的第一行的情况是应用一个字节一个字节的顺序读取1MB的文件。当使用Direct I/O时,由于没有满足4K bytes边界的限制,因此系统采用传统的文件缓存的方式读取4K的文件页,其中的一个字节被从系统的文件缓存拷贝到应用的缓存,然后此4K的文件页被从系统的文件缓存中删除,这就导致读取这4K中每一个字节时,此4K的页被反复的读取,而且也没有避免重复拷贝。当使用传统的缓存I/O时,当读取4K文件页的第一个字节时,4K的文件页被读入系统的文件缓存,随后的读取将在文件缓存中进行,而不需要访问磁盘,预读的功能进一步减小了延迟。 表2 中的第二行的情况是应用4K字节4K字节的顺序读取1GB的文件。虽然在这种情况下满足Direct I/O对于4K bytes边界的限制,但由于Direct I/O没有预读的功能,所以虽然两种情况下所读取的数据量基本相同,传统的缓存I/O的性能仍然好于Direct I/O。

表2 中的第三行的情况是应用10M字节的顺序读取1GB的文件。Direct I/O的性能远远好于传统的缓存I/O。这主要有两个原因:一是Direct I/O不存在重复拷贝,二是传统的缓存I/O没有享受到预读的好处。

这个例子说明,应用程序并不一定能从Direct I/O中带来性能的改善,然而如果一个应用可以从使用裸设备中得到性能的改善,那么它也能从Direct I/O中得到好处。

2.2 Inode锁

虽然应用程序把文件看作连续的数据流,但这并不是文件实际在硬盘上的存储方式,实际上文件是以连续或不连续的数据块的方式存储的,每一个文件都有一个数据结构与其对应被称为inode。

Inode中包含了访问此文件必须的信息,如文件的宿主,访问权限,文件的大小,上一次文件被访问和改变的时间以及文件数据块在磁盘上的分布。需要注意的是文件内容的改变与文件所对应inode的改变是不同的,文件的内容只在对文件进行了写操作以后改变,而inode的改变可能是对文件进行了写操作也可能是文件宿主、访问权限以及其它属性的改变。在实际环境中可能有多个进程同时需要改变文件的inode,这样会造成inode的不一致,为了避免这种情况的发生,inode被inode 锁的锁机制保护。

当文件被读取时,inode不会改变,而写文件时inode会被改变。JFS2 采用读共享,写独占(read-shared, write-exclusive)的inode 锁的锁机制,允许多个进程同时读一个文件,但当一个进程写文件时,其它进程不允许读写此文件。

2.2.1 并行I/O (concurrent I/O)

inode锁使得对于文件的多个写操作串行处理,这就避免了多个写操作并行时造成的数据的不一致性。而大多数数据库的应用有自己的数据串行处理机制,从而不会造成数据的不一致性。因此它们并不需要操作系统的这种inode 锁的锁机制,实际上在这种情况下inode 锁会对性能产生负面的影响。AIX 5L v5.2 ML01提供了并行I/O (concurrent I/O)的功能,在并行I/O的方式下多个进程可同时对一个文件进行读写操作。并行I/O是专门对数据库的应用进行设计的,大多数数据库的应用程序不需要修改就可以运行在并行I/O的模式下。而对于那些没有自己的数据串行处理机制的应用,如果运行在并行I/O的模式下,可能造成数据的损坏。

2.2.1.1 并行I/O的设置方法

并行I/O可以通过两种方式实现,一是通过在mount文件系统时加 –o cio的参数,即mount –o cio /fs。二是在调用open()函数打开一个文件时加O_CIO参数。当一个文件系统在mount时使用了–o cio的参数,此文件系统的所有文件缺省都会使用并行I/O,你也可以通过namefs使得并行I/O只对文件系统中某个子目录中的文件起作用。例如:文件系统somefs中有一些文件希望使用并行I/O功能,但是其它文件并不希望使用,你可以创建一个子目录subsomefs,将所有希望使用并行I/O功能的文件放入这个子目录,在mount somefs时不使用-o cio参数,然后用mount –v namefs –o cio /somefs/subsomefs /somefs 命令mount subsomefs。

并行I/O缺省会包含Direct I/O的功能,因此O_CIO参数会覆盖O_DIRECT。与Direct I/O相似,当有多个进程同时打开一个文件,而其中有一个或多个进程没有使用O_CIO参数,而其它进程使用了此参数时,文件的访问将不会按并行I/O的方式进行,当没有使用O_CIO参数的进程关闭后,文件会转变成并行I/O的方式。

在并行I/O的方式下,inode锁工作在读共享,写共享的方式下,然而当inode改变并不是由于对文件内容进行写操作,而是由于inode的其它属性改变时,此时需要inode锁工作在写独占的模式下。例如文件增大或减小时,增大一个文件需要将磁盘上的空闲数据块分配给这个文件,此时需要改变相应inode的内容,在这种情况下读共享的inode锁升级为写独占的inode锁,当操作完成后inode锁恢复成读共享的方式。这是一个非常有用的功能,这就意味着在并行I/O的方式下,允许文件动态的增大或减小而不需要关闭这个文件。

2.2.1.2 并行I/O对性能的影响

既然并行I/O中包含了Direct I/O,所有Direct I/O对性能的影响也适用于并行I/O。如果应用程序会从预读功能中得到好处,或在系统的文件缓存中有较高的命中率,那么在并行I/O的方式下会对性能产生负面的影响。并行I/O也不会对绝大多数I/O操作为读的应用产生性能的提高,因为在这种情况下读共享,写独占(read-shared, write-exclusive)的inode 锁的锁机制提供了与并行I/O相似的方式。

3.性能测试环境

为了评价并行I/O对性能的影响,我们测试了典型的在线交易(OLTP)的应用在不同存储配置下的性能,我们选用的数据库是Oracle9i。此应用工作在client/server的体系结构下,其负载中有许多更新的操作。测试结果通过在客户端每秒钟完成的交易量来衡量(tps)同时衡量响应时间,我们选取了三种不同的数据库的存储配置:
* 裸设备
* JFS2文件系统+Direct I/O
* JFS2文件系统+并行I/O
系统的配置见表3:
image
表3 系统配置
在作数据库性能测试的时候通常使用裸设备进行数据的存储,这是因为裸设备没有文件系统的开销,通常可以得到最好的性能,在本测试中基于裸设备的测试结果作为基于文件系统的测试所追求的目标。

4.测试结果

表4和图6给出了在每一种存储配置下的平均吞吐率(每秒钟完成的交易量tps)和平均响应时间,虽然平均吞吐率Direct I/O比裸设备低了70%,但是同步I/O只比裸设备低了8%。由此可见Direct I/O性能差的关键是由于严重的inode锁。
image
表4 平均吞吐率和平均响应时间
image
图6 吞吐率

并行I/O与裸设备性能的不同主要由两个因素决定,一是对文件系统的访问比对裸设备的访问多了一层,对于文件系统,应用需要先访问文件系统,文件系统再访问LV,而对于裸设备,应用直接访问LV。二是由于异步I/O(AIO),AIO的进程是一个核心进程,当AIO的进程访问文件系统的文件时需要进行context switch。而对于裸设备的异步I/O时由系统核心完成的,不需要进行context switch。

对于系统锁的研究可以发现三种存储模式的特点。我们使用了AIX的trace工具来获取系统锁的信息。在这里我们首先解释一下AIX 5.2的锁机制,当系统的一个进程或线程试图得到一个系统锁而没有成功,它会不断尝试去取得这个系统锁,尝试的次数由maxspin参数决定,其缺省值为16384, maxspin参数可由AIX schedo命令修改。当此进程或线程尝试了maxspin次后仍然没有取得这个系统锁,此进程或线程会由运行状态转变为等待状态。当取得此系统锁的进程或线程释放了这个系统锁后,它会激活一个或多个等待此系统锁的进程或线程。

图7说明了在测试当中每种情况下最多的系统锁,通过trace的工具我们观察到了三种主要的系统锁:
* AIOQ锁:防止多个进程同时从AIO队列中插入或删除AIO的请求的锁。
* Inode锁:防止多个进程同时更新Inode的锁。
* SSA 锁:防止多个进程同时访问SSA设备的锁
从图6中可以看出在Direct I/O的方式下,系统的瓶颈是在Inode锁上,这会造成大量的context switch, 大量的进程处于等待状态,并且CPU也处于等待状态。降低了整个系统的吞吐率。而在裸设备和同步I/Od的方式下,没有大量的inode写保护锁。
image
图7 不同模式下主要的系统锁类型

5.结论

本文中的性能测试表明,对于数据库的应用,采用JFS2的并行I/O的数据存储方式可以获得与采用裸设备的数据存储方式相似的性能,但却可使得数据的管理更加方便灵活。这说明并行I/O技术适用于数据库的应用。

阅读(1572) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~