[抱歉,我尽量简短但确实做不到]
我正在运行 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=writeback
mount 选项(而不是默认选项)安装该文件系统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涵盖了追踪性能问题所需了解的所有内容。