zabbix 的一次优化尝试

背景

笔者维护的 zabbix 数据库,由于监控几千台机器,几百个监控项,后台数据库压力比较大。zabbix 数据默认存放在 MySQL,基本 SQL 都是自己生成,当监控的机器数多了,监控项也多了之后,很多低效 SQL 的问题就暴露出来了。下面记录下对 zabbix 的运维改造过程。

问题

  • 读写量大。写量每天 1 亿次,曾一度超过微博最大端口的写量。读量每天 2 亿,也排在所有端口读量的前 6 名。
  • 数据量大。history、history_uint 表,trends 表等是不断积累的。
  • zabbix 自带有定期删除的机制,但每次删除从库就延迟,加上读写量又大,从库延迟追不回来。
  • 很难备份。
  • 读写都在主库上,主库压力较大

改造

针对以上这些问题,开始了一步步的改造,只要是能优化、容易优化的方法基本都使了。

  • 读写分离。zabbix 本身不支持读写分离,业务层面使用 oneproxy,而后台则使用主从架构,用 DNS 做的负载均衡,在从库上表现就是轮询多个 ip。这有个问题,虽然主库压力小了,但从库压力相对大了。线上服务器基本是 8 核,32-64 G 内存,sas raid 10 配置,因为机器资源不够,怕影响其它服务也不能混跑,因此只配了一主两从。大部分读都切到从库了,主库上还是有部分读。
  • 部分表用 tokudb 压缩。先清空一遍 history 和 trends 表,再将引擎改为 tokudb ,分 100 个分区。zabbix 官方用的存储过程来定时创建和删除分区,但按照规范不使用存储过程,因此改为手动一次性创建分区,7 天一个分区够 3 年用了。
  • 停止 zabbix 自带的 housekeeper 删数据,改为外部的定时任务去删。 housekeeper 采用的 delete,不加约束的 delete 很容易造成从库延迟;而采用 cron 的话只需要定期删除一些分区即可,比 delete 高效。
  • 用 cgroup 限制 cpu 的使用。一个是 tokudb 引擎比较耗 cpu ,第二个是 zabbix 本身负载较高,需要做些限制。
  • 为了省资源,也不做备份了,监控数据本身也不是特别重要,业务也允许丢数据。
  • tokudb 开启 RFR 特性,但对 insert 效果比较好,而 zabbix 主要是 update,提升并不是很大。

改造后

改造完成后主库压力降了很多,服务看似正常了。一段时间过后又冒出了新问题,主库每过一段时间就重启,并且发现 swap 用完后要么是 MySQL 实例被 kill,要么是机器重启。如下是被 kill 的情况。

通过查看服务器一段时间的资源使用情况,发现一个规律:每天晚上 0 点开始的一段时间,机器负载异常,cpu idle 掉的厉害,memfree 和 swapfree 突然减少。询问业务后,原来每天晚上 zabbix 都要重启一次,很多表项需要重新加载。猜测造成的原因为重启这段时间内访问压力过大,可用内存不够导致 swap。如下两幅图是主库的 CPU 和 MEM 使用情况。

从库上也有 swap ,但是从库并没有因为内存不够而被 kill 的情况。如下是从库的 CPU 情况,下降的并不明显

最后跟业务沟通,业务调整了刷新数据的策略,避免在短时间内出现负载的高峰,于是该端口恢复了正常。

三个问题

  • 为什么主库机器内存耗的这么快(跟 update 语句有关?),实例经常被 kill(主从 swappiness 都设置为 1,并且主库内存有 64G,tokudb 20G,innodb 16G。从库都只有一半)
  • tokudb 除了分配的内存,难道还会大量使用 OS 内存?
  • 有必要对 Server 或者引擎层面的参数做个监控,根据参数的变化趋势来及时发现问题。

一个 BUG

这是最近维护 zabbix 过程中发现的一个 bug https://support.zabbix.com/browse/ZBX-10652

你可能感兴趣的:(MySQL,数据库,Zabbix)