iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >Zabbix数据结构及并行计算实现
  • 121
分享到

Zabbix数据结构及并行计算实现

2024-04-02 19:04:59 121人浏览 独家记忆
摘要

本文原创作者鲍光亚,京东商城基础平台部软件开发工程师,经作者同意发表于本人博客,如需转载需经本人同意。一、 前言我部门对数据库的监控使用的是开源的Zabbix系统,目前监控了上万台主机。本文旨在通过分析Za

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

一、 前言

我部门对数据库监控使用的是开源的Zabbix系统,目前监控了上万台主机。本文旨在通过分析Zabbix系统server端的数据结构和并行计算的实现方法,尝试探寻Zabbix系统server端的潜在扩展能力,同时希望有助于在实际应用过程中进一步优化运行效率和稳定性。

Zabbix系统采用server-proxy-agent架构,其server端的主要功能是收集监控数据并基于所收集的数据触发报警动作。在实际应用中,zabbix有可能会监控10000台主机(host,由hostid唯一标识),如果每台主机设置50个监控指标(item,由itemid唯一标识),并且每分钟收集一次数据,则一共有50万个item,每秒钟需要接收并处理8333项数据(value),即vps(values per second)为8333。如果有三分之一的item设置了报警触发器(trigger,由triggerid唯一标识),则共有17万个trigger。

在以上情境中,为了保证监控的有效性和及时性,zabbix接收到每个value后需要立即在50万个item中找到正确的item,并获取该item的前一个值(previous value,last(),以便计算增量),或者计算前5分钟内的平均值(avg(5m)),以便根据触发器表达式(trigger expression,由functionid唯一标识)判断是否应该触发报警事件(event,由eventid唯一标识)。同时如果item返回值类型为数字型,还需要计算该item在一个小时内的平均值(value_avg)、最大值(value_max)、最小值(value_min)。按照上面的vps数据,zabbix至少需要每秒钟搜索8333*500000次。此外,item和trigger并不是静态数据,用户随时可能会增加、修改、删除、禁用(disable)、启用(enable)某些item和trigger,zabbix需要在处理value时查询该item和trigger最新的状态。如何在一秒时间内完成如此大量的操作,zabbix给出的方案是: 哈希表。

在并行计算的软件方面,由于Zabbix系统监控的各个主机之间是相对独立的,无论在任务还是在数据方面都非常便于计算的并行化。服务器硬件方面,我们实际使用的服务器结构是2*8处理器+三级缓存+16G*8内存+SSD硬盘+10Gbps网卡(数据库、zabbix server和WEB服务共用)。Zabbix的并行计算主要采用的是共享内存模式。

二、 Zabbix中的哈希表种类

Zabbix使用的哈希表是链式哈希表,主要有以下五类(都是在共享内存中分配空间):

1. Valuecache

Valuecache中包含两个哈希表vc_cache->items(itemid作为键值进行哈希)和vc_cache->strpool(字符串作为键值),用于存储收集到的values(包括数字型和字符串型),每个item占用一个slot,每个槽位都是一个链表,链表节点存储实际需要的信息。

Valuecache的哈希表在服务启动时创建,服务退出时销毁,初始槽数为1009(1000之后的第一个素数),随着表中元素数量的增加,槽数也会按照一定的规则增多。Valuecache可使用的最大空间由配置文件中的ValueCacheSize参数控制,允许的范围是128K-64G。

2. Dbcache

Dbcache中的cache->trends哈希表,用于缓存trends表(每个item的小时平均值、最大值、最小值)的数据。Zabbix server的history_syncer进程会持续接收来自agent或者proxy的数据后会将其加载到缓存中,同时更新cache->trends哈希表。该哈希表中的元素是ZBX_DC_TREND结构体。

Cache->trends表中的数据时间超过整点时会被flush到数据库中,例如10点之后会将9-10点之间的数据flush到数据库中。

Cache->trends哈希表在服务启动时创建,初始槽数与vc_cache->items相同,为1009(1000之后的第一个素数)。Cache->trends哈希表的最大可用空间由配置文件中的TrendCacheSize参数控制,允许的范围是128K-2G。

3. Dbconfig

