具有 EBS 卷的 Amazon EC2 MySQL 实例上的高 iowait

具有 EBS 卷的 Amazon EC2 MySQL 实例上的高 iowait

我们有一个在 Amazon EC2 c1.medium 实例上运行的 MySQL 服务器,依靠使用 ext3 文件系统的单个 EBS 卷进行存储。

一些运行在 Web 服务器(也位于 Amazon EC2)上的应用程序对该 MySQL 服务器的查询频率约为 500/ps。

正如您在下面看到的,服务器的平均负载和处理器空闲时间似乎很好,但现在有些事情令我不安和担心,那就是它一直经历的高 iowait。

另一个让我非常担心的数字是 iostat 的每秒传输次数 (tps),​​大多数时候都保持在 450 以上。在对这个主题进行一些研究之后,我看到一些人说这对 EBS 卷的要求太高了:https://forums.aws.amazon.com/thread.jspa?threadID=30769

顺便说一句,下面您将看到的命令输出不是在高峰时间捕获的。大多数时候,服务器的行为/执行方式都是这样的。

好了,总而言之,我的问题如下:

1-是时候考虑转向 RAID 架构了吗(我认为是 RAID 0)?

2——我是否应该花时间研究诸如 MySQL Cluster 之类的集群解决方案?

3- 您认为这种情况会严重影响我们的应用程序吗?如果我们转向 RAID 0 和/或集群解决方案,它们的性能会好得多吗?(到目前为止,应用程序似乎很满意,但它们会更满意吗?)

如果您需要任何进一步的信息,请告诉我。

~ # uptime 
 12:34:14 up 2 days,  4:06,  1 user,  load average: 2.24, 1.90, **1.84**

########################################################

~ # vmstat 5

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------

 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id **wa** st

 0  1     52  11168  16420 1498728    0    0  4586   231   11   81  6  3 52 39  0

 2  1     52  10460  16320 1499588    0    0 11631   397 3194 4319 10  4 47 39  0

 4  1     52  11448  16064 1499156    0    0 12231   592 2301 3331  9  5 50 36  0

 4  0     52  10328  16068 1500176    0    0  8578   392 2131 2745  8  6 49 37  0

 0  1     52  11164  15732 1499928    0    0  9604   578 2609 3510  7  4 49 40  0

 0  1     52  10824  15768 1499836    0    0  5038   634 1912 2509  8  3 47 42  0

 3  1     52  12040  15888 1498096    0    0  5068   204 1927 2531 10  8 45 37  0

 8  2     52  11252  15784 1499272    0    0  8521   390 2437 3100 14 15 39 31  0

 1  2     52  11436  15724 1499748    0    0  8287   401 2159 3113 11 10 42 36  1

 0  1     52  12016  15704 1498752    0    0 11576   499 3324 3984 16 17 31 36  0

 1  1     52  10536  15664 1500508    0    0  8430   718 2686 3265 15 14 37 34  0

 1  1     52  10300  15676 1500744    0    0 10186   720 2488 3488 16  5 45 34  0

########################################################

~ # iostat -dm 5 /dev/sdf 
Linux 2.6.21.7-2.fc8xen (database-new)  01/20/12

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             464.81         8.84         0.33    1658860      61390

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             402.20         7.39         0.43         36          2

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             431.40         7.74         0.32         38          1

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             461.40         8.26         0.39         41          1

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             475.65         9.20         0.29         46          1

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             534.80         9.82         0.52         49          2

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn

sdf             526.60         9.97         0.52         49          2

########################################################

~ # iostat -mdx 5 /dev/sdf 

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              22.21    46.28 427.47 37.54     8.84     0.33    40.38     1.78    3.82   1.72  79.87

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              22.36    80.04 450.30 60.48     9.29     0.55    39.44     1.45    2.85   1.58  80.48

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              23.40    43.60 370.60 47.00     7.75     0.35    39.76     1.45    3.47   1.97  82.08

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              20.20    33.20 382.60 29.60     8.02     0.25    41.05     1.31    3.17   2.11  87.12

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              28.80    35.20 422.40 33.40     9.04     0.27    41.80     1.45    3.19   1.95  88.96

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              14.20    45.00 291.80 51.40     5.97     0.38    37.86     1.45    4.22   2.50  85.68

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              19.16    56.89 535.33 41.32    11.44     0.38    42.00     1.49    2.59   1.53  88.46

Device:         rrqm/s   wrqm/s   r/s   w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util

sdf              20.40    81.40 233.00 64.40     4.86     0.57    37.39     1.74    5.84   3.18  94.72
####################################################### my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
long_query_time=1
key_buffer = 64M
thread_cache_size = 30
table_cache = 1024
table_definition_cache = 512
query_cache_type = 1
query_cache_size = 64M
tmp_table_size = 64M
max_heap_table_size = 64M
innodb_buffer_pool_size = 512M
old_passwords=1
max_connections=400
wait_timeout=30

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

[ndbd]
connect-string="nodeid=2;host=localhost:1186"

