少妇被又大又粗又爽毛片久久黑人,国产无遮挡又黄又爽免费视频,18禁男女爽爽爽午夜网站免费,成全动漫影视大全在线观看国语

3.9 Zabbix-Server對數據的存儲

3.9 Zabbix-Server對數據的存儲

無論監控系統采用何種架構,是否使用代理,對于Zabbix-Server來說,數據存儲都是一個非常大的挑戰。通常來說,使用分布式架構,并讓客戶端處于主動模式,會提高Zabbix-Server的吞吐性能。關于構建分布式架構和客戶端主動模式的一些細節問題,請讀者閱讀本書第9章。本節主要講述如何對Zabbix-Server端數據的存儲進行有效優化,這里采用表分區的方式對數據庫進行優化。除此之外,還可以采用分布式數據庫,以及Zabbix 4.0版本所支持的Elasticsearch搜索引擎數據庫,以提高數據庫的性能。

如果讀者對本節內容不是特別感興趣,只是測試驗證功能,則可略過此節,直接閱讀后續的3.10節。

由于整個章節的數據庫環境均為MySQL,故表分區的方式僅針對MySQL。

3.9.1 監控數據的存儲

通過前面的學習,我們知道Zabbix-Server將采集到的數據存儲在數據庫中,也了解到數據存儲的大小與每秒處理的數據量有關,所以數據存儲取決于以下兩個因素。

· New values per second(每秒處理的數據值):Zabbix-Server從客戶端每秒接收到的數據。

· Housekeeper的設置:對超過存儲期限數據的刪除策略。

Zabbix-Server將采集到的數據主要存儲于歷史表和趨勢表中,對于不同類型的數據,則分別存儲于不同的表中,如表3-7所示。

表3-7 數據存儲表

歷史表存儲在每個采集周期內收集到的全部歷史數據;趨勢表存儲經過聚合后的歷史數據,將每個采集周期的數據合并成每小時的最小值、最大值和平均值。比如監控項每秒采集1個數據,1小時則存儲歷史數據60條記錄,存儲趨勢數據1條記錄。

歷史表的表結構如圖3-30所示,可以看到每個表都有“時間-值”的字段,即監控數據存儲的是一個時間序列值(請參考本書第1章探討的時序數據庫相關知識)。

圖3-30 歷史表的表結構

在趨勢表中都包含最小值(value_min)、最大值(value_max)和平均值(value_avg),圖3-31展示了其表結構。

圖3-31 趨勢表的表結構

對于超過存儲期限的數據,Zabbix-Server使用Housekeeper進程進行數據清理。從源碼中我們可以看到,其刪除機制通過housekeeping_history_and_trends函數實現,其核心刪除SQL語句為“delete from %s where itemid=" ZBX_FS_UI64 " and clock<%d”,具體代碼如下:

shell# cat src/zabbix_server/housekeeper/housekeeper.c
static int  housekeeping_history_and_trends(int now)
{
    /*省略非關鍵代碼*/
    for(i = 0; i < rule->delete_queue.values_num; i++)
    {
      /*省略非關鍵代碼*/
        /*從表中刪除大于clock(指定時間區域)的監控項(item)*/
      rc = DBexecute("delete from %s where itemid=" ZBX_FS_UI64 " and clock<%d",
              rule->table, item_record->itemid, item_record->min_clock);
      if(ZBX_DB_OK < rc)
          deleted += rc;
      }
    /*省略非關鍵代碼*/
  }
  /*省略非關鍵代碼*/
  return deleted;
}

通過閱讀源碼,我們知道了Zabbix-Server對數據的清理是通過SQL語句DELETE來執行刪除動作的。隨著數據存儲的增多,其執行效率會顯著下降。有經驗的讀者都知道,在一個有千萬條、億條記錄的表中執行一條DELETE SQL語句,少則數秒,多則數十分鐘才能夠執行完畢。所以,Housekeeper程序執行的SQL語句會嚴重影響數據庫的性能,從而導致數據庫成為整個監控系統的性能瓶頸。

