从代码级别优化Zabbix的数据展现性能

作者介绍

邹德裕,轻维软件首席数据库专家,DBAplus社群联合发起人,OraZ产品作者。10年以上运维管理经验,Oracle OCM,精通Oracle9i、10g和11g数据库技术及Linux Unix技术。对数据库系统架构具有深刻的理解,并在数据库诊断、故障排除、优化、架构设计等方面具有丰富的经验。

 

一、问题背景  
 

对于特大场景应用环境中,Zabbix本身对某些方面的性能并未考虑周全,本文就从代码级别二次开发优化入手来达到我们的需求。

 

从选择更好的硬件配置,如大容量内存、更快速的SSD固态磁盘、改raid配置等硬件角度优化,效果会立竿见影,不过大部分这些操作都是在规划阶段完成,后期往往通过软件优化为主。

 

Zabbix本身是一个高性能的分布式服务器集群监控系统,其基本结构是在多台被监控机上安装agent客户端,由agent端通过trapper不断捕获数据发送到server端,server端对捕获上来的数据进行解析再分别入库到后台数据库表中(Zabbix可以支持MySQL、Oracle、PostgreSQL等数据库),然后在前端管理界面上来访问相应的页面,并展现各台被监控机上的各项性能指标的情况,它的各种指标性能的展现所需数据的主表基本上是一个历史数据表,如下图样例:

 

上面图中所展示数据就来自于历史表之一history,此表基本结构如下:

 

 

(注:Zabbix原始表里没有为其添加任何主键和索引。)

 

其它的各种性能指标的展现所依赖的数据表结构基本如上表,只是value列类型不一样,而且表名不一样而已。

 

为何Zabbix的原设计者要如此设计这些表呢?我想是基于这样的原因:就是希望它能快速地进行数据入库和数据展现。因为,如果为表加主键或索引,则入库速度肯定会变慢一些,在管理成百上千台机器时,且管理指标项目又很多时(一个host下可以有多个不同类型的被监控项item),单位时间产生的数据量是相当可观的,如果入库一条记录稍微慢那么一点点,那在特大场景应用环境中就会几何倍数放大,收到的数据无法及时入库,并且可能造成Zabbix server内存积压,而连带使Zabbix server本身收集数据的能力变慢(甚至Zabbix server因内存不足而崩溃),最终会导致采到的性能数据丢失,Zabbix的作用就大打折扣,所以入库速度是它第一要考虑的问题。

 

另外,设计者为何要对不同类型的数据实行分开存放呢?我想他同样是为了增加入库速度的目的,也是为了提升查询展示的速度,因为不同数据类型分开存放后,一个表就“专用”化了,方便治理,也有利于将大表拆分成小表,减低单表压力,对入库速度和查询速度都是有利的(特别是有利于降低对表锁的争抢)。

 

好了,我们已经明白,为了管理大量的机器,我们必须要求Zabbix入库速度要尽可能地快,且查询对入库的影响要尽可能地小,为了这个目标它也有了比较多的考虑,但是经过我们的测试并梳理后,发现在展现最新数据时,仍旧是十分缓慢,我们观察了一下最新数据的展现机制,发现它是要从历史表中拿出最新入库的数据来展现,展现示例界面如下:

 


其查询语句大致如下:

select h.itemid,i.name,h.value,… from history hi, items It, hosts ht where hi.itemid=it.itemid and it.hostid=ho.hostid and ho.host='…' and it.name='…' group by it.itemid order by hi.clock desc limit 1
 

(注:以上语句是一个根据显示数据的情况写出的示意语句,不是原始的语句,且是基于MySQL,但实际用到的语句与此相似)

 

在数据量很大的情况下,基于现有的数据库设计,上面语句很明显会很慢。

 

1)它需要关联查询items表和hosts表,而如果没有主键,关联查询的性能肯定是相当慢(特别是数据量又相当大的情况下),而一般情况下,历史表中的数据量肯定是相当巨大;

2)需要用到group by查询和order by查询,在没有索引或主键且获取的数据量很大的情况下,其速度也肯定是很慢的;

3)因为前述问题,后台又要不断往历史表中插入数据,会争抢表或行锁,于是查询和入库之间会互相影响,导致大家都不好过。

4)要是多人同时打开界面查看与历史表相关的其它数据呢?那不是互相之间又产生更多影响。

 

于是,要让最新性能数据的展现显示得快,又对其它查询和入库不产生影响,非常有必要对最新数据的展现这一块进行优化,要设计一种方案来优化。

 

