1. 程式人生 > >MySQL至TiDB複製延遲監控

MySQL至TiDB複製延遲監控

因生產環境mysql中有較多複雜sql且執行效率低,因此採用tidb作為生產環境的從庫進行部分慢sql及報表的讀寫分離。其中MySQL至TIDB採用Syncer工具同步。
關於TIDB的安裝及Syncer可參照官網指引進行,搭建的主從複製架構如下:

因該方式中TiDB的資料是通過Syncer同步的,且TIDB無show slave status命令檢視複製情況,故自己開發指令碼對MySQL至TIDB的複製延遲進行監控,並且將結果進行圖形化展示以便於直觀分析,而且此方法也可以監控MySQL主從延遲,類似於percona toolkit的pt-heartbeat 。

一、 準備工作
1. 監控所需工具
監控

:Python 2.7及以上,安裝pymysql(或MySQLdb),其中linux升級python及pip安裝可參考之前的博文

圖形化展示:Python plotly、matplotlib或pandas包

2. 監控延遲思路
1)建立監控資料庫(monitor)及相關表(monitor_time,monitor_result)
2)每隔固定時間(看監控精確度,如0.5s)將當期時間或時間戳的結果更新到mysql的監控表中
3)對比mysql與tidb對應的監控庫(monitor庫)中的monitor_time表的時間差,並將結果記錄在monitor_result裡

3. 視覺化展示結果
用Python 的plotly、matplotlib或pandas等展示監控結果

二、延時監控實施步驟

1. 建立資料庫及相關表,並將其加入Syncer同步中

-- 建立監控資料庫monitor;
CREATE DATABASE  `monitor`;

USE `monitor`;

-- 建立監控時間表monitor_time;
CREATE TABLE `monitor_time` (
  `t` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 初始化資料,因後面監控程式定時更新該條記錄 
insert into monitor_time  select 1;

-- 建立監控結果表monitor_result;
CREATE TABLE `monitor_result` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `t` int(11) DEFAULT NULL COMMENT '延遲時間', `add_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '監控記錄生成時間', `t_mysql` int(11) DEFAULT NULL COMMENT 'mysql主從延遲時長', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2. 建立監控賬號並授權
單獨建立一個用於監控該延遲的賬號,並新增相應的許可權。

CREATE USER [email protected]'192.168.3.42' IDENTIFIED BY 'monitor';
GRANT  SELECT ,INSERT ,UPDATE ON monitor.* TO [email protected]'192.168.3.42';

3. 監控指令碼

每隔0.5s更新一次monitor_time 表,自定義時間(如例子中10s)獲取一次監控結果,並將記錄寫入資料庫中

import os,time
import pymysql

while True:
        t = time.time()
        t1= int(round(t * 1000))
        conn = pymysql.connect(host='*.*.*.*',port=3306,user='monitor',passwd='monitor')
        cur = conn.cursor()
        sql_update = "update monitor.monitor_time set t="+str(t1)
        cur.execute(sql_update)
        conn.commit()
        conn.close()
        time.sleep(0.5)
import os,time
import pymysql


while True:
        conn_sor = pymysql.connect(host='*.*.*.*',port=3306,user='monitor',passwd='monitor')
        cur_sor = conn_sor.cursor()
        conn_138 = pymysql.connect(host='*.*.*.*',port=3306,user='monitor',passwd='monitor')
        cur_138 = conn_138.cursor()
        conn_des = pymysql.connect(host='*.*.*.*',port=4000,user='monitor',passwd='monitor')
        cur_des = conn_des.cursor()
        sql_get_time = "select t from  monitor.monitor_time "

        cur_sor.execute(sql_get_time)
        v_src_tuple=cur_sor.fetchone()
        t_sor=v_src_tuple[0]


        cur_des.execute(sql_get_time)
        v_des_tuple=cur_des.fetchone()
        t_des=v_des_tuple[0]

        cur_138.execute(sql_get_time)
        v_138_tuple=cur_138.fetchone()
        t_138=v_138_tuple[0]

        t1 = t_sor/1000 - t_des/1000
        t2 = t_sor/1000 - t_138/1000
        sql_insert = "insert into  monitor.monitor_result(t,t_mysql) select "+str(t1)+","+str(t2)
        cur_sor.execute(sql_insert)
        conn_sor.commit()


        conn_sor.close()
        conn_des.close()
        time.sleep(10)

將2個指令碼放在監控伺服器上執行

python monitor_tidb.py  &
python get_tidb_delay.py  &

 三 視覺化展示

以下是其中一種實現方式,其他如折線圖方式可執行修改

# __author__ : 'GJC'
# __created__ : '2018/9/17'
# coding=utf-8

import pymysql
import plotly.plotly
from plotly.graph_objs import *
import plotly.graph_objs as abc
import matplotlib.pyplot as plt

host = "*.*.*.*"
user = "monitor"
passwd = "monitor"
db = "monitor"
port = 3306
charset = "utf8"

conn = pymysql.connect(
    host=host,
    port=port,
    user=user,
    passwd=passwd,
    db=db,
    charset=charset,
)

cur = conn.cursor()

re = cur.execute("SELECT  add_time,t,t_mysql FROM  monitor.monitor_result_t ")

dfs = cur.fetchall()
listx = []
listy = []
listy2 = []
for row in dfs:
    listx.append(row[0])
    listy.append(row[1])
    listy2.append(row[2])

cur.close()
conn.commit()
conn.close()

length = listy.__len__()

data_1 = abc.Scatter(
    x=listx,
    y=listy,
    name='syncer_delay_time_tidb',
    mode='markers',
    marker=dict(
        size=10,
        color="rgba(255,47,167,.9)",
        line=dict(
            width=2,
            color='rgb(2,2,2)'
        )
    )
)

data_2 = abc.Scatter(
    x=listx,
    y=listy2,
    name='syncer_delay_time_mysql',
    mode='markers',
    marker=dict(
        size=10,
        color="rgba(255,47,167,.9)",
        line=dict(
            width=2,
            color='rgb(3,3,3)'
        )
    )
)
data1 = Data([data_1])
plotly.offline.plot(data1)

data2 = Data([data_2])
plotly.offline.plot(data2)

部分時間段效果如下: