首页 > 数据库 >python监控redis主从 双主 VIP切换

python监控redis主从 双主 VIP切换

时间:2023-07-20 20:12:37浏览次数:34  
标签:status slave python redis vip master config 双主

[MySQL]
master_host=
master_port=3306
master_user=root
master_password=
slave_host=
 
 
[DingTalk]
#生产
prod_webhook_url = https://oapi.dingtalk.com/robot/send?access_token=
prod_secret=
#测试
dev_webhook_url= https://oapi.dingtalk.com/robot/send?access_token=
dev_secret=
mobile_number=
 
[Redis]
redis_master_host=
redis_master_port= 6379
redis_master_password = zk123
redis_slave_host=
 
[Code]
mobile_phone_number =
signature_name =
template_code =
master_monitor_address=
slave_monitor_address=
 
[sms]
phonenumbers =
signname =
templatecode =

  

[root@acs-hk-ctos7-prod-01 scripts]# cat monit_vip_redis.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/6/28 17:09
# @Author  : zk_liunx
# @File    : keep_vip.py
# @Software: PyCharm

import os
import time
import re
import redis
import logging
import configparser
import hashlib
import base64
import urllib
import hmac
import requests
import datetime
import socket

logging.basicConfig(level=logging.INFO,
                    filename='/server/scripts/log/keep_vip_drift_mon.log',
                    filemode='a',
                    format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
                    )


def get_digest(secret, timestamp):
    secret_enc = secret.encode('utf-8')
    string_to_sign = '{}\n{}'.format(timestamp, secret)
    string_to_sign_enc = string_to_sign.encode('utf-8')
    hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
    return f"&timestamp={timestamp}&sign={sign}"


class DingTalkConfig:
    def __init__(self, config_file):
        self.config_file = config_file

    def get_config(self):
        config = configparser.ConfigParser()
        config.read(self.config_file)
        return config['DingTalk']



def get_keepalived_vip():
    res = os.popen("ip add|grep 172.31.59.12")
    ip_address = re.search(r'\b(?:\d{1,3}\.){3}\d{1,3}\b', res.read())
    if ip_address:
        keep_vip = ip_address.group()
        return keep_vip




class RedisConfig:
    def __init__(self, config_file):
        self.config_file = config_file

    def get_config(self):
        config = configparser.ConfigParser()
        config.read(self.config_file)
        return config['Redis']


def send_dingtalk_notification(webhook_url, secret, mobile_number, title, msg):
    host_name = socket.gethostname()
    ip_address = socket.gethostbyname(host_name)
    timestamp = str(round(time.time() * 1000))
    msg = "**告警主题**:" + "\n" + title + "\n\n" \
                                           ">当前时间:" + "\n" + datetime.datetime.now().strftime(
        '%Y-%m-%d %H:%M:%S') + "\n\n" \
                               " >当前主机名:" + "\n" + host_name + "\n\n" \
                                                                    " >当前服务器IP:" + "\n" + ip_address + "\n\n" \
                                                                                                            "状态消息:" + "\n" + msg + "\n\n"

    data = {
        "msgtype": "markdown",
        "markdown": {
            "title": title,
            "text": msg,
        },
        "at": {
            "atMobiles": [
                mobile_number
            ],
            "isAtAll": False
        }
    }

    rec = requests.post(webhook_url + get_digest(secret, timestamp), json=data)


class RedisReplicationChecker:
    def __init__(self, master_host, master_port, master_password, redis_slave_host):
        self.master_host = master_host
        self.master_port = master_port
        self.master_password = master_password
        self.slave_host = redis_slave_host

    def check_master_replication(self):
        # 获取主redis状态
        master_connect_redis = redis.Redis(host=self.master_host, port=self.master_port, password=self.master_password)
        master_role_status = master_connect_redis.info()['role']
        # logging.info("当前redis主从状态:{}".format(master_role_status))
        return master_role_status

    def check_slave_replication(self):
        slave_connect_redis = redis.Redis(host=self.slave_host, port=self.master_port, password=self.master_password)
        slave_role_status = slave_connect_redis.info()['role']
        # logging.info("当前redis从状态:{}".format(slave_role_status))
        return slave_role_status