[ndb_mgm]
connect-string="host=localhost:1186"
##################################################### sundry 的调优脚本输出
~ # ./tuning-primer.sh 

    -- MYSQL PERFORMANCE TUNING PRIMER --
         - By: Matthew Montgomery -

MySQL Version 5.1.52 i686

Uptime = 0 days 1 hrs 1 min 1 sec
Avg. qps = 517
Total Questions = 1894942
Threads Connected = 94

Warning: Server has not been running for at least 48hrs.
It may not be safe to use these recommendations

To find out more information on how each of these
runtime variables effects performance visit:
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html
Visit http://www.mysql.com/products/enterprise/advisors.html
for info about MySQL's Enterprise Monitoring and Advisory Service

SLOW QUERIES
The slow query log is NOT enabled.
Current long_query_time = 1.000000 sec.
You have 207 out of 1894981 that take longer than 1.000000 sec. to complete
Your long_query_time seems to be fine

BINARY UPDATE LOG
The binary update log is NOT enabled.
You will not be able to do point in time recovery
See http://dev.mysql.com/doc/refman/5.1/en/point-in-time-recovery.html

WORKER THREADS
Current thread_cache_size = 30
Current threads_cached = 8
Current threads_per_sec = 0
Historic threads_per_sec = 0
Your thread_cache_size is fine

MAX CONNECTIONS
Current max_connections = 400
Current threads_connected = 93
Historic max_used_connections = 195
The number of used connections is 48% of the configured maximum.
Your max_connections variable seems to be fine.

INNODB STATUS
Current InnoDB index space = 1.33 G
Current InnoDB data space = 5.04 G
Current InnoDB buffer pool free = 0 %
Current innodb_buffer_pool_size = 512 M
Depending on how much space your innodb indexes take up it may be safe
to increase this value to up to 2 / 3 of total system memory

MEMORY USAGE
Max Memory Ever Allocated : 1.13 G
Configured Max Per-thread Buffers : 1.04 G
Configured Max Global Buffers : 642 M
Configured Max Memory Limit : 1.67 G
Physical Memory : 1.70 G

Max memory limit exceeds 90% of physical memory

KEY BUFFER
Current MyISAM index space = 379 M
Current key_buffer_size = 64 M
Key cache miss rate is 1 : 162
Key buffer free ratio = 80 %
Your key_buffer_size seems to be fine

QUERY CACHE
Query cache is enabled
Current query_cache_size = 64 M
Current query_cache_used = 43 M
Current query_cache_limit = 1 M
Current Query cache Memory fill ratio = 67.44 %
Current query_cache_min_res_unit = 4 K
MySQL won't cache query results that are larger than query_cache_limit in size

SORT OPERATIONS
Current sort_buffer_size = 2 M
Current read_rnd_buffer_size = 256 K
Sort buffer seems to be fine

JOINS
Current join_buffer_size = 132.00 K
You have had 4013 queries where a join could not use an index properly
You should enable "log-queries-not-using-indexes"
Then look for non indexed joins in the slow query log.
If you are unable to optimize your queries you may want to increase your
join_buffer_size to accommodate larger joins in one pass.

Note! This script will still suggest raising the join_buffer_size when
ANY joins not using indexes are found.

OPEN FILES LIMIT
Current open_files_limit = 2458 files
The open_files_limit should typically be set to at least 2x-3x
that of table_cache if you have heavy MyISAM usage.
Your open_files_limit value seems to be fine

TABLE CACHE
Current table_open_cache = 1024 tables
Current table_definition_cache = 512 tables
You have a total of 45237 tables
You have 1024 open tables.
Current table_cache hit rate is 0%
, while 100% of your table cache is in use
You should probably increase your table_cache
You should probably increase your table_definition_cache value.

TEMP TABLES
Current max_heap_table_size = 64 M
Current tmp_table_size = 64 M
Of 38723 temp tables, 44% were created on disk
Perhaps you should increase your tmp_table_size and/or max_heap_table_size
to reduce the number of disk-based temporary tables
Note! BLOB and TEXT columns are not allow in memory tables.
If you are using these columns raising these values might not impact your 
ratio of on disk temp tables.

TABLE SCANS
Current read_buffer_size = 128 K
Current table scan ratio = 537 : 1
read_buffer_size seems to be fine

TABLE LOCKING
Current Lock Wait ratio = 1 : 954
You may benefit from selective use of InnoDB.
If you have long running SELECT's against MyISAM tables and perform
frequent updates consider setting 'low_priority_updates=1'
If you have a high concurrency of inserts on Dynamic row-length tables
consider setting 'concurrent_insert=2'.

答案1

如果您发布 my.cnf,并说明您使用的是 InnoDB 还是 MyISAM 表,以及您的工作负载是读取密集型还是写入密集型,这将很有帮助。否则,我们只是在猜测。以下是我的猜测:

首先,我会查看并确保你的查询已正确编入索引。MySQL 数据库的高 I/O 要么是由极高的并发性、服务器调优不佳造成的,要么是由必须进行全表或索引扫描的查询性能不佳造成的。有关如何查找性能不佳的查询的一些提示,可在我的在 Ideeli 的技术博客上发表文章