Dbconfig缓存中存储了多个与监控有关的配置信息的哈希表,包括config->hosts、config->items、config->functions、config->triggers等等。配置信息哈希表的键值包括hostid、itemid、functionid、triggerid、triggerdepid、expressionid、globalMacroid、hostmacroid、hosttemplateid、interfaceid、host_inventory等,其中数量最多的往往是itemid、functionid和triggerid,会在数十万级别(以10000个host计)。

以config->items为例,该哈希表的元素是ZBX_DC_ITEM结构体。Config->items中的数据是从数据库中查询获得的,zabbix server的configuration syncer进程会周期性地从数据库同步数据到缓存中。

Dbconfig缓存中的其他哈希表与config->items表类似,都是从数据库同步数据,都是在服务启动时创建,初始槽数都是1009,并随着数据量的增加动态扩展。整个dbconfig缓存可用空间大小由CacheSize参数决定,取值范围为128K-8G。

4. Strpool

此处的strpool与vc_cache->strpool是相互独立的两个哈希表。此Strpool缓存用于存储配置信息相关的字符串值,它与dbconfig共同分享CacheSize的空间(strpool占15%)。Strpool存储的字符串包括host name、item key、item delay_flex、snmp commUnity、snmp securityname、snmp passphrase、logitem fORMat等数据。Zabbix需要使用host name等字符串时,会首先在strpool中查找。

Strpool的哈希表初始槽数为1009。键值是字符串本身,哈希值是对字符串调用哈希函数的返回值。

5. 其他

除了以上哈希表,还有snmpidx、vmware service等哈希表。

三、 哈希表的实现

下面以config->items哈希表为例,说明zabbix中哈希表的实现方法。

1. 数据结构定义

Zabbix采用的是链式哈希表,哈希表中的每个slot都是一个链表。具体的数据结构定义如下:

2. Zabbix数据结构及并行计算实现    
槽数取值及负载因子

Zabbix的哈希过程是先调用哈希函数计算键值对应的哈希值,然后用取余法确定槽位号。因此,取余计算时的除数就是槽位数,该数值取素数(因为素数可以做到最大程度上均匀散列)。在config->items哈希表中,槽位数的初始值是1009,随着数据量的增加,当负载因子(元素数/槽数)达到0.8时,会扩充槽数量(扩充为当前数量的1.5倍以上,并取素数)。因此,负载因子总是保持在0.8和0.533之间。

按照以上规则,每次扩展哈希表,其槽数如下表示。当item数量为50万时,槽数应为670849。

序号

理论值

素数(槽数)

允许的元素数

0

1000

1009

806

1

1513

1523

1217

2

2284

2287

1828

3

3430

3433

2745

4

5149

5153

4121

5

7729

7741

6191

6

11611

11617

9292

7

17425

17431

13943

8

26146

26153

20921

9

39229

39229

31382

10

58843

58889

47110

11

88333

88337

70668

12

132505

132511

106007

13

198766

198769

159014

14

298153

298153

238521

15

447229

447233

357785

16

670849

670849

536678

17

1006273

1006279

805022

18

1509418

1509427

1207540

19

2264140

2264149

1811318

3. 哈希函数

