MHA高可用

manager 组件
masterha_manger             # 启动MHA 
masterha_check_ssh      	  # 检查MHA的SSH配置状况 
masterha_check_repl         # 检查MySQL复制状况,配置信息
masterha_master_monitor     # 检测master是否宕机 
masterha_check_status       # 检测当前MHA运行状态 
masterha_master_switch     	# 控制故障转移(自动或者手动)
masterha_conf_host      	  # 添加或删除配置的server信息node 组件
save_binary_logs            # 保存和复制master的二进制日志 
apply_diff_relay_logs       # 识别差异的中继日志事件并将其差异的事件应用于其他的
purge_relay_logs            # 清除中继日志(不会阻塞SQL线程)

MHA在发生切换的过程中,从库的恢复过程中依赖于relay log的相关信息,所以这里要将relay log的自动清除设置为OFF,采用手动清除relay log的方式。在默认情况下,从服务器上的中继日志会在SQL线程执行完毕后被自动删除。但是在MHA环境中,这些中继日志在恢复其他从服务器时可能会被用到,因此需要禁用中继日志的自动删除功能。定期清除中继日志需要考虑到复制延时的问题。在ext3的文件系统下,删除大的文件需要一定的时间,会导致严重的复制延时。为了避免复制延时,需要暂时为中继日志创建硬链接,因为在linux系统中通过硬链接删除大文件速度会很快。(在mysql数据库中,删除大表时,通常也采用建立硬链接的方式)

MHA节点中包含了pure_relay_logs命令工具,它可以为中继日志创建硬链接,执行SET GLOBAL relay_log_purge=1,等待几秒钟以便SQL线程切换到新的中继日志,再执行SET GLOBAL relay_log_purge=0。

pure_relay_logs脚本参数如下所示:

--user mysql                      用户名
--password mysql                  密码
--port                            端口号
--workdir                         指定创建relay log的硬链接的位置,默认是/var/tmp,由于系统不同分区创建硬链接文件会失败,故需要执行硬链接具体位置,成功执行脚本后,硬链接的中继日志文件被删除
--disable_relay_log_purge         默认情况下,如果relay_log_purge=1,脚本会什么都不清理,自动退出,通过设定这个参数,当relay_log_purge=1
[root@192.168.0.60 ~]# cat purge_relay_log.sh 
#!/bin/bash
user=root
passwd=123456
port=3306
log_dir='/data/masterha/log'
work_dir='/data'
purge='/usr/local/bin/purge_relay_logs'if [ ! -d $log_dir ]
thenmkdir $log_dir -p
fi$purge --user=$user --password=$passwd --disable_relay_log_purge --port=$port --workdir=$work_dir >> $log_dir/purge_relay_logs.log 2>&1
[root@192.168.0.60 ~]#
#!/bin/sh
BACKUP_BIN=/usr/local/mysql/bin/mysqlbinlog
LOCAL_BACKUP_DIR=/data/backup/binlog_bk
BACKUP_LOG=/data/backup/bakbinlog.log
REMOTE_HOST=192.168.56.100
#REMOTE_PORT=3306
SERVER_ID=20003306
REMOTE_USER=wanbin
REMOTE_PASS=mysql
#time to wait before reconnecting after failure
SLEEP_SECONDS=10
##create local_backup_dir if necessary
##mkdir -p ${LOCAL_BACKUP_DIR}
cd ${LOCAL_BACKUP_DIR}
## 运行while循环,连接断开后等待指定时间,重新连接
while :
FIRST_BINLOG=$(mysql --host=${REMOTE_HOST} --user=${REMOTE_USER} --password=${REMOTE_PASS} -e 'show binary logs'|grep -v "Log_name"|awk '{print $1}'|head -n 1)
doif [ `ls -A "${LOCAL_BACKUP_DIR}" |wc -l` -eq 0 ];thenLAST_FILE=${FIRST_BINLOG} ##如果备份目录中没有备份文件则 LAST_FILE=FIRST_FILEelseLAST_FILE=`ls -l ${LOCAL_BACKUP_DIR} |tail -n 1 |awk '{print $9}'` ##last_file取序列最大的binlog文件fi${BACKUP_BIN} -R --raw --host=${REMOTE_HOST} --user=${REMOTE_USER} --password=${REMOTE_PASS} ${LAST_FILE} --stop-never --stop-never-slave-server-id=${SERVER_ID} echo "`date +"%Y/%m/%d %H:%M:%S"` mysqlbinlog停止,返回代码:$?" | tee -a ${BACKUP_LOG}echo "${SLEEP_SECONDS}秒后再次连接并继续备份" | tee -a ${BACKUP_LOG}  sleep ${SLEEP_SECONDS}
done
#!/bin/bash[ -e /etc/profile ] && source /etc/profile || exit 0#本地binlog路径local_binlog_dir=/data/3306/247binlog[ ! -d "$local_binlog_dir" ] && mkdir -p "$local_binlog_dir"cd "$local_binlog_dir"#远程服务器ssh端口ssh_port=22#远程服务器ipremote_host=192.168.0.68#本地binlog文件名local_logfile=`ls -al "$local_binlog_dir" | grep 'mysql-bin\.[0-9]\+' |tail -n 1 | awk '{print $NF}'`#远程服务器binlog路径remote_binlog_dir=/data/mysql3306/#远程服务器第一个binlog文件名first_remote_lofile=`ssh -p ${ssh_port} -o StrictHostKeyChecking=no ${remote_host} " cat \${remote_binlog_dir}/mysql-bin.index | head -n 1 | awk -F'/' '{print \\$NF}'"`last_remote_logfile=`ssh -p ${ssh_port} -o StrictHostKeyChecking=no ${remote_host} " cat \${remote_binlog_dir}/mysql-bin.index | tail -n 1 | awk -F'/' '{print \\$NF}'"`#远程mysql用户remote_user=root#远程mysql用户密码remote_password=xxfunction start() {
running=`ps uax | grep 'mysqlbinlog -R --raw' | grep -v grep|grep raw | awk '{print $2}'`if [ "$running" != "" ];thenecho "mysqlbinlog server is running"exitfiif [ "$local_logfile" == "" ];then#echo "the binlogserver is first start "mysqlbinlog -R --raw --host=$remote_host --user="$remote_user" --password="$remote_password" --stop-never  $first_remote_lofile &elseif ! ssh -p ${ssh_port} -o StrictHostKeyChecking=no ${remote_host} "ls -lh ${remote_binlog_dir}/${local_logfile}" &> /dev/null;thenlocal_logfile_num=`ll /data/3306/247binlog/ |tail -1 |awk '{print $NF}' |grep -o '[1?9][1?9]\+[0?9][0?9]\+'`binlogs=(`ssh -p ${ssh_port} -o StrictHostKeyChecking=no ${remote_host} "ls -lh ${remote_binlog_dir}/mysql-bin.* |grep -v index |awk -F'/' '{print \\$NF}' |wc -l"`)for binlog in `seq 1 $binlogs`dolocal_logfile_num=`expr $local_logfile_num + 1`if [ "$local_logfile_num" -lt 10 ];thenlocal_logfile=mysql-bin.00000${local_logfile_num}elif [ "$local_logfile_num" -lt 100 ];thenlocal_logfile=mysql-bin.0000${local_logfile_num}elif [ "$local_logfile_num" -lt 1000 ];thenlocal_logfile=mysql-bin.000${local_logfile_num}elif [ "$local_logfile_num" -lt 10000 ];thenlocal_logfile=mysql-bin.00${local_logfile_num}elif [ "$local_logfile_num" -lt 100000 ];thenlocal_logfile=mysql-bin.0${local_logfile_num}elselocal_logfile=mysql-bin.${local_logfile_num}fiif ssh -p ${ssh_port} -o StrictHostKeyChecking=no ${remote_host} "ls -lh ${remote_binlog_dir}/${local_logfile}" &> /dev/null;thenbreakfidonemysqlbinlog -R --raw --host=$remote_host --user="$remote_user" --password="$remote_password" --stop-never  $local_logfile &elsemysqlbinlog -R --raw --host=$remote_host --user="$remote_user" --password="$remote_password" --stop-never  $local_logfile &fifi}function stop() {
ps uax | grep mysqlbinlog | grep raw | awk '{print $2}' | xargs kill}case $1 instart)start;;stop)stop;;*)# usagebasename=`basename "$0"`echo "Usage: $basename  {start|stop}  [ MySQL BinlogServer options ]"exit 1;;esac

 

 

 

Phase 1: Configuration Check Phase
init_config(): 初始化配置
MHA::ServerManager::init_binlog_server: 初始化binlog server
check_settings()
    a. check_node_version(): 查看MHA的版本
    b. connect_all_and_read_server_status(): 检测确认各个Node节点MySQL是否可以连接
    c. get_dead_servers(),get_alive_servers(),get_alive_slaves():再次检测一次node节点的状态
    d. print_dead_servers(): 是否挂掉的master是否是当前的master
    e. MHA::DBHelper::check_connection_fast_util : 快速判断dead server,是否真的挂了,如果ping_type=insert,不会double check
    f. MHA::NodeUtil::drop_file_if($_failover_error_file|$_failover_complete_file): 检测上次的failover文件
    g. 如果上次failover的时间在8小时以内,那么这次就不会failover,除非配置了额外的参数
    h. start_sql_threads_if(): 查看所有slave的Slave_SQL_Running是否为Yes,若不是则启动SQL thread
    is_gtid_auto_pos_enabled(): 判断是否是GTID模式
Phase 2: Dead Master Shutdown Phase..
    force_shutdown($dead_master):
    a. stop_io_thread(): stop所有slave的IO_thread
    b. force_shutdown_internal($dead_master):
          b_1. master_ip_failover_script: 如果有这个脚本,则执行里面的逻辑(比如:切换vip)
          b_2. shutdown_script:如果有这个脚本,则执行里面的逻辑(比如:Power off 服务器)
Phase 3: Master Recovery Phase..
    Phase 3.1: Getting Latest Slaves Phase..
    * check_set_latest_slaves()
          a. read_slave_status(): 获取所有show slave status 信息
          b. identify_latest_slaves(): 找到最新的slave是哪个
          c. identify_oldest_slaves(): 找到最老的slave是哪个
    Phase 3.2: Saving Dead Master's Binlog Phase..
        * save_master_binlog($dead_master);
          -> 如果dead master可以ssh,那么
               b_1_1. save_master_binlog_internal: 用node节点save_binary_logs脚本拷贝相应binlog到manager
                   diff_binary_log 生产差异binlog日志
               b_1_2. file_copy: 将差异binlog拷贝到manager节点的 manager_workdir目录下
          -> 如果dead master不可以ssh
               b_1_3. 那么差异日志就会丢失
    Phase 3.3: Determining New Master Phase..
    b. 如果GTID auto_pos没有打开,调用find_latest_base_slave()
        b_1. find_latest_base_slave_internal: 寻找拥有所有relay-log的最新slave,如果没有,则failover失败
                b_1_1. find_slave_with_all_relay_logs:
                        b_1_1_1. apply_diff_relay_logs: 查看最新的slave是否有其他slave缺失的relay-log
    
    c. select_new_master: 选举new master
        c_1. MHA::ServerManager::select_new_master:
           #If preferred node is specified, one of active preferred nodes will be new master.
           #If the latest server behinds too much (i.e. stopping sql thread for online backups), we should not use it as a new master, but we should fetch relay log there
           #Even though preferred master is configured, it does not become a master if it's far behind
    
           get_candidate_masters(): 获取配置中候选节点
           get_bad_candidate_masters(): 以下条件不能成为候选master
               # dead server
               # no_master >= 1
               # log_bin=0
               # oldest_major_version=0
               # check_slave_delay: 检查是否延迟非常厉害(可以通过设置no_check_delay忽略)
                   {Exec_Master_Log_Pos} + 100000000 只要binlog position不超过100000000 就行
           选举流程: 先看candidate_master,然后找 latest slave, 然后再随机挑选
    Phase 3.3(3.4): New Master Diff Log Generation Phase..
    * recover_master_internal
             recover_relay_logs:
                   判断new master是否为最新的slave,如果不是,则生产差异relay logs,并发送给新master
             recover_master_internal:
                   将之前生产的dead master上的binlog传送给new master
    Phase 3.4: Master Log Apply Phase..
    * apply_diff:
           a. wait_until_relay_log_applied: 直到new master完成所有relay log,否则一直等待
           b. 判断Exec_Master_Log_Pos == Read_Master_Log_Pos, 如果不等,那么生产差异日志:
                       save_binary_logs --command=save
           c. apply_diff_relay_logs --command=apply:对new master进行恢复
                       c_1. exec_diff:Exec_Master_Log_Pos和Read_Master_Log_Pos的差异日志
                       c_2. read_diff:new master与lastest slave的relay log的差异日志
                       c_3. binlog_diff:lastest slave与daed master之间的binlog差异日志
    * 如果设置了master_ip_failover_script脚本,那么会执行这里面的脚本(一般用来漂移vip)
    
    * disable_read_only(): 允许new master可写
Phase 4: Slaves Recovery Phase..
    recover_slaves_internal
    
    Phase 4.1: Starting Parallel Slave Diff Log Generation Phase..
        recover_all_slaves_relay_logs: 生成Slave与New Slave之间的差异日志,并将该日志拷贝到各Slave的工作目录下
    Phase 4.2: Starting Parallel Slave Log Apply Phase..
        * recover_slave:
            对每个slave进行恢复,跟以上Phase 3.4: Master Log Apply Phase中的 apply_diff一样
        * change_master_and_start_slave:
            重新指向到new master,并且start slave
Phase 5: New master cleanup phase..
    reset_slave_on_new_master
    在new master上执行reset slave all;

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    Phase 1: Configuration Check Phase
    init_config(): 初始化配置
    MHA::ServerManager::init_binlog_server: 初始化binlog server
    check_settings()
        a. check_node_version(): 查看MHA的版本
        b. connect_all_and_read_server_status(): 检测确认各个Node节点MySQL是否可以连接
        c. get_dead_servers(),get_alive_servers(),get_alive_slaves():再次检测一次node节点的状态
        d. print_dead_servers(): 是否挂掉的master是否是当前的master
        e. MHA::DBHelper::check_connection_fast_util : 快速判断dead server,是否真的挂了,如果ping_type=insert,不会double check
        f. MHA::NodeUtil::drop_file_if($_failover_error_file|$_failover_complete_file): 检测上次的failover文件
        g. 如果上次failover的时间在8小时以内,那么这次就不会failover,除非配置了额外的参数
        h. start_sql_threads_if(): 查看所有slave的Slave_SQL_Running是否为Yes,若不是则启动SQL thread
    is_gtid_auto_pos_enabled(): 判断是否是GTID模式
Phase 2: Dead Master Shutdown Phase completed.
    force_shutdown($dead_master):
        a. stop_io_thread(): stop所有slave的IO_thread
        b. force_shutdown_internal($dead_master):
          b_1. master_ip_failover_script: 如果有这个脚本,则执行里面的逻辑(比如:切换vip)
          b_2. shutdown_script:如果有这个脚本,则执行里面的逻辑(比如:Power off 服务器)
Phase 3: Master Recovery Phase..
    Phase 3.1: Getting Latest Slaves Phase..
        * check_set_latest_slaves()
              a. read_slave_status(): 获取所有show slave status 信息
              b. identify_latest_slaves(): 找到最新的slave是哪个
              c. identify_oldest_slaves(): 找到最老的slave是哪个
    Phase 3.2: Saving Dead Master's Binlog Phase.. (GTID 模式下没有这一步)
    Phase 3.3: Determining New Master Phase..
        get_most_advanced_latest_slave(): 获取最新的slave
    
    c. select_new_master: 选举new master
        c_1. MHA::ServerManager::select_new_master:
           #If preferred node is specified, one of active preferred nodes will be new master.
           #If the latest server behinds too much (i.e. stopping sql thread for online backups), we should not use it as a new master, but we should fetch relay log there
           #Even though preferred master is configured, it does not become a master if it's far behind
    
           get_candidate_masters(): 获取配置中候选节点
           get_bad_candidate_masters(): 以下条件不能成为候选master
               # dead server
               # no_master >= 1
               # log_bin=0
               # oldest_major_version=0
               # check_slave_delay: 检查是否延迟非常厉害(可以通过设置no_check_delay忽略)
                   {Exec_Master_Log_Pos} + 100000000 只要binlog position不超过100000000 就行
           选举流程: 先看candidate_master,然后找 latest slave, 然后再随机挑选
    
    Phase 3.3: New Master Recovery Phase..
        * recover_master_gtid_internal:
            wait_until_relay_log_applied: 候选master等待所有relay-log都应用完
            如果候选master不是最新的slave:
                $latest_slave->wait_until_relay_log_applied($log): 最新的slave应用完所有的relay-log
                change_master_and_start_slave : 让候选master同步到latest master,追上latest slave
                获取候选master此时此刻的日志信息,以便后面切换
            如果候选master是最新的slave:
                获取候选master此时此刻的日志信息,以便后面切换
            save_from_binlog_server:
                如果配置了binlog server,那么在binlogsever 能连的情况下,将binlog 拷贝到Manager,并生成差异日志diff_binlog(save_binary_logs --command=save)
            apply_binlog_to_master:
                Applying differential binlog: 应用差异的binlog到new master

Phase 4: Slaves Recovery Phase..
    Phase 4.1: Starting Slaves in parallel..
        * recover_slaves_gtid_internal:
            change_master_and_start_slave: 因为master已经恢复,那么slave直接change master auto_pos=1 的模式就可以恢复
            gtid_wait:用此等待同步全部追上
Phase 5: New master cleanup phase..
    reset_slave_on_new_master
    在new master上执行reset slave all;
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/535325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL Replication需要注意的问题

主库意外宕机 如果没有设置主库的sync_binlog选项,就可能在奔溃前没有将最后的几个二进制日志事件刷新到磁盘中。备库I/O线程因此也可一直处于读不到尚未写入磁盘的事件的状态中。当主库从新启动时,备库将重连到主库并再次尝试去读该事件,但…

update和delete操作忘加where条件导致全表更新的处理方法

在数据库日常维护中,开发人员是最让人头痛的,很多时候都会由于SQL语句写的有问题导致服务器出问题,导致资源耗尽。最危险的操作就是在做DML操作的时候忘加where条件,导致全表更新,这是作为运维或者DBA的我们改如何处理…

Innodb结构

从MySQL5.5版本开始默认使用InnoDB作为引擎,它擅长处理事务,具有自动崩满恢复的特性,在日常开发中使用非常广泛,下面是言方的InnoDB引擎美构图,主要分为内存结构和磁盘结构两大部分。 内存结构主要包括Buffer Pool、C…

innodb_flush_method理解【转】

innodb_flush_method这个参数控制着innodb数据文件及redo log的打开、刷写模式,对于这个参数,文档上是这样描述的: 有三个值:fdatasync(默认),O_DSYNC,O_DIRECT 默认是fdatasync,调用fsync()去…

Docker容器间网络通信

自从Docker容器出现以来,容器网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器网络通信又分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信。 一、Docker单主机容器通信 基于对net namespace的控制&#…

k8s二进制安装

1. 前言 之前文章安装 kubernetes 集群,都是使用 kubeadm 安装,然鹅很多公司也采用二进制方式搭建集群。这篇文章主要讲解,如何采用二进制包来搭建完整的高可用集群。相比使用 kubeadm 搭建,二进制搭建要繁琐很多,需要…

ELK学习笔记之Logstash详解

0x00 Logstash概述 官方介绍:Logstash is an open source data collection engine with real-time pipelining capabilities。简单来说logstash就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端;与此同时…

k8---proxy

kube-proxy 通过 Informer知道了Service、endpoints对象的创建,然后把service身上的CLUSTER-IP 和端口已经端点信息拿出来,创建iptable NAT规则做转发或通过ipvs模块创建VS服务器,这样经过CLUSTER-IP的流量都被转发到后端pod。 iptables模式 …

logstash密码设置步骤

生成密钥存储仓库 cd /app/logstash-6.8.4/bin/ ./logstash-keystore create 输入y 添加Logstash中可引用的变量 ./logstash-keystore add es_user 输入elastic ./logstash-keystore add es_pwd 输入bamBoo123 ./logstash-keystore add kafka_pwd 输入bamBoo123 ./logstash…

pycharm 自动补全括号 引号

过程&#xff1a; File->settings->Editior->General->Smart Keys 勾选Insert paired barckets(),[],{},<>

IndexError: list index out of range image_name=self.images_name[index]

这里是引用 def __len__(self):return len(self.images_name) 注意这个地方

Anaconda如何重新在开始菜单显示

步骤&#xff1a; &#xff08;1&#xff09; win R &#xff0c;然后输入Cmd 进入电脑命令端 &#xff08;2&#xff09;cd 进入anaconda 安装的路径&#xff0c;然后 输入 、、、 python .\Lib_nsis.py mkmenus 、、、 然后就OK了

python matplotlib 绘制曲线图,柱状图

matplotlib.pyplot.bar(x, y, width0.8, bottomNone, \*, aligncenter, dataNone, \*\*kwargs) x:x轴的数据值&#xff0c;或者标签 y:每个标签的值 width: 每个柱形图中每个柱子的宽度 bottom&#xff1a;y轴的基准值&#xff08;一般为0&#xff09; align: 柱形图中每个柱子…

python plt.plot bar 设置绘图尺寸大小

plt.rcParams(figure.figsize)(12,8) 修改前 修改后

Latex+Texstudio+Texlive 2020 windows10 安装教程

1.Texlive2020安装 清华大学镜像文件 link,下载比较快&#xff0c;尽量用这个资源 然后解压之后 点击 install-tl-window 即可安装 安装过程一个小时左右 2.Texstudio 安装 官网地址 link 然后安装 安装完成即可 % 导言区 \documentclass{article} % 导入中文宏 \us…

pyhton 面向对象(下)

1.私有属性 两个下划线开头&#xff0c;声明该属性为私有&#xff0c;不能在类的外部使用或者被访问 派生类&#xff08;子类&#xff09;不能去继承 class person:def __init__(self):self.__name黎明self.age30xlperson() print(xl.age) print(xl.__name)30不能继承父类的私…

Python 面向对象(中)

在python中面向对象的三大特征&#xff1a; 封装&#xff0c;继承&#xff0c;多态 1. 析构方法 程序结束后&#xff0c;之后调用析构方法&#xff0c;来释放空间 def __del__(self):print("析构方法")2.单继承 子类继承父类 class animal():def eat(self):prin…

Python 面向对象 实例方法 属性 (上)

1.面对对象和面对过程的区别 面向对象&#xff1a; 将数据与函数绑定到一起&#xff0c;进行封装&#xff0c;这样能够跟快的开发程序&#xff0c;减少代码的重复书写。 函数式&#xff1a; 包装为一个函数&#xff0c;然后调用 **面向过程&#xff1a;**根据业务逻辑从上到下…

Python高级数据类型-字符串,列表,元组,字典

0.序列 序列&#xff1a;在python中 序列就是一组按照顺序排列的值 python中三种内资的序列类型&#xff1a;字符串&#xff0c;列表&#xff0c;元组 优点&#xff1a;支持索引和切片的操作&#xff0c;从0开始 1.字符串 可以查询&#xff0c;修改 字符串常用的方法 ahe…

Juypter 代码自动补全

1.安装 pip install jupyter_contrib_nbextensions2. 配置 安装完之后需要配置 nbextension&#xff0c;注意配置的时候要确保已关闭 Jupyter Notebook&#xff1a; jupyter contrib nbextension install --user --skip-running-check3.启动 Jupyter Notebook 勾选Hinderlan…