對于記錄條數很多的表,在SQL優化方案中最常見的方式有橫向擴展和縱向擴展。在這兩種方式中,一是用足夠好的硬件;二是將數據進行分布式存儲。而分表可以看作分布式的一種,即按一定的規則將數據劃分區間,從而避免全表掃描所帶來的性能損失,這樣就可以最大程度地提高性能。在這里我們就采用對表區間進行劃分的方式來優化數據庫。

下面來看一個在線的Zabbix數據庫中歷史表數據量的大小(見圖3-32)。

圖3-32 數據大小和數量統計

mysql> select table_name, (data_length+index_length)/1024/1024 as total_mb, table_rows  from  information_schema.tables  where  table_schema='zabbix';

在history_uint表中,數據達到3.8億條,如果在這個表中執行DELETE的SQL語句,其速度是可想而知的。

在了解了對Zabbix數據庫進行分表的必要性之后,下面介紹如何劃分表的區間。首先,對history表進行區間劃分,這里分區的標準是按天進行劃分的,分區后,會提高查詢數據的效率。如圖3-33所示,基于時間片段,直接找到數據所在的分區,而不用掃描全表進行數據匹配。

圖3-33 有無表分區查詢數據的方式

有些讀者肯定會想到,既然采用了表分區,那么對過期的數據是否可以通過表分區的規則方法直接刪除,而不再使用效率低下的Housekeeper?答案是可以的,我們可以直接將Housekeeper關閉,使其不再執行DELETE這種落后的方式來刪除數據。在Web頁面中,依次找到Administration→General→Housekeeper,去掉History和Trends選項的勾選狀態,即可關閉History和Trends的Housekeeper功能,如圖3-34所示。

圖3-34 歷史數據和趨勢數據的Housekeeper開關

3.9.2 MySQL表分區實例

1.表分區腳本代碼實現

以下腳本實現對數據庫zabbix的表分區:

shell# vim /usr/sbin/partitiontables_zabbix.sh
#! /bin/bash
# author: itnihao
# date: 2018-06-06
# funtion: create parition for zabbix MySQL
# repo: 

#配置環境變量,讀者可根據實際情況修改
ZABBIX USER="zabbix"
ZABBIX PWD="zabbix"
ZABBIX DB="zabbix"
ZABBIX PORT="3306"
ZABBIX HOST="127.0.0.1"
MYSQL BIN="mysql"

#歷史數據保留時間,單位是“天”,讀者可根據實際情況修改
HISTORY DAYS=30

#趨勢數據保留時間,單位是“月”,讀者可根據實際情況修改
TREND MONTHS=12

HISTORY_TABLE="history history_log history_str history_text history_uint"
TREND_TABLE="trends trends_uint"
#MySQL連接命令,如果讀者的MySQL為非標準安裝路徑,可增加--socket=參數
MYSQL_CMD=$(echo ${MYSQL_BIN} -u${ZABBIX_USER} -p${ZABBIX_PWD} -P${ZABBIX_PORT} -h${ZABBIX_HOST} ${ZABBIX_DB})

