Python脚本如何监控数据同步延迟状态

wen python案例 29

本文目录导读:

Python脚本如何监控数据同步延迟状态

  1. MySQL主从复制延迟监控
  2. Redis主从延迟监控
  3. 通用数据同步延迟监控
  4. 带告警功能的监控器
  5. 使用方法

我来为你提供几个监控数据同步延迟的Python脚本方案:

MySQL主从复制延迟监控

import pymysql
import time
from datetime import datetime
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, 
                   format='%(asctime)s - %(levelname)s - %(message)s')
class MySQLReplicationMonitor:
    def __init__(self, host, user, password, port=3306):
        self.config = {
            'host': host,
            'user': user,
            'password': password,
            'port': port
        }
    def get_replication_delay(self):
        """获取主从复制延迟"""
        try:
            conn = pymysql.connect(**self.config)
            cursor = conn.cursor()
            # 检查从库状态
            cursor.execute("SHOW SLAVE STATUS")
            slave_status = cursor.fetchone()
            if slave_status:
                # Seconds_Behind_Master 是延迟秒数
                seconds_behind = slave_status[32]  # 第33个字段
                return {
                    'delay_seconds': seconds_behind or 0,
                    'slave_io_running': slave_status[10],  # Slave_IO_Running
                    'slave_sql_running': slave_status[11], # Slave_SQL_Running
                    'last_error': slave_status[19]         # Last_Error
                }
            else:
                return None
        except Exception as e:
            logging.error(f"获取复制延迟失败: {e}")
            return None
        finally:
            if 'conn' in locals():
                conn.close()
    def monitor(self, interval=5, threshold=60):
        """持续监控复制延迟"""
        logging.info("开始监控MySQL主从复制延迟...")
        while True:
            status = self.get_replication_delay()
            if status:
                delay = status['delay_seconds']
                if delay > threshold:
                    logging.warning(f"复制延迟过高: {delay}秒")
                    if status['slave_io_running'] != 'Yes':
                        logging.error("Slave IO线程停止运行")
                    if status['slave_sql_running'] != 'Yes':
                        logging.error("Slave SQL线程停止运行")
                else:
                    logging.info(f"复制延迟正常: {delay}秒")
            else:
                logging.warning("无法获取复制状态")
            time.sleep(interval)
# 使用示例
monitor = MySQLReplicationMonitor(
    host='10.0.0.2',  # 从库地址
    user='repl_user',
    password='password'
)
monitor.monitor(interval=10, threshold=30)

Redis主从延迟监控

import redis
import time
import logging
logging.basicConfig(level=logging.INFO, 
                   format='%(asctime)s - %(levelname)s - %(message)s')
class RedisReplicationMonitor:
    def __init__(self, host='localhost', port=6379, password=None):
        self.redis_client = redis.Redis(
            host=host,
            port=port,
            password=password,
            decode_responses=True
        )
    def get_replication_delay(self):
        """获取Redis主从复制延迟"""
        try:
            # 从库使用 info replication 命令
            info = self.redis_client.info('replication')
            if info['role'] == 'slave':
                # master_last_io_seconds_ago 表示上次与主库通信的秒数
                delay = info.get('master_last_io_seconds_ago', 0)
                # 计算复制积压量
                master_repl_offset = info.get('master_repl_offset', 0)
                slave_repl_offset = info.get('slave_repl_offset', 0)
                replication_gap = master_repl_offset - slave_repl_offset
                return {
                    'role': 'slave',
                    'delay_seconds': delay,
                    'master_link_status': info.get('master_link_status', 'down'),
                    'replication_gap': replication_gap,
                    'master_host': info.get('master_host', 'unknown')
                }
            else:
                return {'role': 'master', 'connected_slaves': info.get('connected_slaves', 0)}
        except Exception as e:
            logging.error(f"获取Redis复制状态失败: {e}")
            return None
    def monitor(self, interval=5, threshold=10):
        """持续监控复制延迟"""
        logging.info("开始监控Redis主从复制延迟...")
        while True:
            status = self.get_replication_delay()
            if status and status.get('role') == 'slave':
                delay = status['delay_seconds']
                if delay > threshold:
                    logging.warning(f"Redis复制延迟: {delay}秒, "
                                  f"复制gap: {status['replication_gap']}字节")
                    if status['master_link_status'] != 'up':
                        logging.error("Redis主从连接断开")
                else:
                    logging.info(f"Redis复制正常: {delay}秒")
            time.sleep(interval)
# 使用示例
monitor = RedisReplicationMonitor(
    host='10.0.0.3',  # 从库地址
    port=6379
)
monitor.monitor(interval=10, threshold=5)

通用数据同步延迟监控

