严重的写入性能问题

[对不起,我尽量保持简短,但这是不可能的]

我在富士通西门子Primergy RX200 S3上运行Linux 2.6.22.19和linux-vserver 2.3.0.34进行开发。 英特尔(R)Xeon(R)5140 @ 2.33Ghz(带有4GB RAM)(其中大部分仍然是500MB)。 服务器有两个热插拔250GB镜像RAIDconfiguration:

dev:~# mpt-status --newstyle ioc:0 vol_id:0 type:IM raidlevel:RAID-1 num_disks:2 size(GB):231 state: OPTIMAL flags: ENABLED ioc:0 phys_id:0 scsi_id:1 vendor:ATA product_id:WDC WD2500JS-55N revision:2E01 size(GB):232 state: ONLINE flags: NONE sync_state: 100 ASC/ASCQ:0xff/0xff SMART ASC/ASCQ:0xff/0xff ioc:0 phys_id:1 scsi_id:8 vendor:ATA product_id:WDC WD2500JS-55N revision:2E01 size(GB):232 state: ONLINE flags: NONE sync_state: 100 ASC/ASCQ:0xff/0xff SMART ASC/ASCQ:0xff/0xff scsi_id:0 100% scsi_id:1 100% 

我正在运行LVM和ext3。

我们在2007年7/7月左右使用这台机器,并且在同一天固定的破损内存旁边没有任何问题。 而且,基本上,一切都比我们之前拥有的机器要好。

然而,性能问题在2008年8月左右首先被注意到,直到最近我至less还有一些信心是问题出现。 现在平均有7个虚拟服务器正在运行(三台MySQL机器,两台tomcat,三台Apaches,Hudson,CruiseControl,MediaWiki,Samba等)。 但是不要错过这样的印象,就开发人员和其他访问服务器的人而言,我们是一个小公司,所以没有太多的事情要做(浏览MediaWiki,Hudson自动化在晚上运行,大多数Apache / PHP应用程序有很多静态内容)。

一旦我安装了慕尼黑,我开始看到有趣的事情,特别是在夜间。 由于在每个虚拟服务器中都有运行(在同一时间,无处不在)的负载,如15,17或20这样的虚幻数字。

但最终问题不仅仅是在夜间(我开始禁用找工作,还没有使用),而且在白天,特别是当我们最近开始一个项目时,我们不得不使用数据库一个500MB的MySQL转储文件。

我第一次在工作时间导入转储文件( mysql < dump.sql ;在我们的一个运行MySQL实例的mysql < dump.sql ),定时输出是:

 real 71m28.630s user 0m15.477s sys 0m10.185s 

由于我没有注意,正在开会,只是我的同事问我服务器上有什么问题,因为他的速度非常慢。

我在晚上重新testing了这个testing,在主机上安装了一个vanilla Debian MySQL(不是在一个guest虚拟机中,closures所有这些),并且input以下数字:

 real 48m33.067s user 0m15.397s sys 0m13.517s 