二、我们的优化方案和目标  
 

根据前面对问题的分析,我们需要实现以下几点:

 

  1. 对最新数据的查询要尽可能地快;
  2. 必须不能影响对历史表的入库;
  3. 保持对现有数据的结构。

 

基于以上目标,我们容易想到的方案是:在历史数据入库时,找出最新的数据并另存一份到一个独立的结构相同的最新数据表中,最新数据的展示查询时,只到这个独立的表中去查询,这样就可以解决上述三个问题。

 

三、设计及实现  
 

1、首先必须设计几个与历史表对应的用于存放最新数据的表。

 

last表(对应history表):

 

last_unit表(对应history_unit表):

 

last_str表(对应history_str表):

 

其它还有两个字串型表就不罗列了。

 

以上各个表的结构基本一样,与原对应的历史表数据结构也是一样的。

 

2、为上述表添加主键索引

 

根据前面问题背景分析里所述的查询语句,最新数据查询时会关联到items表和hosts表,为了加快数据查询展示速度,需要为上面新加的这些表的itemid列添加主键索引,即将itemid列设为主键列,在入库时每个itemid只有一行数据,就是最新的那条性能数据,同时要为相关的items.itemid列、hosts.hostid列添加主键索引(如果它们没有被加上的话)。

 

3、修改Zabbix server源码,添加对最新数据的入库,并做一些历史数据的入库优化。

 

找到Zabbix server程序的源码中同步历史数据的代码处(即:将内存数据刷入数据库的过程),根据其逻辑添加对最新数据的入库逻辑,以下是修改后的对history表数据入库的代码逻辑过程:

 


其它表的数据入库过程与此类似,参考代码略。

 

简单解释:

 

在上面代码里:ADD_HISTORY_PART_MID1(dbl, value.dbl)这一行展开的过程里会有以下代码:

 

 

上面的这一行dc_add_last_dbl(phis->itemid, &(phis->ts), phis->vf, 0);就会向存最新数据的数据表中插入最新的性能数据行。并且,上面过程看出,对同个itemid的数据行,只会执行一次记录插入(根据分析,在调用入库逻辑过程前,同一批历史数据是按itemid排好序了的,所以这样做是可以的),另外,dc_add_last_dbl(phis->itemid, &(phis->ts), phis->vf, 0)过程(代码略)在插入数据时,在插入语句里加了 "on duplicate key update value=values(value), clock=values(clock);" 这么一个子句,通过这个子句来实现插入时对已经存在的相同itemid数据进行修改,而不是插入一条新数据,这实现了数据的减量,但又不会增加插入性能消耗,因为表上只加了itemid主键。

 

改好后,重编译安装Zabbix server,再启动即可。

 

4、更改前端界面的查询

 

前面修改好后,还需要把前面展现最新数据的界面那里的原来的数据查询语句修改一下,将原来的从历史表中查询的方式改为从最新数据表中查询(就是前面新加的表),修改时相当简单,直接把前面问题背景分析里所述的查询语句里的表名改掉即可,如:history改成last,history_uint改成last_uint即可,以此类推,因为新加的表的结构与原来对应的历史表结构一模一样。

 

四、效果与总结  
 

经过上述修改后,我们发现,最新性能数据展现那里已经可以十分快速地打开界面了,这说明上面的做法起到了相当明显的优化效果,同时,从这个效果里我们也看到解决了背后的一个问题:历史数据的入库也不会受到因对历史表的group by/order by/关联查询的影响而变得快速了,不会因为查一下历史表里的最新数据,就让入库都受到影响而变慢。

 

总结起来就是:要尽量让客户端捕获上来的数据尽快收集起来并能快速插入到数据库中,要尽量避免在历史表中使用可以避免的影响速度的查询,否则可能会影响到入库(同时查询本身也会慢)导致采集到的数据丢失。


时间: 2024-10-17 11:31:56

从代码级别优化Zabbix的数据展现性能的相关文章

优化-java代码中有个循环,数据量一大直接网页报500错误

问题描述 java代码中有个循环,数据量一大直接网页报500错误 求大神帮忙优化一下,10000数据还可以,但是数据一多网页就崩溃了,就是代码中的row++,加上去就不行了 解决方案 结果是内存益处了 那就是你的程序太耗费资源了. 那个获取page的方法: 1--Page对象村的东西太多了,很多何你写入单元格的数据没关系, 既然这块逻辑是大数据量的,为什么不拆分针对这块逻辑的结构呢? 使用Page造成了很大的内存浪费 在循环外部定义这个结构 List list = null 2--将方法的参数精

c#这段代码向数据库批量添加数据为何1000行就需要10分钟啊求大神帮忙优化啊

问题描述 c#这段代码向数据库批量添加数据为何1000行就需要10分钟啊求大神帮忙优化啊 public void ShuaXin() { SqlCommand com = new SqlCommand(""delete from priceavg"" DBHelper.con); DBHelper.con.Open(); com.ExecuteNonQuery(); adapter = new SqlDataAdapter(""select *

《高性能科学与工程计算》——第2章 串行代码基本优化技术2.1 标量剖析

第2章 串行代码基本优化技术 在千核级并行计算机时代,有些观点认为编写高效串行代码在许多领域已经有些过时了.因为增加更多CPU以获得大规模并行能力要比投入大量精力优化串行代码简单得多.这似乎是一个合理的理论,5.3.8节的论述中也体现了对这种观点的支持.然而,本书认为程序在单处理器上的性能优化毫无疑问是最重要的,如果通过一些简单的优化方法就可以实现两倍加速比,那么用户会更倾向于使用较少的CPU.这样不仅可把宝贵的计算资源释放给其他用户或项目,而且还可以使投入大量资金购买的硬件获得更加有效的利用.

for-大神们,这样写容易内存溢出,这段代码怎么优化?1000张表,表结构相同,表名不同

问题描述 大神们,这样写容易内存溢出,这段代码怎么优化?1000张表,表结构相同,表名不同 raf = new RandomAccessFile(srcFilerw""); int index = 0; //获取imei数据 connection = getConnection(); String _sql = null; for(int i=0;i<10;i++){ _sql = ""select * from "" + "&q

大数据优化 | 以大数据优化为基础构建未来就绪企业

打造未来就绪的企业,并非以"预测未来"为前提,而是面向未来做好准备. 大数据真正的价值即在于为面向未来做好准备,帮助企业规避风险. 戴尔提供专门为大数据目标而设计的端到端体系架构,助力企业通过大数据获得商业洞察,面向未来就绪. 正如纳特·西尔弗(Nate Silver)在他的畅销书<信号与噪声>(The Signal and the Noise)中写的,预测未来是非常困难的,因为"我们选择性地忽略了最难以衡量的风险,即便这些风险对我们的生活构成了最大的威胁&quo

探讨SQL Server批量向数据库插入数据的性能优化问题

昨天下午快下班的时候,无意中听到公司两位同事在探讨批量向数据库插入数据的http://www.aliyun.com/zixun/aggregation/14109.html">性能优化问题,顿时来了兴趣,把自己的想法向两位同事说了一下,于是有了本文. 公司技术背景:数据库访问类(xxx.DataBase.Dll)调用存储过程实现数据库的访问. 技术方案一: 压缩时间下程序员写出的第一个版本,仅仅为了完成任务,没有从程序上做任何优化,实现方式是利用数据库访问类调用存储过程,利用循环逐条插入.

FullCalendar日历插件应用之数据展现(一)_javascript技巧

开发者可以使用FullCalendar创建强大的日历日程应用,FullCalendar提供了丰富的选项设置和方法调用,使得开发者可以轻松的创建各种功能的日历程序. 由于项目需求,需要通过日历的方式展现某些数据,在网上搜索了很多日历的插件,觉得比较好用的还是fullCalendar,下面是我写的一个简单Demo,如有不足,请多多指正!!!  一.引入必要的文件: <link href="Scripts/Plugins/fullcalendar.css" rel="styl

代码需要优化!!!!!!

问题描述 代码需要优化!!!!!! public void exportArrearDatail(HttpServletRequest request, HttpServletResponse response){ String templateId = request.getParameter("templateId"); String fileNames = request.getParameter("fileName"); String fileName =

西部数据发布针对现代数据中心优化的冷数据存储硬盘

 全球领先的现代化数据中心存储领导者西部数据发布了旗下创新的WD Ae 硬盘产品线.针对在网络规模数据中心新兴的归档分层存储,该系列产品为此归档存储独特运营特点进行了特殊设计.WD Ae硬盘基于为实现最优总拥有成本(TCO)的平台设计,其最低功耗性能与Progressive Capacity (渐进式扩充容量模式) 为大规模云架构存储开创了全新的存储分层. "现代化数据中心客户给我们提出了专为持续扩展的冷数据储存而设计的硬盘解决方案需求."西部数据存储技术事业部高级副总裁兼总经理Mat