概述
本文是Aurimas Mikalauskas在参加Zabbix2014年大会之后根据演讲内容整理而成。
关于Aurimas Mikalauskas
Percona公司 MySQL高级顾问;
Percona是领先的MySQL咨询公司,其发布的产品Percona Server是一款独立的数据库产品,为用户提供了换出其MySQL安装并换入Percona Server产品的能力。
本文由Zabbix开源社区核心成员 thinkc(微信ID:田川)翻译分享,代表社区送上感谢ヽ(✿゚▽゚)ノ
关于 thinkc
某大型企业云计算架构师,多年Zabbix,Python,Linux使用经验,社区群活跃核心成员之一 。
以下是正文
Zabbix和MySQL
当我到达Zabbix2014会议地点后,做的第一件事就是与正在大规模使用Zabbix的人们交流,并试图找出他们面临的最大挑战。显然,在所有的案例中,问题点都是MySQL,特别是MySQL的磁盘I/O
考虑到这一点,我建议进行一些优化,这将有助于您的MySQL从磁盘和可用的硬件资源中获得最好的性能表现(进而将帮助您的Zabbix获得最好的MySQL性能表现)。
SSD是一个游戏改变者
“MySQL在SSD上会运行得更好吗?”我一遍又一遍地听到这个问题,无论是公开的还是私下的。
我可以明确地告诉您,如果目前I/O是您的瓶颈,无论是因为某些查询需要很长的时间来运行,然后您看到diskstats报告每秒100-250个读取直到查询完成(等待时间),还是因为请求与等待时间的影响(吞吐量)导致的磁盘过载。固态硬盘都必然有所助益,不只是一点点,而是极显著的!
思考一下:最快的机械磁盘(15K RPM)可以每秒最高执行250个随机I/O的操作(在这一点上它受限于物理法则),即使你有由16块磁盘组成的RAID 10阵列,一次独立查询也只能读取一块磁盘。所以如果你需要读取15000个数据点去显示一幅图像,那么从磁盘中读取这些数据点将会花费60秒的时间。
另一方面,企业级的SSD硬盘可以执行15,000次甚至更多次的单线程下16k数据块的每秒随机读操作(16k是InnoDB数据库引擎中最小单位数据块的大小)。而随着您增加吞吐量,它只会变得更好!这意味着上面例子中的查询将会由60秒减少到1秒,这是很显著的变化。此外,您还可以在同一块SSD硬盘上同时运行更多的请求,这只会使I/O操作的总量有所增加却不会影响到性能,而单个机械磁盘则不得不在多个请求之间共享其全部可用的250个I/O操作。
SSD唯一无法击败机械磁盘的领域是顺序操作,特别是单线程下的顺序写入。如果这是您的典型工作负载场景(假设您主要是收集数据并很少读取的话),那么您可能需要考虑其它策略。
MySQL配置
除了改进您的磁盘I/O子系统之外,还有一些方法可以减少I/O上的压力,我将介绍一些my.cnf变量,这些变量将帮助您实现这一点(以及其它问题,例如内部争用)。
请注意,这些变量参数中的大多数对于任何典型的高性能MySQL设置而言都是常见的。但是可以为了性价比而放宽一些参数从而使之适用于Zabbix,这会导致在最差的情况下,收集数据时多损耗1秒的时间,不过从本次会议的讨论来看,没有任何人认为这是个大问题。
innodb_buffer_pool_size
如果你有一个专用的MySQL服务器,将此参数设置得尽可能地高(上限是所有可用内存的75%)。否则,您应该在服务器上平衡此参数与其它应用进程的内存占用比例,不过如果仅仅是Zabbix服务器的话,那么我仍会将此参数设置的很高,比如接近全部内存的75%。
innodb_buffer_pool_instances
对于MySQL 5.5版本,可以将此参数设置为4。对于MySQL 5.6版本,可以将此参数设置为8甚至16。
innodb_flush_log_at_trx_commit = 0
这是为了显著提高写入吞吐量而妥协了数据持久性,尤其是如果您没有拥有非易失性缓存的磁盘子系统的话。基本上您可能会在MySQL或服务器崩溃时造成1秒的数据写入损失。而很多网站都是这样运行的(很多网站甚至仍然运行在MyISAM数据库引擎上! ! !),我敢肯定这不是Zabbix安装配置的问题。
innodb_flush_method = O_DIRECT
如果您正在运行Linux操作系统,请这样设置该参数。
2:00
innodb_log_file_size
您需要事务日志(默认情况下有两种日志)保存1到2个小时的写入值。为了确定这一点,您或者可以查看Zabbix中MySQL服务器的“图形”指标,或者可以从MySQL的控制台上运行以下命令:
mysql> pager grep seq; show engine innodb status\G select sleep(3600); show engine innodb status\G
PAGER set to 'grep seq'
Log sequence number 8373513970951
...
Log sequence number 8373683996767
这两个数字之间的差值就是InnoDB数据库引擎在最近一小时内写入了多少字节数。因此,在上面的这个服务器中,我将设置innodb_log_file_size = 128M,并最终得到256M的日志文件空间从而允许我存储超过1小时的事务日志写入量(如果运行MySQL 5.5或更早的版本,请参阅此链接[https://www.percona.com/blog/2013/09/05/my-favorite-secret-mysql-5-6-feature/]以了解更改日志文件大小)
innodb_read_io_threads, innodb_write_io_threads
不要过于纠结这些变量,它们并不如看起来的那么重要,尤其是如果您使用了Async IO(您可以通过在MySQL控制台终端上运行“show global variables like 'innodb_use_native_aio';"命令来检查确认AIO状态)。对于MySQL 5.5和5.6版本,通常您会希望使用Async IO(AIO),如果您还不是很明白,那么请检查MySQL日志以了解原因。也就是说,如果您不使用AIO,那么就无需理会,只要把这些值设为8,并保持不变即可。
innodb_old_blocks_time = 1000
这将有助于防止由于偶尔的扫描而引起的缓冲池污染。这个变量在MySQL 5.6版本中已被默认设置(对于5.5版本,则需要显式设置)
innodb_io_capacity
此变量设置为与您的磁盘子系统可以处理的写IOPS操作量相同的数值。对于SSD来说,至少应该是几千(2000是一个较好的起始值),而对于机械磁盘来说,它的值要低一些 --- 500-800是较为合适的(取决于承载盘的数量)。最好是对磁盘进行基准测试,或者根据实际数字进行核算。不过对于目前大多数系统而言,200的默认值肯定是太低了。
sync_binlog=0
此变量是默认设置的,但是如果它的值大于0,那么除非你运行了除Zabbix之外的其它应用,否则将此变量设回0。不同步二进制日志的代价是,在主库崩溃的情况下,副本机制会失去同步,不过如果您由于二进制日志同步而经常遇到I/O瓶颈,仅仅因为您想避免可能五年才发生一次的主库崩溃而需同步从库的诸如此类的麻烦,那么您应该重新考虑这个选项。
query_cache_size=0, query_cache_type=0
这些变量设置将禁用查询缓存。在大多数情况下,您不会想查询缓存。如果这些设置在内核中没有被禁用,那么查询操作的性能(尤其是小数据量的)可能会因为查询缓存的互斥争用而受到影响。
sort_buffer_size, join_buffer_size, read_rnd_buffer_size
如果您曾经配置过这些变量,那么请取消这些更改(只需要删除或注释掉它们即可)。我发现,在大多数客户的服务器上,这是三个最易被误改的变量。在很多情况下,最好不要触碰它们。只要将它们保持默认值就行了。
tmpdir
有时,把tmpdir指向/dev/shm是一个好主意,因为这样磁盘上的临时表实际上是写入到内存中的,但是从MySQL 5.5版本开始,对此有了一个重要警告:如果您这样做,将全面禁用AIO,因为tmpfs不支持AIO。所以,我会监视当前的tmpdir(通常是/tmp目录)上的活动,只有当我认为它是一个问题时,才会将其切换到/dev/shm。
MySQL分区
我知道Zabbix为了简化数据处理目前已支持分区,不管怎样,我认为从分区技术中是可以得到一些额外好处的。如果您已经按日期使用分区,事实上就已经是在用子分区技术了。
您可能一次又一次听说Zabbix的KPI,也就是您在Zabbix的状态页面中可以找到的“每秒新值”这个数字。基本上,值越高(基于您有足够的数值来监控),那么您的Zabbix的吞吐量就越好。这是很多人在使用Zabbix时都遇到的限制———MySQL无法插入足够的每秒新值。
除了上面我已经提到的优化措施(它们应该大大提升了您的写吞吐量!),我也鼓励您尝试一下分区(如果您还没有使用分区)或者是基于哈希的子分区(如果您已经使用了分区),因为我们发现在某些情况下,分区可以提升InnoDB数据库引擎的吞吐量[https://www.percona.com/blog/2011/01/07/high-rate-insertion-with-mysql-and-innodb/]。
我没有专门测试Zabbix的这个特性,因为它没有被Zabbix默认支持,所以你不得不自行研究分析并使之正常运行,但是如果您做了上面所有的调整仍然无法获得足够的每秒新值(当然前提是底层硬件资源没有限制您),那么建议尝试一下分区或者是关键表基于哈希的子分区。
如果这听起来很有趣,但您不确定从哪里开始,那么请随时与我们联系,我们将与您一起协作并使之生效。
MySQL高可用性
有很多方法可以实现MySQL的高可用,即使很多人相信不是这样的。我们已经在博客上写了很多关于这方面的内容,所以我不会复述或重复,相反,我想向你们介绍一些关于此话题的宝贵资源:
Yves post on High Availability Options for MySQL
[https://www.percona.com/blog/2013/10/23/high-availability-options-for-mysql-october-2013-update/]
Jay’s recent webinar on Percona XtraDB Cluster
[https://www.percona.com/blog/2014/09/22/migrate-percona-xtradb-cluster-galera/]
Fernando’s and Martin’s webinar on MySQL Fabric
[https://www.percona.com/blog/2014/08/04/qa-putting-mysql-fabric-to-use/]
另外,Percona Server, Percona XtraDB Cluster, Percona Toolkit – 都是免费的!
我不太确认为什么,但我在这次会议上曾与之交谈过的很多人都认为,所有的Percona软件要么需要购买,要么除非你购买许可认证否则它所具备的一些企业功能将是不可用的。
而事实是,这两种看法都不对。所有的Percona软件都是完全免费的。您可以随时从我们的网站上或资料库中免费下载它们并随意使用。