而且我还是很喜欢, 好吧,这是500MB的转储文件; 倾销到InnoDB空间需要1GB左右,这是相当多的数据 。 我做了一些testing,比如在这样的testing中用vim写一行到一个文件,并用strace捕获它:

  0.000048 write(1, "\33[?25l\"foo\" \33[78;7H\33[K", 22) = 22 0.000033 stat64("foo", 0xbfda1f04) = -1 ENOENT (No such file or directory) 0.000033 open("foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4 0.000035 write(4, "thios isthis ia a testa\n", 24) = 24 0.000144 fsync(4) = 0 7737.631089 stat64("foo", {st_mode=S_IFREG|0664, st_size=24, ...}) = 0 0.000084 close(4) = 0 0.000117 write(1, "\33[78;7H[New] 1L, 24C written", 28) = 28 0.000051 lseek(3, 0, SEEK_SET) = 0 0.000022 write(3, "b0VIM 7.0\0\0\0\0\20\0\0\0\0\0\0\0\0\0\0!\21\0\0mark"..., 4096) = 4096 0.000052 select(1, [0], NULL, [0], {0, 0}) = 1 (in [0], left {0, 0}) 

这对我来说是一个令人难以置信的事实数字。 看来,stat64系统调用被迫等待转储操作完成。 更不用说在这样的转储期间在MediaWiki中提供页面也需要几分钟的时间。

无论如何,我安排了一个testing时间表与我们的托pipe公司在晚上testing我们的生产服务器,我得到了一个完全不同的画面:

 real 7m4.063s user 0m2.690s sys 0m30.500s 

我被吹走了。 我还获得了Amazon EC2的testing许可,而且我还有更less的数字(在MySQL数据写入EBS卷的情况下m1.large实例大约需要5分钟才能保持不变)。

另外,导入数据时,其他操作变得非常缓慢,以至于无法使用,并且负载迅速上升到5或7(尽pipe看起来不是很好,但看起来进程开始相互阻塞现在的原因)。

然后我开始做bonnie ++testing ,看起来像这样(我实际上从去年开始testing,几乎忘记了)。 所以这里是2008年10月

 Version 1.03 ------Sequential Output------ --Sequential Input- --Random- -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks-- Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP vserver-host 8G 12332 21 12600 3 10290 2 48519 74 52431 6 235.8 0 ------Sequential Create------ --------Random Create-------- -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete-- files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP 16 +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++ vserver-host,8G,12332,21,12600,3,10290,2,48519,74,52431,6,235.8,0,16,+++++,+++,+++++,+++,+++++,+++,+++++,+++,+++++,+++,+++++,+++ 

以下是2009年4月份的最新版本:

 Version 1.03 ------Sequential Output------ --Sequential Input- --Random- -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks-- Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP vserver-host 8G 9705 16 7268 1 4823 1 29620 45 41336 5 73.1 0 ------Sequential Create------ --------Random Create-------- -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete-- files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP 16 11678 15 +++++ +++ +++++ +++ +++++ +++ +++++ +++ 27739 31 vserver-host,8G,9705,16,7268,1,4823,1,29620,45,41336,5,73.1,0,16,11678,15,+++++,+++,+++++,+++,+++++,+++,+++++,+++,27739,31 

我不知道在哪里调整什么来摆脱问题,因为我不完全确定真正的问题在哪里/什么。 我想我开始没有看到树木的木材。

更新1:

感谢迄今为止的反馈,我已经select了第一个东西,我可以轻松testing,而无需安排维护时间。

首先我已经testing了针对/dev/null的MySQL转储:

 dev01:~$ time mysqldump -u root -h db01 database-p >/dev/null Enter password: real 0m18.871s user 0m12.713s sys 0m0.512s 

系统负载几乎不明显:

  10:27:18 up 77 days, 9:10, 7 users, load average: 0.16, 0.75, 0.67 [...] 10:27:33 up 77 days, 9:10, 7 users, load average: 0.52, 0.79, 0.69 

另外在这次testing中, sar输出没有透露任何特别的东西:

 12:11:45 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 12:11:46 PM dev8-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:11:46 PM dev254-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:11:46 PM dev254-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:11:46 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 12:11:47 PM dev8-0 5.00 0.00 200.00 40.00 0.18 36.00 20.00 10.00 12:11:47 PM dev254-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:11:47 PM dev254-1 25.00 0.00 200.00 8.00 0.74 29.60 4.00 10.00 

然后,我在转储到文件时运行testing:

 dev01:~$ time mysqldump -u root -h db01 database -p >foo.sql real 1m7.527s user 0m13.497s sys 0m2.724s 

所花费的时间对我而言并不是那么不寻常,转储以570MB文件结束。

然而,负载是相当有趣的…

  10:30:49 up 77 days, 9:14, 7 users, load average: 0.76, 0.89, 0.75 10:30:57 up 77 days, 9:14, 7 users, load average: 1.34, 1.01, 0.79 10:31:05 up 77 days, 9:14, 7 users, load average: 2.13, 1.19, 0.85 10:31:13 up 77 days, 9:14, 7 users, load average: 2.68, 1.32, 0.89 10:31:21 up 77 days, 9:14, 7 users, load average: 3.79, 1.60, 0.99 10:31:29 up 77 days, 9:14, 7 users, load average: 4.05, 1.69, 1.02 10:31:37 up 77 days, 9:14, 7 users, load average: 4.82, 1.93, 1.10 10:31:45 up 77 days, 9:15, 7 users, load average: 4.54, 1.97, 1.12 10:31:53 up 77 days, 9:15, 7 users, load average: 4.89, 2.08, 1.16 10:31:57 up 77 days, 9:15, 7 users, load average: 5.30, 2.22, 1.21 10:32:01 up 77 days, 9:15, 7 users, load average: 5.12, 2.23, 1.22 10:32:05 up 77 days, 9:15, 7 users, load average: 5.03, 2.26, 1.24 10:32:13 up 77 days, 9:15, 7 users, load average: 4.62, 2.22, 1.23 

…就像是…

 12:16:47 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 12:16:48 PM dev8-0 116.00 0.00 21712.00 187.17 134.04 559.31 8.62 100.00 12:16:48 PM dev254-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:16:48 PM dev254-1 3369.00 0.00 26952.00 8.00 3271.74 481.27 0.30 100.00 12:16:48 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 12:16:49 PM dev8-0 130.00 0.00 17544.00 134.95 143.78 752.89 7.69 100.00 12:16:49 PM dev254-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:16:49 PM dev254-1 1462.00 0.00 11696.00 8.00 2749.12 1407.78 0.68 100.00 12:16:49 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 12:16:50 PM dev8-0 128.00 0.00 18400.00 143.75 143.68 1593.91 7.84 100.40 12:16:50 PM dev254-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 12:16:50 PM dev254-1 810.00 0.00 6480.00 8.00 1598.99 4911.94 1.24 100.40 

在这个testing过程中,我很快启动了vim来做一个简单的写testing。 vim本身的加载速度也很慢,但我无法从strace正确地提取这些信息。 只有待处理的stat64调用再次清晰可见:

 0.000050 stat64("bla", 0xbf98caf4) = -1 ENOENT (No such file or directory) 0.000038 open("bla", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4 0.000053 write(4, "fooo\n", 5) = 5 0.000051 fsync(4) = 0 5.385200 stat64("bla", {st_mode=S_IFREG|0664, st_size=5, ...}) = 0 0.000073 close(4) = 0 

我会尽快追加进一步的文件系统testing。

更新2 /解决scheme:

根据Mihai有关MTP设备和RAIDconfiguration的反馈,我更深入地探讨了这个话题。 通过lspci我找回了RAID控制器信息:

 dev:~$ sudo lspci|grep -i lsi 05:05.0 SCSI storage controller: LSI Logic / Symbios Logic SAS1068 PCI-X Fusion-MPT SAS (rev 01) 

进入蓝色后,在http://www.ask.com/web?q=linux+problem+performance+SAS1068上发现了一个问题,并发现LSI Logic SAS1068的写入性能问题 。 错误描述进一步链接到博客谈论也使用SAS1068的DELL PE860性能问题 。

这篇文章提到了使用可从lsi.com获得的LSIUtil 。 文章还介绍了如何打开写入cachinglsiutil菜单。

不出意料的是,这对性能有重大影响。 激活之前

 dev:~# time (dd if=/dev/zero of=bigfile count=1024 bs=1M; sync) 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 180.902 seconds, 5.9 MB/s real 3m8.472s user 0m0.004s sys 0m3.340s 

启用写入caching后:

 dev:~# time (dd if=/dev/zero of=bigfile count=1024 bs=1M; sync) 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 43.7899 seconds, 24.5 MB/s real 0m46.413s user 0m0.000s sys 0m3.124s 

这就像白天黑夜,黑色和白色。 有时感觉愚蠢是可以的。 我可能应该知道,默认情况下,RAID控制器随附写caching。

更新3:

我偶然发现了一个名为diskstat的munin插件,它为所有块设备提供详细的IO,读/写/等等graphics。 作者还有一篇非常好的详细的博客文章,标题为“ 使用Munin绘制Linux磁盘I / O统计数据” 。

从其他海报中得到一些关于排除软件和调整RAID性能的好build议。 值得一提的是,如果你的工作量很大,那么如果你正在考虑更换你的套件,那么使用带有电池供电的写入caching的硬件很可能是正确的select。

这对我来说是一个令人难以置信的事实数字。 看来,stat64系统调用被迫等待转储操作完成。


这是你正在寻找的线索。 我敢打赌,这里的罪魁祸首是ext3。 默认情况下,在ext3下,由任何用户帐户下的任何应用程序发出的任何fsync都会强制整个日志到磁盘。 如果你正在运行经常需要发出fsync()调用的数据库,这是特别恼人的。 当运行在不支持写入障碍的RAID设备上时,这更令人讨厌(不知道MPT设备是否支持它们,对不起。)

如果您确信UPS和服务器的稳定性,请尝试使用data=writeback mount选项来挂载该文件系统,而不是默认data=ordered 。 面对服务器崩溃,您将牺牲可靠性,但是如果您的性能受到影响,那么这不是一个大的损失。

不过,长期的解决scheme可能会转向更好的文件系统。 目前我会推荐XFS。 我已经使用了多年,没有大问题。 唯一的缺点是不能缩小ext2 / 3的缩小方式 – 可以扩展。

  • 尝试执行mysql dump do /dev/null 。 这将告诉你是否写作或阅读部分是负责任的。

  • 尝试将转储写入单独的逻辑卷/文件系统或RAM磁盘。

  • 检查文件系统上的journal选项。

  • 检查文件系统上的noatime / atime状态

  • 文件系统是否填满? 通常情况下,当数据量达到某个阈值时,性能会下降。

它闻起来就像是在填充IO容量。 首先检查一下,以确保你的磁盘没有死亡(扇区重映射可以对IO做坏事),然后运行sar -d 1 0并查看物理磁盘的%util编号。 如果达到100%左右,那么我就把更多的主轴放在一个RAID-10上。 你不会得到两倍的performance,但它会给你更多的机会。 现在250GB的磁盘并不是非常昂贵的。

哦,再来拉我的作品,把一面文字与你的文本墙拼在一起,我写了一个指南来追踪性能问题: http : //www.anchor.com.au/hosting/development/ HuntingThePerformanceWumpus涵盖了所有你需要了解的跟踪性能问题。