Zabbix使用的哈希函数是在fnv-1a函数(Http://www.isthe.com/chonGo/tech/comp/fnv/index.html)的基础上稍微进行了改进。该函数采用乘积和位操作达到快速哈希的目的。具体实现如下:

Zabbix数据结构及并行计算实现

按照以上函数,模拟620000个itemid的哈希过程(槽数取1006279),哈希效率如下:

总桶数

1006279

空桶数量

543405

深度大于1的桶数

127940

载荷因子

0.616131311

最大桶深

7

深桶占有值桶比例

0.276403514

深桶占总桶数比例

0.127141677

空桶占总数比例

0.540014251

四、 任务和数据的并行化

1. 任务的并行

Zabbix系统的任务基本上都是基于所监控的host和item,各个host和item之间有较强的独立性。为了并行化,Zabbix将任务拆分为相对独立的子任务,各个子任务由一个或者多个进程来执行。Zabbix server端的进程划分如下表所示:

启动

顺序

process title

允许

进程数

默认值

任务

1

configuration syncer

1-1

1

从数据库同步数据到Dbconfig缓存

2

db watchdog

1-1

1

周期性地检查server端数据库是否可用,如果不可用则发送报警信息

3

poller #n

0-1000

5

根据dbconfig中的数据,从passive agent和snmp设备采集数据,并flush到共享内存cache->history中

4

unreachable poller #n

0-1000

1

当设备处于unreachable状态时,周期性地polling设备

5

trapper #n

0-1000

5

Socket接收并处理active agent和active proxy发来的数据(JSON格式,zabbix通讯协议),并flush到共享内存cache->history中

6

icmp pinger #n

0-1000

1

根据dbconfig中的数据,批量采集icmpping相关的item数据,并flush到共享内存cache->history中

7

alerter

1-1

1

发送各种报警通知

8

housekeeper

1-1

1

周期性地删除过期的历史数据

9

timer #n

1-1000

1

计算与时间相关的trigger表达式等

10

node watcher

1-1

1

处理与node之间的交互

11

http poller #n

0-1000

1

收集web监控相关的数据,并flush到共享内存cache->history中

12

discoverer #n

0-250

1

按照指定规则扫描网络,自动发现host、interface等

13

history syncer #n

1-100

4

将共享内存cache->history中的数据批量更新到数据库中,并flush到共享内存vc_cache、cache->trends、config->items等中

14

eScalator

1-1

1

当报警操作需要分步连续执行时,控制各步骤之间的escalations

15

ipmi poller #n

0-1000

0

与poller进程类似,处理ipmi items

16

java poller #n

0-1000

0

与poller进程类似,处理JMX items

17

snmp trapper #n

0-1

0

与trapper进程类似,处理snmp items

18

proxy poller #n

0-250

1

与passive proxy交互,以设定的频率获取所需要的json格式数据并将数据flush到共享内存cache->history中

19

self-monitoring

1-1

1

处理与zabbix自身运行状态相关的item信息,访问共享内存中的collector变量

20

vmware collector #n

0-250

0

采集vmware虚拟机相关的数据,并flush到共享内存中

所有进程中比较关键的进程有两类:poller/trapper类进程,用于采集数据并加载到共享内存中;history syncer进程,用于更新数据库及触发events和报警。逻辑上这两类任务是先后执行的,首先要采集到数据然后才能触发报警。而每类任务的各个进程之间是独立的,多个poller/trapper进程可以同时执行,多个history syncer进程也可以同时执行。

2. Socket multiplexing对多进程的支持

Zabbix监控系统的数据最终来源是被监控的主机,数据通过socket监听端口接收(监听端口允许的最大连接数由操作系统决定)。Zabbix通过fork多个子进程来共享同一个socket,在读socket时则通过基于select()函数的multiplexing实现多进程同时读取。

按照10000个host,每分钟采集一次数据(假设每个host上的所有item同时采集数据,事实可能并非如此),平均每秒钟有167个连接请求。

3. Mysql数据库的读写

Zabbix支持多种数据库,包括Mysqloracle、IBM DB2、postgresqlsqlite,我们实际使用的是mysql。为了保证数据的持续性,zabbix在触发报警前会先将数据插入到数据库中。History syncer进程数允许最多100个,每个进程可以与数据库建立独立的连接,进行数据更新。

五、 共享内存与进程间通信

1. 共享内存的创建

共享内存是进程间通信中最简单并且速度最快的一种机制。Zabbix的进程间通信主要采用共享内存的方式,主进程在fork出所有子进程之前调用shmget创建共享内存,并attach到地址空间中。

Zabbix调用shmget创建的共享内存segment共有8个,为config_mem、trend_mem、history_mem、history_text_mem、vc_mem、vmware_mem、strpool.mem_info、collector,分别用于dbconfig缓存、cache->trends数据、cache->history(数字和string)、vc_cache、vmware数据、strpool、监控zabbix自身状态的collector结构。如果实际应用中没有启用vmware,则只有7个共享内存被attach到各子进程的地址空间中,如下图所示,这些共享内存段将一直保持attach状态,直到服务停止。

Zabbix数据结构及并行计算实现

从上图可以看出,每个共享内存段都attach到了553个进程中,即zabbix server的每个进程都可以访问所有七个共享内存。

2. 信号量机制

Zabbix使用二进制信号量机制来协调多个进程对共享内存的同时访问,避免资源争用。系统在创建共享内存之前会调用semget函数,创建一个包含13个信号量的信号量集,并将每个信号量的值初始化为1。各个信号量用于对不同的共享内存进行访问控制,具体如下所示:

# define ZBX_MUTEX_LOG 0

# define ZBX_MUTEX_NODE_SYNC 1

# define ZBX_MUTEX_CACHE 2

# define ZBX_MUTEX_TRENDS 3

# define ZBX_MUTEX_CACHE_IDS 4

# define ZBX_MUTEX_CONFIG 5

# define ZBX_MUTEX_SELFMON 6

# define ZBX_MUTEX_CPUSTATS 7

# define ZBX_MUTEX_DISKSTATS 8

# define ZBX_MUTEX_ITSERVICES 9

# define ZBX_MUTEX_VALUECACHE 10

# define ZBX_MUTEX_VMWARE 11

# define ZBX_MUTEX_SQLITE3 12

当进程需要对某个共享内存进行写操作时,会首先lock(调用semop函数将信号量-1),执行写操作完毕后将再unlock(将信号量+1)。如果执行lock时信号量为0,则等待,直到信号量非0。Zabbix的信号量在释放共享内存时销毁。

六、 声明与结论

本文创作基于zabbix 2.2.10版本的源码分析,欢迎批评指正。

Zabbix所采用的哈希函数效果比较理想。但在实际应用中,仍然可以根据需要和资源情况对负载因子、槽数扩展速度、槽数初值、哈希函数定义进行改进。

在Zabbix的并行计算方面,由于监控系统的特点,数据和任务之间有较强的独立性,非常便于并行化。Zabbix通过多进程+共享内存实现并行,资源争用问题通过信号量进行控制。从实际应用效果来看,并行的性能非常理想。

Zabbix数据结构及并行计算实现

您可能感兴趣的文档:

--结束END--

本文标题: Zabbix数据结构及并行计算实现

本文链接: https://www.lsjlt.com/news/39010.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java数据结构之栈与综合计算器的实现
    目录1.栈1.1 栈的简介1.2 使用数组模拟栈1.3 栈的测试2.综合计算器的实现2.1 需求简介2.2 详细思路及分步图解2.3 完整代码及测试1.栈 1.1 栈的简介 栈(st...
    99+
    2022-11-13
    Java 栈 综合计算器 Java 栈 Java 综合计算器
  • go数据结构和算法BitMap原理及实现示例
    目录1. BitMap介绍如何判断数字在bit数组的位置设置数据到bit数组从bit数组中清除数据数字是否在bit数组中2. Go语言位运算左移右移使用&^和位移运算来给某一...
    99+
    2024-04-02
  • Java数据结构中如何进行并查集的实现
    这篇文章跟大家分析一下“Java数据结构中如何进行并查集的实现”。内容详细易懂,对“Java数据结构中如何进行并查集的实现”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“Java数...
    99+
    2023-06-28
  • 大数据文本并行计算实现方式是什么
    本篇文章为大家展示了大数据文本并行计算实现方式是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。对于大数据文件的处理,可以充分利用现代计算机的多核CPU,实施多线程并行计算,从而达到提速的目的。然...
    99+
    2023-06-03
  • Java数据结构之并查集的实现
    目录代码解析代码应用实际应用并查集就是将原本不在一个集合里面的内容合并到一个集合中。 在实际的场景中用处不多。 除了出现在你需要同时去几个集合里面查询,避免出现查询很多次,从而放在一...
    99+
    2024-04-02
  • Java数据结构之KMP算法详解以及代码实现
    目录暴力匹配算法(Brute-Force,BF)概念和原理next数组KMP匹配KMP全匹配总结我们此前学了前缀树Trie的实现原理以及Java代码的实现。Trie树很好,但是它只能...
    99+
    2022-12-08
    Java 数据结构 KMP算法 Java KMP算法 Java KMP
  • Python并行计算简单实现
    multiprocessing包是Python中的多进程管理包. Pool(num)类提供一个进程池,然后在多个核中执行这些进程, 其中默认参数num是当前机器CPU的核数. Pool.map(func, iterable...
    99+
    2023-01-31
    简单 Python
  • Java数据结构之KMP算法的实现
    目录问题介绍暴力求解知识补充Next示例Next代码匹配示例匹配代码完整代码本次我们介绍数据结构中的KMP算法,我们会从下面几个角度来介绍: 问题介绍 首先我们先介绍适用于KMP算法...
    99+
    2022-11-21
    Java KMP算法 Java KMP
  • PostgreSQL并行计算算法及参数强制并行度怎么设置
    这篇文章主要讲解了“PostgreSQL并行计算算法及参数强制并行度怎么设置”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL并行计算算法及参数强制并行度怎么设置”吧!一、优...
    99+
    2023-06-29
  • PostgreSQL并行计算算法及参数强制并行度设置方法
    目录一、优化器并行计算的并行度计算方法二、优化器是否选择并行计算三、优化器是否忽略并行计算四、优化器强制选择并行计算参数五、并行计算相关参数六、强行并行七、函数并行一、优化器并行计算...
    99+
    2024-04-02
  • python数据结构leetcode338比特位计数算法
    目录一、题目内容示例 1:示例 2:进阶:二、解题思路三、代码一、题目内容 给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数...
    99+
    2024-04-02
  • 详解Java实现数据结构之并查集
    目录​一、什么是并查集二、并查集解析2.1、初始化2.2、并 union(int a,int b)2.3、查 search(int a)三、优化四、代码实现五、...
    99+
    2024-04-02
  • DotNet中怎么实现并行计算
    这期内容当中小编将会给大家带来有关DotNet中怎么实现并行计算,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。误区三 . 并行计算是运行时的事 的确,DotNet会在运行时决定是否使用并行库处理代码,但是...
    99+
    2023-06-17
  • Java数据结构之KMP算法怎么实现
    这篇文章主要讲解了“Java数据结构之KMP算法怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java数据结构之KMP算法怎么实现”吧!暴力匹配算法(Brute-Force,BF)这...
    99+
    2023-07-04
  • Python编程算法:如何实现并行计算?
    在计算机科学领域中,计算机的速度一直是一个瓶颈。为了克服这个瓶颈,现代计算机通常采用并行计算方法。并行计算是指通过同时执行多个计算任务来提高计算机的效率。 Python作为一种高级编程语言,也可以实现并行计算。在本篇文章中,我们将探讨如何...
    99+
    2023-06-27
    编程算法 开发技术 git
  • Beam怎么实现数据的并行处理和分布式计算
    Beam是一个用于实现数据处理管道的统一编程模型,它可以在不同的运行环境中进行数据的并行处理和分布式计算。下面是Beam实现数据的并...
    99+
    2024-03-15
    Beam
  • Cassandra数据的分布式计算和并行处理怎么实现
    Cassandra是一个分布式数据库系统,它支持并行处理和分布式计算。要实现Cassandra数据的分布式计算和并行处理,可以采用以...
    99+
    2024-05-11
    Cassandra
  • Golang函数的算法和数据结构实现方法
    作为一种相对较新的编程语言,Go语言(也通常称为Golang)已被越来越多的开发者所青睐。Golang的一大特点就是速度快,而这是得益于其高效的并发机制和出色的算法实现。在Golang中,函数是非常重要的概念,成为了程序员高效编写代码的关键...
    99+
    2023-05-17
    算法 Golang 数据结构
  • 【Java数据结构与算法】Day2-高级排序(希尔、归并、快速、计数)
    ✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。 🍎个人主页:Hhzzy99 🍊个人信条:坚持就是胜利! 💞当前专栏:...
    99+
    2023-09-16
    java 排序算法 算法
  • 怎么进行Redis数据结构底层实现
    这篇文章将为大家详细讲解有关怎么进行Redis数据结构底层实现,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。面试中,redis也是很受面试官亲睐的一部分。我...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作