class MonitorRedisVipMasterStatus():
    ALERT_FILE = 'alert_status.txt'

    def get_master_slave_vip_status(self):
        redis_config = RedisConfig('config.ini').get_config()
        checker = RedisReplicationChecker(
            redis_config['redis_master_host'],
            int(redis_config['redis_master_port']),
            redis_config['redis_master_password'],
            redis_config['redis_slave_host']
        )
        master_status = checker.check_master_replication()
        slave_status = checker.check_slave_replication()
        res = get_keepalived_vip()
        return master_status, slave_status, res

    def webhookurl(self):
        dingtalk_config = DingTalkConfig('config.ini').get_config()
        webhook_url = dingtalk_config['prod_webhook_url']
        secret = dingtalk_config['prod_secret']
        mobile_number = dingtalk_config['mobile_number']
        return webhook_url, secret, mobile_number

    def delete_first_line(self, file_name):
        with open(file_name, 'r') as file:
            logging.info("VIP switching notification status deletion")
            lines = file.readlines()

        if lines:
            with open(file_name, 'w') as writ_file:
                writ_file.write(lines.pop(0))
                logging.info("VIP switch notification status has been deleted {}".format(lines))

    def get_status(self):
        master_slave_vip_status = res.get_master_slave_vip_status()
        hook_secret_mobile = res.webhookurl()

        with open(MonitorRedisVipMasterStatus.ALERT_FILE, 'r') as file:
            status = file.read().strip()
        logging.info(master_slave_vip_status[2])
        if not master_slave_vip_status[2]:
            logging.error("Master The current machine VIP does not exist {}.".format(master_slave_vip_status[2]))
            time.sleep(5)
            if master_slave_vip_status[0] == "slave" and master_slave_vip_status[1] == "master":
                logging.info("VIP switch successful")
                print(status)
                if status != "send":
                    time.sleep(5)
                    send_dingtalk_notification(hook_secret_mobile[0], hook_secret_mobile[1], hook_secret_mobile[2],
                                               "Redis VIP切换通知",
                                               '切换后从变更master当前状态:{},切换后从变更主,当前状态:{}'.format(
                                                   master_slave_vip_status[1], [
                                                       master_slave_vip_status[0]]))
                    with open(MonitorRedisVipMasterStatus.ALERT_FILE, 'w') as wr:
                        wr.write('send' + "\n")

                else:
                    logging.info("VIP switch notification has already been sent and is not being sent for the second time")

            elif master_slave_vip_status[0] == "master" and master_slave_vip_status[1] == "master":
                send_dingtalk_notification(hook_secret_mobile[0], hook_secret_mobile[1], hook_secret_mobile[2],
                                           "主从异常-Redis存在双主",
                                           '当前主Redis状态:{},从Redis状态{}'.format(master_slave_vip_status[0], [
                                               master_slave_vip_status[1]]))
                logging.error("Redis synchronization exception, current status dual master")
            elif master_slave_vip_status[0] == "slave" and master_slave_vip_status[1] == "slave":
                send_dingtalk_notification(hook_secret_mobile[0], hook_secret_mobile[1], hook_secret_mobile[2],
                                           "主从异常-Redis存在双从",
                                           '当前主Redis状态:{},从Redis状态:{}'.format(master_slave_vip_status[0], [
                                               master_slave_vip_status[1]]))
                logging.error("Redis synchronization is abnormal, and the current status is from Chinese New Year to Chinese New Year")
        else:
            logging.info("The current VIP has not been switched and remains in the check state")
            res.delete_first_line(MonitorRedisVipMasterStatus.ALERT_FILE)


if __name__ == '__main__':
    res = MonitorRedisVipMasterStatus()
    res.get_status()

  

TRANSLATE with x English
Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian  
  TRANSLATE with COPY THE URL BELOW Back EMBED THE SNIPPET BELOW IN YOUR SITE Enable collaborative features and customize widget: Bing Webmaster Portal Back