function create_partitions_history(){
    #給歷史表創建分區
    for PARTITIONS_CREATE_EVERY_DAY in $(date +"%Y%m%d")$(date+"%Y%m%d" --date='1 days')$(date +"%Y%m%d" --date='2 days')$(date+"%Y%m%d" --date='3 days') $(date +"%Y%m%d" --date='4 days')$(date+"%Y%m%d" --date='5 days')$(date +"%Y%m%d" --date='6 days')$(date+"%Y%m%d" --date='7 days')
    do
        TIME_PARTITIONS=$(date -d "$(echo ${PARTITIONS_CREATE_EVERY_DAY}23:59:59)" +%s)
        for TABLE_NAME in ${HISTORY_TABLE}
        do
            SQL1=$(echo "show create table ${TABLE_NAME}; ")
            RET1=$(${MYSQL_CMD} -e "${SQL1}"|grep "PARTITION BY RANGE"|wc -l)
            #表結構中的表分區不存在,創建將表修改為支持分區的表結構
            if [ "${RET1}" == "0" ]; then
                SQL2=$(echo "ALTER TABLE $TABLE_NAME PARTITION BY RANGE(clock)(PARTITION p${PARTITIONS_CREATE_EVERY_DAY}  VALUES LESS THAN(${TIME_PARTITIONS})); ")
                RET2=$(${MYSQL_CMD} -e "${SQL2}")
                if [ "${RET2}" ! = "" ]; then
                    echo  ${RET2}
                    echo "${SQL2}"
                else
                    printf "table %-12s create partitions p${PARTITIONS_CREATE_EVERY_DAY}\n" ${TABLE_NAME}
                fi
                continue
            fi
            #表結構中的表分區已經存在,則可以創建新的分區
            if [ "${RET1}" ! = "0" ]; then
                SQL3=$(echo "show create table ${TABLE_NAME}; ")
                RET3=$(${MYSQL_CMD} -e "${SQL3}"|grep "p${PARTITIONS_CREATE_EVERY_DAY}"|wc -l)
                if["${RET3}"=="0"];then
                    TIME_PARTITIONS=$(date -d "$(echo ${PARTITIONS_CREATE_EVERY_DAY} 23:59:59)" +%s)
                    SQL4=$(echo"ALTERTABLE$TABLE_NAMEADDPARTITION(PARTITIONp${PARTITIONS_CREATE_EVERY_DAY}VALUESLESSTHAN(${TIME_PARTITIONS}));")
                    RET4=$(${MYSQL_CMD} -e "${SQL4}")
                    if["${RET4}"!=""];then
                        echo  ${RET4}
                        echo "${SQL4}"
                    else
                        printf "table %-12s create partitions p${PARTITIONS_CREATE_EVERY_DAY}\n" ${TABLE_NAME}
                    fi
                fi
            fi
        done
    done
}

function drop_partitions_history(){
    #刪除歷史表分區
    for PARTITIONS_DELETE_DAYS_AGO in $(date +"%Y%m%d" --date="${HISTORY_DAYS} days ago")
    do
        for TABLE_NAME in ${HISTORY_TABLE}
        do
            SQL=$(echo-e"showcreatetable${TABLE_NAME};")
            RET=$(${MYSQL_CMD} -e "${SQL}"|grep "p${PARTITIONS_DELETE_DAYS_AGO}"|wc -l)
            if["${RET}"=="1"];then
                SQL=$(echo"ALTERTABLE${TABLE_NAME}DROPPARTITION p${PARTITIONS_DELETE_DAYS_AGO};")
                RET=$(${MYSQL_CMD} -e "${SQL}")
                if["${RET}"!=""];then
                    echo  ${RET}
                    echo "${SQL}"
                else
                    printf "table %-12s drop partitions p${PARTITIONS_DELETE_DAYS_AGO}\n" ${TABLE_NAME}
                fi
            fi
            done
        done
    }

    function create_partitions_trend(){
        #創建趨勢表分區
        for PARTITIONS_CREATE_EVERY_MONTHS in $(date +"%Y%m")$(date +"%Y%m"--date='1  months') $(date  +"%Y%m"  --date='2  months') $(date  +"%Y%m"  --date='3 months')$(date +"%Y%m" --date='4 months')$(date +"%Y%m" --date='5 months')
        do
            TIME_PARTITIONS=$(date -d "$(echo ${PARTITIONS_CREATE_EVERY_MONTHS}01 00:00:00)" +%s)
            for TABLE_NAME in ${TREND_TABLE}
            do
                SQL1=$(echo "show create table ${TABLE_NAME}; ")
                RET1=$(${MYSQL_CMD}-e"${SQL1}"|grep "PARTITION BY RANGE"|wc -l)
                #表結構中的表分區不存在,創建將表修改為支持分區的表結構
                if [ "${RET1}" == "0" ]; then
                    SQL2=$(echo "ALTER TABLE $TABLE_NAME PARTITION BY RANGE(clock)(PARTITION p${PARTITIONS_CREATE_EVERY_MONTHS}  VALUES LESS THAN(${TIME_PARTITIONS})); ")
                    RET2=$(${MYSQL_CMD} -e "${SQL2}")
                    if [ "${RET2}" ! = "" ]; then
                        echo  ${RET2}
                        echo "${SQL2}"
                    else
                        printf "table %-12s create partitions p${PARTITIONS_CREATE_EVERY_MONTHS}\n" ${TABLE_NAME}
                    fi
                    continue
                fi
                #表結構中的表分區已經存在,則可以創建新的分區
                if [ "${RET1}" ! = "0" ]; then
                    SQL3=$(echo "show create table ${TABLE_NAME}; ")
                    RET3=$(${MYSQL_CMD} -e "${SQL3}"|grep "p${PARTITIONS_CREATE_EVERY_MONTHS}"|wc -l)
                    if [ "${RET3}" == "0" ]; then

                        SQL4=$(echo "ALTER TABLE ${TABLE_NAME}  ADD PARTITION(PARTITION p${PARTITIONS_CREATE_EVERY_MONTHS} VALUES LESS THAN(${TIME_PARTITIONS})); ")
                        RET4=$(${MYSQL_CMD} -e "${SQL4}")
                        if [ "${RET4}" ! = "" ]; then
                        echo  ${RET4}
                        echo "${SQL4}"
                    else
                        printf "table %-12s create partitions p${PARTITIONS_CREATE_EVERY_MONTHS}\n" ${TABLE_NAME}
                    fi
                fi
            fi
        done
    done
}

function drop_partitions_trend(){
    #刪除趨勢表分區
    for PARTITIONS_DELETE_MONTHS_AGO in $(date +"%Y%m" --date="${TREND_MONTHS} months ago")
    do
        for TABLE_NAME in ${TREND_TABLE}
        do
            SQL=$(echo "show create table ${TABLE_NAME}; ")
            RET=$(${MYSQL_CMD} -e "${SQL}"|grep "p${PARTITIONS_DELETE_MONTHS_AGO}"|wc -l)
            if [ "${RET}" == "1" ]; then
                SQL=$(echo "ALTER TABLE ${TABLE_NAME} DROP PARTITION p${PARTITIONS_DELETE_MONTHS_AGO}; ")
                RET=$(${MYSQL_CMD} -e "${SQL}")
                if [ "${RET}" ! = "" ]; then
                    echo  ${RET}
                    echo "${SQL}"
                else
                    printf "table %-12s drop partitions p${PARTITIONS_DELETE_MONTHS_AGO}\n" ${TABLE_NAME}
                fi
            fi
        done
    done
}

function main(){
    create_partitions_history
    create_partitions_trend
    drop_partitions_history
    drop_partitions_trend
}
main

注意該腳本在Zabbix 3.0和4.0版本中均測試通過,適用于已經安裝過Zabbix但未進行表分區的數據庫;對于已經在線運行的環境,Zabbix數據庫中的表數據量會比較大,執行此腳本的時間會非常長,筆者測試時遇到過長達10多個小時表分區仍未執行完畢的情況,故建議讀者先清空history、trends表中數據(注意,歷史記錄會全部被清空),再執行。清空語句如下:

mysql> use zabbix;
mysql> truncate table history;
mysql> optimize table history;
mysql> truncate table history_str;
mysql> optimize table history_str;
mysql> truncate table history_uint;
mysql> optimize table history_uint;
mysql> truncate table history_log;
mysql> optimize table history_log;
mysql> truncate table history_text;
mysql> optimize table history_text;
mysql> truncate table trends;
mysql> optimize table trends;
mysql> truncate table trends_uint;
mysql> optimize table trends_uint;

2.運行表分區腳本

為了防止網絡中斷后引起腳本運行中斷而造成數據庫故障,我們應該選用screen后臺執行的方法。如果沒有screen程序,請先安裝(運維人員要處處持有謹慎態度)。

shell# screen  -R  zabbix
shell# sh partitiontables_zabbix.sh
table history      create partitions p20180716
table history_log  create partitions p20180716
table history_str  create partitions p20180716
table history_text create partitions p20180716
table history_uint create partitions p20180716
table history      create partitions p20180717
table history_log  create partitions p20180717
table history_str  create partitions p20180717
table history_text create partitions p20180717
table history_uint create partitions p20180717
#中間省略部分輸出內容
table trends        create partitions p201807
table trends_uint   create partitions p201807
table trends        create partitions p201808
table trends_uint  create partitions p201808

退出screen,腳本將在后臺執行。方法如下:

按“Ctrl+A”組合鍵之后,再按“Ctrl+D”組合鍵。

進入screen,可以查看后臺運行的任務:

shell# screen  -R  zabbix

注意:嚴禁在腳本運行的過程中中斷腳本的運行,否則可能造成表的損壞。腳本運行完畢后,請讀者手動添加定時任務(用于每天創建新的表空間),每天凌晨運行。

shell# crontab -e
1 0 * * * /usr/sbin/partitiontables_zabbix.sh
Shell# chmod 700 /usr/sbin/partitiontables_zabbix.sh

驗證表分區是否成功,可以查看history表結構,輸出如下:

MariaDB [zabbix]> show create table history\G;
*************************** 1. row ***************************
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
/*!50100 PARTITION BY RANGE ( clock)
 (PARTITION p20180716 VALUES LESS THAN (1531756799) ENGINE = InnoDB,
PARTITION p20180717 VALUES LESS THAN (1531843199) ENGINE = InnoDB,
PARTITION p20180718 VALUES LESS THAN (1531929599) ENGINE = InnoDB,
PARTITION p20180719 VALUES LESS THAN (1532015999) ENGINE = InnoDB,
PARTITION p20180720 VALUES LESS THAN (1532102399) ENGINE = InnoDB,
PARTITION p20180721 VALUES LESS THAN (1532188799) ENGINE = InnoDB,
PARTITION p20180722 VALUES LESS THAN (1532275199) ENGINE = InnoDB,
PARTITION p20180723 VALUES LESS THAN (1532361599) ENGINE = InnoDB)*/
/*粗體字部分為表分區*/
1 row in set(0.00 sec)
ERROR: No query specified
MariaDB [zabbix]>

在上面的分區中,時間戳使用的是數值,若需將特定日期轉換為時間戳,則可以通過Linux下的date命令直接進行轉換。

在表分區中,使用的是時間戳格式進行日期區間劃分的,如需將時間轉換為時間戳數值格式,則可以使用如下命令進行轉換:

shell# date -d "2018-07-16" +%s
1531756799

將時間戳數值轉換為時間格式,命令如下:

shell# date -d @1531756799 "+%Y-%m-%d"
2018-07-16

下面的SQL查詢語句用于查詢指定時間段的數據,以驗證數據是否寫入。

mysql> select count(*) from history where clock > 1531670399 and clock<1531756799;
+----------+
| count(*)|
+----------+
|     1356 |
+----------+
1 row in set(0.13 sec)
mysql> select count(*) from history_uint where clock > 1531670399 and clock <1531756799;
+----------+
| count(*)|
+----------+
|   6302   |
+----------+
1 row in set(0.05 sec)

至此,表分區已經完成,這對提高數據庫的性能具有重要的作用。對MySQL的優化還可以通過調整其本身的配置參數來進行。

若讀者想了解更多關于表分區的知識,可以訪問以下地址:

特種奶爸俏老婆林昆楚靜瑤 你是我的命運 最佳女婿大結局 紈绔少爺星域縱橫 天降甜妻:傅少請接招 幸福不脫靶 紅顏亂:狂妃傾天下 官道之權色撩人 仰望 父承

本站所有小說均由搜索引擎轉碼而來,只為讓更多讀者欣賞,本站不保存小說內容及數據,僅作宣傳展示。

Copyright © 2024 噠噠看書網sitemap