zabbix運行久了以后效率會變慢的原因分析


公司zabbix 的規模500多台機器,日常操作感覺很卡,隨着好奇心看了一下zabbix的實現。。發現了一些有趣的東西。。

首先是數據庫特別的大,大概340g ,是我見的過比較大的。用的是mysql innodb ,里面表比較多,但是大多都比較平常,有一個特別之巨大,是history這個表,看了下,有30億行數據。。

select table_name ,table_rows from tables  where table_schema='zabbix'  and table_name like 'history%';

+-------------------+------------+
| table_name        | table_rows |
+-------------------+------------+
| history           | 2881585282 |
| history_log       |          0 |
| history_str       |     720801 |
| history_str_sync  |          0 |
| history_sync      |          0 |
| history_text      |    5275879 |
| history_uint      |  352996499 |
| history_uint_sync |          0 |
+-------------------+------------+

這里table_rows這個並不是精確數值,是一個大概的值,每次查詢得到的都不一樣,而且相差個1,2億是正常的。。要正確取得rows 的話只能count(*) ,但是運行一下的話全表遍歷,估計要n久才能得出結果。

好吧,不去糾結具體多少,大概就是30億數據這個數據量。

history的表結構如下,

       Table: history
Create Table: CREATE TABLE `history` (
  `itemid` bigint(20) unsigned NOT NULL,
  `clock` int(11) NOT NULL DEFAULT '0',
  `value` double(16,4) NOT NULL DEFAULT '0.0000',
  `ns` int(11) NOT NULL DEFAULT '0',
  KEY `history_1` (`itemid`,`clock`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

說道這里就必須提一下zabbix的架構了,是一個典型的c/s架構,server段去拿agent 端的數據,然后把數據存在數據庫里,這也是為什么運行server的時候一定要給出正確的連接數據庫參數的原因了。

他很簡單,叫拿到的數據按照itemid 存到數據庫里面去,需要的時候select 出來,通過php 的frontpage 來展現給我們。

但是這個數據增長的有點快,已500個主機的監控為例,每個host默認有108項items ,當然有些不止108,可以自定義添加的。那么多是時間獲取一次呢,這個也是不定的,system.cpu.load[,avg1],網卡流量net.if.in[eth0,bytes]等都是5s 一次的,system.cpu.util[,nice,avg1] 什么的都是10s一次,還有20s,30s ,60s等。

算他20s 平均,那么一天的數據流就是

500*100*20=20w  ,這個估算有作用,有個server 參數MaxHousekeeperDelete ,當開啟自動清理history數據的時候,最大清理多少項,如果這個值設的太低,低於每天生成的數據,那么清理是無效的。

我看了下公司的zabbix 記錄,可以看到1年前的圖。。基本沒起什么用,所以這個數據量才能達到驚人的30億行!

大家都知道,在這么大的一個數據量上進行select ,不慢才怪了。。基本上生成一幅圖表需要15s樣子。。插入數據需要30多秒。。系統變的越來越臃腫,用戶體驗直線下降。。查詢效率非常之慢!

那么寫到這里大概找到整個系統運行慢的終極原因了。似乎有二條路可以分兩步走,第一是手動把history數據給刪掉點。。第二是設置正確的MaxHousekeeperDelete 參數。但是做之前先要備份數據庫。這里沒有實踐。因為考慮到history有不少相關的其他的表

+-----------------------------+
| history                     |
| history_log                 |
| history_str                 |
| history_str_sync            |
| history_sync                |
| history_text                |
| history_uint                |
| history_uint_sync           |

把history刪了以后,其他地方 導致不統一了怎么辦?

這里我的做法 是先改大MaxHousekeeperDelete,每次多刪有點,保持每天都在瘦的狀態,那么最終會達到我們想要的效果。

 怎么看是否有刪除呢,我的做法是開啟slow log ,基本上,這種操作都會被記錄進slowlog 的,有記錄那么肯定在刪除了。而且5.1以后slow log都是可以動態開啟的。不需要重啟mysql。不要的時候關閉即可。非常方便。

========================================

隔了一段時間,再修改這篇文章,發現這個也是存在問題的,首先zabbix 卡不單是因為history這個表,還要一個events的表我覺得很有關系。還是,history 這個表時刻在insert數據,這么大量的刪除,會和insert 爭用鎖? delete的時候為了保證數據完整性,應該會用鎖,而我覺得這個鎖會對insert有 影響。

分析slowlog

Count: 10936 Time=18.11s (198094s) Lock=0.00s (0s) Rows=1.0 (10935), zabbix[zabbix]@2hosts
SELECT e.eventid, e.value, e.clock, e.objectid as triggerid, e.acknowledged FROM events e WHERE e.object=N AND e.objectid=N AND e.value=N ORDER by e.object DESC, e.objectid DESC, e.eventid DESC LIMIT N OFFSET N

Count: 9435 Time=17.47s (164812s) Lock=0.00s (0s) Rows=1.0 (9434), zabbix[zabbix]@[192.168.0.75]
select eventid,value from events where source=N and object=N and objectid=N and value in (N,N) order by object desc,objectid desc,eventid desc limit N

可以看到zabbix 一直在從events 數據庫里面查詢數據,這個表數據大概在8千萬樣子,1億不到,物理數據有14G,

show engine innodb status
68.23 inserts/s, 0.50 updates/s, 11.75 deletes/s, 5300219.70 reads/s

發現大量的read 操作,再看這個sql 語句,14g的數據,雖然explain中有用到索引,我覺得這個量還是非常大的,如果減小這個表的規模,查詢應該會很快。

這里我覺得有兩個方法,一種是比較大膽的,刪了events表的全部數據,當然14G的數據你不能這么干,否則老板也會把你干掉的。網上有種不錯的方法是利用ln 硬連接,先drop了,然后再慢慢對付硬盤文件。

還一種是慢慢切割行,每天分鍾刪一點,那么一天累計起來也不錯。這個數據要測試,不能太大,影響業務。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM