严重的写入性能问题

严重的写入性能问题

[抱歉,我尽量简短但确实做不到]

我正在运行 Linux 2.6.22.19linux-vserver 2.3.0.34富士通西门子 Primergy RX200 S3用于开发目的。Intel(R) Xeon(R) 5140 @ 2.33Ghz,配备 4GB RAM(其中大部分 500MB 仍是空闲的)。该服务器有两个热插拔 250GB,用于镜像 RAID 配置:

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%

我在跑逻辑卷管理器和 ext3。

我们从 2007 年 7 月/8 月左右开始使用这台机器,除了内存损坏(当天就修好了)外,没有出现任何问题。而且基本上一切都比我们之前的机器好。

然而,性能问题最早是在 2008 年 8 月左右发现的,直到最近我才至少确定了问题出在哪里。目前平均有 7 个 vserver 在运行(三台 MySQL 机器、两台 tomcat、三台 Apache、Hudson、CruiseControl、MediaWiki、Samba 等)。但不要误以为我们是一家小公司,因为开发人员和其他访问服务器的人都很少,所以没有那么多事情要做(浏览 MediaWiki,Hudson 自动化在晚上运行,大多数 Apache/PHP 应用程序都有很多静态内容)。

安装 munin 后,我开始看到一些有趣的东西,尤其是在晚上。由于每个虚拟服务器都在find运行(同时,在所有地方),负载猛增到不真实的数字,如 15、17 或 20。

但最终问题不仅仅存在于夜间(我开始禁用查找作业,因为它们反正也没用),也存在于白天,特别是当我们最近开始一个项目时,我们必须使用一个带有 500MB MySQL 转储文件的数据库。

我第一次在工作时间导入转储文件时(mysql < dump.sql;在运行 MySQL 实例的虚拟服务器之一内),定时输出为:

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

由于我没注意并且正在开会,所以只是我的同事问我服务器出了什么问题,因为服务器运行速度太慢了。

我在晚上重新进行了测试,在主机上安装了原始的 Debian MySQL(不是在客户机内;关闭所有客户机),并达到了以下数字:

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

我还是觉得是的,这是 500MB 的转储文件;转储到 InnoDB 空间占用大约 1GB,这是相当多的数据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 中提供页面也需要几分钟。

无论如何,我与托管公司安排了一个测试时间范围,以便在晚上对我们的生产服务器进行测试,结果得到了完全不同的画面:

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

我被震惊了。我还获得了 Amazon EC2 的测试批准,我得到了更低的数字(在 m1.large 实例上大约需要 5 分钟,其中 MySQL 数据被写入 EBS 卷以保持永久状态)。

此外,在导入数据时,其他所有操作都会变得非常慢,以致于无法使用,并且负载迅速上升到 5 或 7(尽管似乎并没有发生太多事情;看起来进程现在开始相互阻塞)。

然后我开始做bonnie++ 测试,看起来像这样(实际上我去年就进行了一次测试,我差点忘了)。所以这里是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:

感谢您迄今为止的反馈,我已经首先选择了可以轻松测试而无需安排维护时间的东西。

首先我测试了 MySQL 转储/dev/null

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

这次测试的输出也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

然后我在转储到文件时运行了测试:

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

... 就像sar...

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

在这次测试中,我很快就开始vim做一个简单的写入测试。加载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

我将尽快附加进一步的文件系统测试。

更新 2/解决方案:

根据 Mihai 关于 MTP 设备和 RAID 配置的反馈,我对该主题进行了更深入的研究。通过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 的写入性能问题。错误描述进一步链接到博客,讨论DELL PE860 也使用 SAS1068 的性能问题

文章提到使用LSIUtil 可从 lsi.com 获取。本文还详细介绍了lsiutil菜单,描述了如何开启写入缓存

毫不奇怪,事实证明这对性能有重大影响。激活:

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

启用写缓存后:

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 控制器默认禁用写入缓存。

更新 3:

偶然中我发现了一个名为磁盘状态它提供了所有块设备的详细 IO、读/写/等待等图表。作者还发表了一篇非常精彩且详细的博客文章,标题为使用 Munin 绘制 Linux 磁盘 I/O 统计图表

答案1

其他发帖者提出了一些关于排除软件和调整 RAID 性能的好建议。值得一提的是,如果您的工作负载是写入密集型的,那么如果您正在考虑更换套件,那么选择具有电池支持的写入缓存的硬件可能是正确的选择。

答案2

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


这就是你要找的线索。我敢打赌,这里的罪魁祸首是 ext3。默认情况下,在 ext3 下,任何用户帐户下的任何应用程序发出的任何 fsync 都会强制将整个日志写入磁盘。如果您运行的数据库经常必须发出 fsync() 调用,这尤其令人讨厌。在运行不支持写入屏障的 RAID 设备时,这甚至更加令人讨厌(不知道 MPT 设备是否支持它们,抱歉。)

如果您对 UPS 和服务器的稳定性相当有信心,请尝试使用data=writebackmount 选项(而不是默认选项)安装该文件系统data=ordered。如果服务器崩溃,您将牺牲可靠性,但如果您的性能受到如此严重的打击,那么损失也不大。

不过,长期解决方案可能是切换到更好的文件系统。目前我推荐 XFS。我已经用了好几年了,没有出现什么大问题。唯一的缺点是它不能像 ext2/3 那样缩小 - 不过它可以扩展。

答案3

  • 尝试执行 mysql dump do /dev/null。这将向您显示写入或读取部分是否负责。

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

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

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

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

答案4

听起来你只是在填满 IO 容量。首先检查以确保你的磁盘之一没有坏掉(扇区重新映射会对 IO 造成不良影响),然后运行sar -d 1 0并查看%util物理磁盘的数字。如果这个数字上升到 100% 左右,那么我就会向它投入更多主轴,将它们放入 RAID-10 中。你不会获得双倍的性能,但它会给你带来更多乐趣。250GB 磁盘现在并不贵得离谱。

哦,为了进一步完善我的工作,并让一大堆文本与你的一大堆文本进行对抗,我写了一篇指南来追踪性能问题:http://www.anchor.com.au/hosting/development/HuntingThePerformanceWumpus涵盖了追踪性能问题所需了解的所有内容。

相关内容