import requests
import time
import json
from datetime import datetime
import hashlib
class DataSyncMonitor:
    def __init__(self, source_api, target_api):
        self.source_api = source_api
        self.target_api = target_api
    def get_latest_record(self, api_url, table_name):
        """获取指定表的最新记录"""
        try:
            response = requests.get(
                f"{api_url}/latest/{table_name}",
                timeout=5
            )
            if response.status_code == 200:
                return response.json()
            return None
        except Exception as e:
            print(f"获取记录失败: {e}")
            return None
    def calculate_delay(self, source_time, target_time):
        """计算同步延迟时间"""
        if source_time and target_time:
            s_time = datetime.fromisoformat(source_time.replace('Z', '+00:00'))
            t_time = datetime.fromisoformat(target_time.replace('Z', '+00:00'))
            delay = (s_time - t_time).total_seconds()
            return max(0, delay)
        return -1
    def check_data_integrity(self, source_data, target_data):
        """检查数据完整性"""
        if not source_data or not target_data:
            return False, "数据不存在"
        source_hash = hashlib.md5(
            json.dumps(source_data, sort_keys=True).encode()
        ).hexdigest()
        target_hash = hashlib.md5(
            json.dumps(target_data, sort_keys=True).encode()
        ).hexdigest()
        if source_hash != target_hash:
            return False, "数据不一致"
        return True, "数据一致"
    def monitor_table(self, table_name, interval=30):
        """监控指定表的同步状态"""
        while True:
            source_record = self.get_latest_record(self.source_api, table_name)
            target_record = self.get_latest_record(self.target_api, table_name)
            if source_record and target_record:
                # 计算时间延迟
                delay = self.calculate_delay(
                    source_record.get('update_time'),
                    target_record.get('update_time')
                )
                # 检查数据完整性
                is_integrity, integrity_msg = self.check_data_integrity(
                    source_record, target_record
                )
                print(f"[{datetime.now()}] 表: {table_name}")
                print(f"  数据延迟: {delay}秒")
                print(f"  数据完整性: {integrity_msg}")
                if delay > 60:
                    print(f"  ⚠️ 警告: 同步延迟超过1分钟!")
            else:
                print(f"[{datetime.now()}] 无法获取源或目标数据")
            time.sleep(interval)
# 使用示例
monitor = DataSyncMonitor(
    source_api='http://source-system:8000/api',
    target_api='http://target-system:8000/api'
)
monitor.monitor_table('orders', interval=60)

带告警功能的监控器

import smtplib
from email.mime.text import MIMEText
import requests
import time
class AlertSyncMonitor:
    def __init__(self, alert_config):
        self.alert_config = alert_config
        self.alert_thresholds = {
            'critical': 300,  # 5分钟
            'warning': 60     # 1分钟
        }
    def send_email_alert(self, subject, message):
        """发送邮件告警"""
        msg = MIMEText(message)
        msg['Subject'] = subject
        msg['From'] = self.alert_config['email_from']
        msg['To'] = self.alert_config['email_to']
        try:
            with smtplib.SMTP(self.alert_config['smtp_server'], 
                             self.alert_config['smtp_port']) as server:
                server.starttls()
                server.login(
                    self.alert_config['email_user'],
                    self.alert_config['email_password']
                )
                server.send_message(msg)
        except Exception as e:
            print(f"发送邮件告警失败: {e}")
    def send_dingtalk_alert(self, message):
        """发送钉钉告警"""
        webhook_url = self.alert_config.get('dingtalk_webhook')
        if webhook_url:
            data = {
                "msgtype": "text",
                "text": {"content": message}
            }
            requests.post(webhook_url, json=data)
    def check_and_alert(self, delay, component_name):
        """检查延迟并发送告警"""
        if delay >= self.alert_thresholds['critical']:
            message = f"严重告警: {component_name}同步延迟 {delay}秒"
            self.send_email_alert(f"[CRITICAL] {component_name}延迟告警", message)
            self.send_dingtalk_alert(message)
            print(message)
        elif delay >= self.alert_thresholds['warning']:
            message = f"警告: {component_name}同步延迟 {delay}秒"
            print(message)
# 使用示例
alert_config = {
    'email_from': 'monitor@example.com',
    'email_to': 'admin@example.com',
    'smtp_server': 'smtp.example.com',
    'smtp_port': 587,
    'email_user': 'monitor@example.com',
    'email_password': 'password',
    'dingtalk_webhook': 'https://oapi.dingtalk.com/robot/send?access_token=xxxx'
}
monitor = AlertSyncMonitor(alert_config)
monitor.check_and_alert(120, "MySQL复制")

使用方法

  1. 安装依赖

    pip install pymysql redis requests
  2. 选择合适的监控方案

    • MySQL从库:使用方案1
    • Redis主从:使用方案2
    • 自定义数据同步:使用方案3
    • 需要告警功能:整合方案4
  3. 作为后台服务运行

    nohup python mysql_monitor.py > monitor.log 2>&1 &

这些脚本可以根据你的具体需求进行修改和扩展,比如添加更多的监控指标、集成不同的告警渠道等。

抱歉,评论功能暂时关闭!