一种zabbix server扩容改造方案

本文原创做者鲍光亚,京东商城基础平台部软件开发工程师,经做者赞成发表于本人博客,如需转载需经本人赞成。web

1、引言算法

随着监控量的迅速增加,zabbix管理员有一天会发现硬盘iops达到了数万,接近硬盘io的极限,无力支持处理更多监控数据。本文提出一种横向扩展方案,以尽可能小的改动,增长zabbix系统的数据io能力。
考虑到zabbix的数据库io主要在于history表和trends表,这一方案是在不增长zabbix server数量的状况下,将history表和trends表的io分散到其余主机上。此方案的优势是保持单个zabbix server,不须要考虑多server之间的协同一致。这一数据库分离模式还能够兼容原有的集中模式。可是,因为io分散到多个主机上,当须要读写数据时,不得不访问多个数据库实例。同时,代码中涉及数据库读写的部分,包括zabbix server和web api,都须要重写,好在大部分能够参考已有的代码。
本方案设计基于zabbix 3.0.10版本。本文只论及对zabbix server的改造方案,对web api的修改方案将另文讨论,本文不涉及。sql

2、zabbix数据读写机制数据库

因为configuration数据的io远小于history和trends数据io,本方案没有涉及对configuration数据的改动。
cache和vc_cache是zabbix源码中的两个变量名称,前者用于存储来自agent/proxy的原始数据,后者存储的则是从数据库中加载的数据(当数据已过时时,新数据则会直接从前者复制到后者之中),用于进行trigger计算等。
1.history和trends数据的写入
poller和trapper两类进程(包括pinger)负责从agent和proxy接收history数据,而后flush到cache中,同时更新cache中的trends数据。对cache的更新主要经过函数 process_hist_data实现。
dbsyncer进程则负责将cache中的数据写入到数据库中的history表和trends表中。因为dbsyncer存在多个进程,进程之间经过锁进行协调,避免冲突。cache数据入库主要经过DCsync_history和DCsync_trends两个函数实现。api

  1. history和trends数据的读取
    vc_cache在程序启动时分配空间,可是并不加载数据。此时poller和trapper进程还没有开始接收数据,所以也不会往vc_cache中写数据。
    程序启动之后,当须要数据进行计算时,会尝试从vc_cache中获取values,若是获取不到则会从history表中加载数据到vc_cache中。源文件中有三个函数用于从数据库读取value并加载到vc_cache中,这三个函数名为vc_db_read_values_by_time、vc_db_read_values_by_count、 vc_db_read_values_by_time_and_count。
  2. history和trends数据的删除
    housekeeper进程负责将过时的数据从history和trends表中删除。housekeeper还负责删除过时的events、alerts、sessions等。
  3. 数据库链接
    zabbix各进程对数据库的访问经过单个connection来创建链接。各个查询的执行函数都没有设置链接参数,而是经过全局性的conn变量维持链接。若是要实现对多数据库的访问,则只能增长链接变量数,或者动态修改conn。
  4. watchdog
    watchdog进程负责监视数据库状态,当发现链接失败时发送报警信息。

3、具体方案及实现数组

在数据库中,history表依照数据类型不一样分为history、history_uint、history_str、history_text、history_log五个表,trends表则分为trends和trends_uint两个表。遵循着分散io的思路,能够考虑两种方案,第一种方案是按照类别将history和trends分散到两个独立的数据库中,另一种是按照类别以及数据类型的不一样,将每个表都独立地存储到单个数据库中。下文主要按照第一种方案进行论述。缓存

  1. 改写配置文件
    在配置文件中增长所需的数据库链接参数,以及用于集中和分离模式切换的开关。配置文件的解析在程序启动时进行,所以还须要修改启动程序,增长存储数据库链接参数的数组元素以及开关变量。
  2. 修改数据库connect函数
    在保留原有connect函数的基础上,新增一个带有入参的connect,以根据须要创建不一样的链接。同时增长全局变量,用于保持多个链接。
  3. 修改数据库查询函数
    在保持原有查询函数的基础上,增长带有链接参数的查询函数,以动态变换查询链接。zabbix中有多个查询函数,用于不一样类型的查询,全部这些都须要修改。
  4. 对函数的调用
    上文说起的涉及history和trends读写的函数中,对数据库的访问部分都须要修改,增长对模式开关的条件判断,以调用不一样的函数。模式开关的逻辑应保证经过重启服务可使数据存储模式在集中和分离模式之间切换。
    若是采用按监控数据类型分库的方案,则还须要对sql文本构造过程进行修改。
  5. 修改watchdog逻辑
    将原来的单个实例状态监视,改成多实例同时监视,有任何实例链接失败时均报警。

4、数据一致性问题session

分离模式存在的风险之一是数据一致性问题。在集中模式时,zabbix经过互斥锁来协调对缓存的访问,保证缓存数据的一致性。写数据库时则经过transaction保证一致性。由于缓存锁机制的存在,数据库的分离与否并不会影响缓存的一致性,问题只能存在于数据库内部。
若是采用按类别分离的方案,即history和trends数据分别存储在两个数据库中,则须要考虑history、trends和其余表之间的一致性。若是采用按类别+数据类型分离的方案,则同时要考虑history各个表之间的数据一致性以及trends表之间的一致性。
经过分析源码中的transaction逻辑,history/trends表的更新操做不须要与其余表保持一致性(在数据库级别),在程序容许的状况下,双方能够独立写数据库。app

5、进一步的方案ide

遵循数据库分离的思路,更激进的方案是将history和trends数据中的每个表都进行拆分,以itemid或者clock为key按照必定的哈希算法,将数据分散存储到更多的数据库中。

相关文章
相关标签/搜索