检查您的 my.cnf。如果您使用的是 InnoDB,请确保 innodb_buffer_pool_size 和 innodb_log_file_size 足够大。由于 EBS 具有如此多的可变延迟,因此最大化 innodb_log_file_size 可以带来显着的性能优势。如果您使用的是 MyISAM(您不应该使用),请确保您的 key_buffer 大小足够大。

如果您确信您的查询已得到很好的优化,并且您的服务器已得到很好的调整,我们可以继续讨论下一个项目。ext3 对于数据库来说并不理想。其中一个主要原因是 ext3 一次只允许一个线程更新一个 inode(尝试查找相关文档)。如果您没有使用 innodb-file-per-table 运行,则意味着 ibdata 文件上存在大量文件系统争用。xfs 没有此限制,并且已被证明在数据库工作负载方面表现更好(需要源代码)。

如果您无法更改为 xfs,请确保您正在使用 innodb-file-per-table,并且至少确保您在挂载上有 noatime 和 nodiratime。

接下来,讨论您的实例大小。除非数据集很小,否则 c1.medium 不是大多数数据库的理想实例大小。MySQL 通常更看重内存而不是计算能力。c1.medium 只有 1.7GB 的 RAM!您的数据集有多大?一般来说,m1.large(具有 7.5GB RAM)的性能优于 c1.medium,除非在极少数情况下。它的价格也是 c1.large 的两倍,为 0.34 美元/小时。

现在讨论 EBS 卷的 RAID。是的,RAID 将大大提高您的 IOPS。(增加实例大小也是如此)。 不要使用 RAID0...至少如果你关心你的数据。我已经在很多地方解释过这一点,包括我的博客,作为演讲者2011 年 Percona Live 纽约站, 和这里是 serverfault简而言之,EBS 卷会以非典型方式发生故障,并且能够从集合中删除卷已被证明在很多情况下都是有价值的,最明显的是在 2011 年的 EBS 大中断期间,当时一些站点离线了好几天...尽管有数十个实例受到 EBS 问题的影响,但我们在凌晨 4 点离线了 45 分钟。

以下是一些基准对于使用 MySQL 的 RAIDed EBS 卷。

最后,Percona 服务器拥有大量的可扩展性优化。 这是一份白皮书关于我公司从 MySQL 切换到 Percona Server 的经历。我们每天都会遇到数据库停滞和中断的情况。由于进行了多项可扩展性改进,只需从 MySQL 切换到 Percona Server,就可以在一夜之间解决该问题。

因此,总而言之...

  • 调整查询
  • 调整你的服务器
  • 让自己拥有更好的“硬件”
  • 使用 xfs,而不是 ext3
  • RAID10,而不是 RAID0
  • 从 MySQL 切换到 Percona Server

至于 MySQL Cluster,它与 MySQL 完全不同,通常不适合大多数 OLTP 应用程序。 加莱拉/Percona XtraDB集群也是新的和有趣的集群产品。你有很多但是,在开始之前,您需要考虑多种选择。我们在 EC2 中使用 RAID10 的单个 m2.4xlarge 提供 24k qps 的峰值服务。

祝你好运!

答案2

这是很多公司都遇到的问题,各种在线论坛上对该问题的解决方案进行了相当充分的讨论。

通常,为了增加潜在的 iops,会将两个或多个 EBS 卷合并成一个 RAID0 阵列。但这并非没有风险。如您所知,使用 RAID0,只要其中一个成员 EBS 卷出现问题,您的数据就会被毁掉。因此,您可以考虑使用更具弹性的 RAID 级别,比如 RAID 10。

答案3

由于 500gps 对 SQL 服务器来说是一个相当温和的负载,我建议查看磁盘上创建的临时表的百分比,并开始优化查询和 MySQL 服务器设置。

1、不要采用Raid0的方法,它最终会失败,你会后悔的。

2、不,当每秒查询数如此低时,您不需要 MySQL Cluster。

3、是的,它确实会影响应用程序的性能,您可以启用慢速日志来测量它的性能,然后亲自查看一下。

mysql 目前使用了多少内存,还有剩余空间吗?
如果没有,您应该考虑切换到更大的实例,并开始使用 sundry 的 mysql 调整脚本优化设置:
http://www.day32.com/MySQL/tuning-primer.sh

答案4

3- 您认为这种情况会严重影响我们的应用程序吗?如果我们转向 RAID 0 和/或集群解决方案,它们的性能会好得多吗?

由于您正在运行 SQL 服务器,因此查看 SQL 服务器指标比了解查询是否快速响应更有意义。从您的个位数平均请求等待时间 (await) 来看,我认为 I/O 还不是问题。

此外,由于您主要看到的是读取负载,因此您可以通过使用更大的缓存/增加 RAM 量并调整 MySQL 实例的缓存参数来减少它。我预计这会比更改存储以处理更多 I/O 产生更大的性能影响。

相关内容