标签:status,slave,python,redis,vip,master,config,双主
From: https://www.cnblogs.com/sseban/p/17569535.html

相关文章

  • Python监控Nginx 4、7层健康检查
    [root@acs-hk-ctos7-prod-01scripts]#catupstrem.py#!/usr/bin/envpython#-*-coding:utf-8-*-#@Time:2023/6/2517:18#@File:nginx_upstram.py#@Software:PyCharmimportrequestsfromurllib.requestimporturlopenimportos,socket,datetim......
  • Redis学习(Redis哨兵) 持续更新中
    Redis学习(Redis哨兵)引入:master节点宕机怎么办一个可行的解决办法是:在master节点宕机之后,立刻将一个slave节点变成master节点,之后将恢复后的master节点变为slave节点那么监测和重启该怎么做,这里我们就需要哨兵哨兵的作用和原理哨兵(Sentinel)实现主从集群的自动故障恢复监......
  • Redis集群搭建
    Redis集群是Redis提供的一种高可用性和容错性解决方案,它通过将数据分片存储在多个节点上来实现数据的自动分布和负载均衡。要搭建Redis集群,可以按照以下步骤进行操作。一、准备服务器这以3台服务器为例,分别192.168.3.100 node1192.168.3.102 node3192.168.3.103 node2......
  • Python基础day49
    overflow溢出属性值描述visible默认值。内容不会被修剪,会呈现在元素框之外hidden内容会被修剪,并且其余内容是不可见的scroll内容会被修剪,但是浏览器会显示滚动条以便查看其余的内容auto如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容inherit规定......
  • PYTHON 没有实体类做修改
    PYTHON没有实体类做修改在Python中,我们经常需要对数据进行操作和修改。有时候,我们可能需要修改一个已经存在的数据对象,或者需要创建一个新的数据对象来存储修改后的数据。在其他编程语言中,通常会使用实体类来实现这些操作。实体类是一个包含属性和方法的数据结构,可以用来表示现实......
  • Linux python 查找模块和版本号
    LinuxPython查找模块和版本号作为一名经验丰富的开发者,你需要教会一位刚入行的小白如何在Linux环境下使用Python查找模块和版本号。以下是一份详细的步骤和相应的代码注释,帮助他完成这个任务。步骤步骤描述步骤一打开终端步骤二运行Python交互式解释器步骤三......
  • Redis的五大数据类型及其使用场景
    前言redis是一个非常快速‎‎的非关系数据库‎‎解决方案。其简单的键值数据模型使Redis能够处理大型数据集,同时保持令人印象深刻的读写速度和可用性。‎redis提供了五种数据类型,分别是是:1、string(字符串);2、hash(哈希);3、list(列表);4、set(集合);5、sortset(有序集合)(其实随着Redis......
  • Redissonclient怎么添加数据
    Redisson是一个基于Redis的分布式Java对象和服务的框架。RedissonClient是Redisson的主要接口之一,用于与Redis进行交互。要添加数据到Redis中,可以使用RedissonClient提供的多种方法,包括常见的数据结构如字符串、列表、集合、有序集合和哈希表等。首先,我们需要在项目中添加Redisson......
  • RedisTemplate 泛型不同 指向的是同一个实例吗
    RedisTemplate泛型不同指向的是同一个实例吗在使用RedisTemplate时,我们经常会遇到需要指定不同数据类型的情况。比如,我们可能需要将某个对象存储到Redis中,并且需要使用不同的数据类型进行序列化和反序列化。那么,RedisTemplate在这种情况下会创建多个实例吗?本文将解答这个问......
  • RedisSubscriber redis
    RedisSubscriber:一个订阅者模式的简介在分布式系统中,订阅者模式是一种非常有用的设计模式,它能够帮助我们实现消息的发布与订阅。Redis作为一种流行的内存数据库,其中的发布-订阅机制使得实现订阅者模式变得非常简单。什么是RedisSubscriberRedisSubscriber是一个Redis客户端库,......