> MySQL安装和复制请查看7.1/7.2相关章节
> MHA要求MySQL所有节点创建复制账户
> LVS负责读操作的负载均衡
#### 基础环境
操作系统:Centos 7.3 64位;
```shell
数据库写VIP:192.168.0.20
数据库读VIP(LVS):192.168.0.21
```
服务器角色和配置信息
|角色|IP地址|主机名|Server-ID|功能类型|
| :------------: | :------------: | :------------: | :------------: | :------------: |
|Master|192.168.0.230|mdb01.prod.ding|168001200|写|
|Candicate Master|192.168.0.236|mdb01-s1.prod.ding|168001201|读|
|Slave|192.168.0.235|mdb01-s2.prod.ding|168001202|读|
|Monitor host|192.168.0.237|mha.prod.ding||MySQL主库的故障转移|
|LVS+Keepalived-A|192.168.0.90|mdb-lvs01.prod.ding||读操作的负载均衡|
|LVS+Keepalived-B|192.168.0.91|mdb-lvs02.prod.ding||LVS高可用备机|
各服务器软件部署情况
|角色|Manager|Node|Keepalived|LVS|
| :------------: | :------------: | :------------: | :------------: | :------------: |
|Master|-|部署|-|-|
|Candicate Master|-|部署|-|-|
|Slave|-|部署|-|-|
|MHA host|部署|部署|-|-|
|LVS+Keepalived-A|-|-|部署|部署|
|LVS+Keepalived-B|||部署|部署|
#### 拓扑图及实现原理
![MHA拓扑图](index_files/MHA.png "MHA拓扑图")
##### 业务流程
**读操作**
1. LVS实现读操作的负载均衡;
2. Keepalived在上层管理LVS,并对两台从库进行健康检测(通过定义Check脚本);
3. 一台从库出现故障后,Keepalived将其剔除出负载均衡集群;
**写操作**
1. 在Master上绑定写VIP(MHA启动后会通过脚本进行操作);
2. MHA监控Master状态,当Master出现故障后(宕机、复制暂停)时;
3. 通过Failover脚本,卸载Master上的WVIP;
4. 通过Failover在CMaster上绑定WVIP,提升其为主库;
5. 同步并应用差异日志,并将从库指向新主库;
问题:当MHA把Master切换到了CMaster上后,LVS如何处理分发在CMaster上的读操作?
解释:由于Keepalived会通过脚本定期监控CMaster的状态,包括同步、SQL线程、I/O线程,所以当CMaster升级为主库后,这些状态都将消失,Keepalived将自动将CMaster剔除出负载均衡集群。
#### 部署MHA
MHA使用Perl编写,需要安装Perl依赖,建议使用阿里云的YUM源,YUM安装
Node节点需要perl-DBD-MySQL perl-DBI
Manger需要perl-Config-Tiny.noarch perl-Log-Dispatch.noarch perl-Parallel-ForkManager.noarch perl-DBD-MySQL perl-DBI
##### 部署约定
|序号|目录名称|目录位置|
| :------------: | :------------: | :------------: |
|1|上传文件目录|/tmp/|
|2|MHA配置文件目录|/app/mha|
|3|MHA日志文件目录|/app/mha/log|
|4|MHA管理目录|/app/mha/app1|
|5|MHA处理数据目录|/tmp|
|6|relay_log_purge脚本目录|/app/scripts|
|7|master_ip_failover脚本目录|/app/scripts|
##### 配置阿里云的YUM源
```shell
#clean OS default repo
mkdir /etc/yum.repos.d/old && mv /etc/yum.repos.d/C* /etc/yum.repos.d/old/
#add local repo
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
```
##### 安装Perl依赖
方法一 使用YUM 安装(推荐)
```shell
yum install -y perl-Config-Tiny.noarch perl-Log-Dispatch.noarch perl-Parallel-ForkManager.noarch perl-DBD-MySQL perl-DBI
```
方法二 使用cpanm安装。注意:时间必须整正确
编写脚本DBD_install.sh
```shell
#!/bin/bash
wget http://xrl.us/cpanm --no-check-certificate
mv cpanm /usr/bin/
chmod 755 /usr/bin/cpanm
cat >/root/list<<EOF
install DBD::mysql
install Config::Tiny
install Log::Dispatch
install Parallel::ForkManager
install Time::HiRes
EOF
for package in `cat /root/list`
do
cpanm $package
done
```
##### 在所有节点上安装MHA Node:
rpm包安装
```shell
cd /opt/
rpm -ivh mha4mysql-node-0.57-0.el7.noarch.rpm
```
编译安装
```shell
tar xf mha4mysql-node-0.53.tar.gz
cd mha4mysql-node
perl Makefile.PL
make && make install
```
##### 安装MHA Manager
rpm包安装
```shell
cd /opt/
rpm -ivh mha4mysql-manager-0.57-0.el7.noarch.rpm
rpm -ivh mha4mysql-node-0.57-0.el7.noarch.rpm
```
编译安装
```shell
tar zxf mha4mysql-manager-0.53.tar.gz
cd mha4mysql-manager-0.53
perl Makefile.PL
make
make install
```
#### 配置MHA manger
创建基础目录
```shell
mkdir -p /etc/mha
mkdir -p /etc/mha/log
mkdir -p /etc/mha/app1
mkdir -p /etc/mha/scripts
mkdir -p /tmp/
```
##### 配置MHA对MySQL监控和binlog控制
>这个账户和复制账户没有关系
```shell
grant all on *.* to 'mha'@'192.168.0.%' identified by 'mha'; flush privileges;
```
##### 在(MHA/M/S1/S2)服务器上配置主机名(MHA管理脚本通过主机名调用)
```shell
cat >>/etc/hosts<< EOF
192.168.0.230 ip230
192.168.0.235 ip235
192.168.0.236 ip236
192.168.0.237 ip237
EOF
```
##### 所有MySQL节点增加mysqlbinlog环境变量(解析binlog用)
```shell
echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/bashrc ;source /etc/bashrc
```
> bashrc是每次执行bash脚本时加载的变量
##### 配置MHA和MySQL主从之间的主机免密钥登录
所有节点执行以下操作
- 部署SSH免密钥登录
- 所有节点可以SSH访问MHA和其他MySQL节点
- 所有节点可以SSH访问自己
```shell
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub "root@192.168.0.230"
ssh-copy-id -i ~/.ssh/id_rsa.pub "root@192.168.0.235"
ssh-copy-id -i ~/.ssh/id_rsa.pub "root@192.168.0.236"
ssh-copy-id -i ~/.ssh/id_rsa.pub "root@192.168.0.237"
```
##### 在/app/mha下创建app1.cnf
>注意修改相关配置文件master_binlog_dir为MySQl的数据目录
```shell
[server default]
manager_log=/etc/mha/log/app1.log
manager_workdir=/etc/mha/app1/
master_binlog_dir=/data/mysql3306
master_ip_failover_script=/etc/mha/master_ip_failover
ping_interval=1
remote_workdir=/tmp
secondary_check_script=/bin/masterha_secondary_check -s ip235 -s ip236 --user=root --master_host=ip230 --master_ip=192.168.0.230 --master_port=3306
ssh_user=root
user=mha
password=mha
repl_password=repl
repl_user=repl
[server1]
hostname=192.168.0.230
port=3306
[server2]
candidate_master=1
check_repl_delay=0
hostname=192.168.0.235
port=3306
[server3]
hostname=192.168.0.236
port=3306
```
> 根据实际情况修改masterha_secondary_check位置,rpm安装在bin目录下
#### 上传并修改/etc/mha/master_ip_failover脚本
```shell
chmod 600 master_ip_failover
```
内容详见结尾附件
##### 调整参数(网卡名称和IP)
```shell
my $vip = '192.168.0.20/24'; # Virtual IP
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
```
#### 部署从库(S1/S2)的手动回收中继日志脚本
上传relay_purge.sh到/app/scripts下并增加执行权限
```shell
#!/bin/bash
/usr/bin/purge_relay_logs --user=root --password=123.com --socket=/tmp/mysql3306.sock --host=localhost -disable_relay_log_purge --port=3306 --workdir=/tmp >> /app/scripts/purge_relay_logs.log 2>&1
```
增加执行权限
```shell
chmod 600 /app/scripts/relay_purge.sh
```
部署定时任务
```shell
echo '0 4 * * * /bin/sh /app/scripts/relay_purge.sh' >/var/spool/cron/root
```
#### 切换测试
##### 验证SSH配置
```shell
masterha_check_ssh --conf=/etc/mha/app1.cnf
```
##### 测试复制、应用差异日志、故障转移脚本
```shell
masterha_check_repl --conf=/etc/mha/app1.cnf
```
##### 启动MHA
```shell
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover< /dev/null >/etc/mha/app1/manager.log 2>&1 &
#状态检查
sterha_check_status --conf=/etc/mha/app1.cnf
```
##### 关闭MHA
正常关闭
```shell
masterha_stop --conf=/etc/mha/app1.cnf
```
##### 关闭主库,并监控MHA日志
具体日志请查看MHA日志部分
这时,230(down) 235提升为主库,236指向了235
#### 恢复原有环境
1.启动230数据库,并查看position情况
```shell
show master status\G
```
2.将236重新指向230
```shell
stop slave;
change master to master_host='192.168.0.230',master_user='repl',master_password='repl',master_log_file='mysql-bin.000003',master_log_pos=154;
start slave;
```
3.将235重新指向230
```shell
change master to master_host='192.168.0.230',master_user='repl',master_password='repl',master_log_file='mysql-bin.000003',master_log_pos=154;
start slave;
```
4.恢复MHA配置文件,并删除锁文件
```shell
rm -f /etc/mha/app1/app1.failover.complete
```
> 不删除,不会切换,防止反复切换
5.卸载235上的写VIP
```shell
/sbin/ifconfig eth0:1 down
```
#### 附件
/etc/mha/master_ip_failover
```shell
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port,
);
my $vip = '192.168.0.20/24'; # Virtual IP
my $key = "0";
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
$ssh_user = "root";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
#eval {
# print "Disabling the VIP on old master: $orig_master_host \n";
# &stop_vip();
# $exit_code = 0;
#};
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
#my $ping=`ping -c 1 10.0.0.13 | grep "packet loss" | awk -F',' '{print $3}' | awk '{print $1}'`;
#if ( $ping le "90.0%" && $ping gt "0.0%" ){
#$exit_code = 0;
#}
#else {
&stop_vip();
# updating global catalog, etc
$exit_code = 0;
#}
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $ssh_user\@$orig_master_ip \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
# the end.
```
- 献给乐于奉献的你
- 一、工作感悟
- 1.1 工作感悟
- 1.2 数据库工作总结
- 二、运维专题(非技术)
- 2.1 公有云运维
- 2.1.1 阿里云采坑记.md
- 三、运维专题(技术类)
- 3.1 Linux(操作系统)
- 3.1.1 常见工作总结
- 3.1.2 常见服务使用和部署
- 3.1.3 操作系统优化
- 3.1.4 常用命令(Centos8)
- 3.2 Docker & K8s(容器技术)
- 3.2.1 Docker
- 1. Docker
- 1-1 容器基础
- 1-2 部署和加速
- 1-3 常用命令
- 1-4 Dockerfile编写
- 1-5 容器网络
- 1-6 数据持久化
- 2. docker-compose
- 2-1 基础
- 3.2.2 kubernetes
- 1. 导读-请先看我
- 2. kubeadm部署集群
- 1-1 k8s-1.14-基于calico
- 1-2 k8s-1.17-基于flanne
- 3. 二进制部署集群
- 4. 日常工作及故障处理
- 4-1 常用命令
- 4-2 故障处理
- 3.2.3 依赖服务部署
- 1. Harbor(镜像仓库)
- 1-1 harbor-2.1.0(单节点)
- 3.3 CICD(持续集成/部署)
- 3.3.1 GitLab
- 1. 服务部署
- 1-1 Gitlab-CE-13.3.4(单节点)
- 2. Git基础
- 3.3.2 Ansible
- 1. 服务部署
- 1-2 ansible-2.5(pip部署)
- 3. ansible-playbook
- 3-1 基于Roles的Playbook
- 3-3 循环语法
- 3.3.3 Jnekins
- 1. Jenkins部署
- 1-1 Jenkins-2.65部署
- 1-2 Jenkins-2.249部署
- 2. Jenkins项目初始化
- 3. Jenkins集成
- 3-1 Jenkins-2.65集成Sonar
- 3.4 LB/HA(负载均衡,反向代理)
- 3.4.1 LVS+Keepalive
- 1. LVS为MySQL读提供负载均衡
- 3.4.2 Pacemaker(HA)
- 1. 常用命令(转)
- 3.5 Runtime(代码运行环境)
- 3.5.1 Tomcat(Web中间件)
- 1. Tomcat部署手册
- 1-1 Tomcat-7.0.76部署
- 2. Tomcat常用脚本
- 3.6 NoSQL(非关系型数据库)
- 3.6.1 redis(非关系数据库)
- 1. Redis 基础
- 2. Redis 4.0变化
- 3. Codis实现Redis的集群
- 4. Redis故障处理
- 5. redis安全第一步
- 6. Redis集群搭建
- 7. CacheCloud部署
- 3.6.1 Redis挑战
- 3.6.2 MongoDB(文档数据库)
- 1. Mongodb基础
- 1-1 Mongodb4.0新特性
- 1-2 支持多大数据量
- 2. Mongodb安装
- 2-1 Mac OS安装Mongodb
- 2-2 Yum安装Mongodb
- 2-3 二进制安装Mongodb
- 2-4 docker容器安装Mongodb
- 2-5 Mongodb 配置文件详解
- 2-6 Mongodb 生产安全清单
- 2-7 用户身份认证和授权
- 3. Mongodb副本集
- 3-1 副本集搭建
- 3-2 用户身份认证与授权
- 4. 日常维护工作
- 4-1 Mongodb磁盘回收
- 4-2 Mongodb备份恢复到任意时间点
- 4-3 Mongodb慢查询分析
- 4-4 Mongodb版本升级
- 4-5 Mongodb副本集成员状态
- 4-6 Mongodb备份恢复工具使用
- 4-7 Mongodb服务启动和停止
- 4-8 修改副本集成员oplog大小
- 4-9 Mongodb 副本集Oplog
- 3.7 MQ(消息队列)
- 3.7.1 Zookeeper(分布式协调系统)
- 1. ZooKeeper基础
- 2. ZooKeeper集群搭建
- 2-1 ZK-3.4.10部署
- 3.2 RabbitMQ(消息队列)
- 1. 服务部署
- 1-1 RabbitMQ-3.8部署
- 2. 常用命令
- 3.8 Monitor(数据收集,监控)
- 3.8.1 Zabbix(运维监控)
- 1. 服务部署
- 1-1 服务端部署
- 1-2 客户端部署
- 2. 监控服务
- 2-1 监控Apache
- 2-2 监控IIS
- 2-3 监控Ningx
- 2-4 监控Tomcat(6/7/8)
- 2-5 监控WebSphere 7
- 2-6 监控MySQL
- 2-7 监控Oracle
- 2-8 监控SQL Servre
- 2-9 监控Weblogic
- 2-10 监控Windows
- 2-11 自定义监控项
- 3. 告警推送
- 3-1 邮件告警
- 3-2 短信告警
- 3-3 告警推到Syslog
- 4. 日常工作
- 4-1 数据库优化(TokuDB)
- 4-2 数据库优化(分区表)
- 4-3 前端定制(Grafana)
- 5. 与Grafana结合
- 3.8.2 ELKBstack(日志收集展示)
- 1. 服务部署
- 1-1 ELK 5.5部署及配置
- 1-1-1 ELKBstack介绍
- 1-1-2 Elasticsearch部署
- 1-1-3 Logstash部署
- 1-1-4 Kibana部署
- 1-1-5 X-pack部署
- 1-1-6 Filebeat部署
- 2. ELK高级配置
- 1. Elasticsearch实战
- 2. Logstash实战
- 3. Filebeat实战
- 5. 引入队列
- 3.9 Virtualization(虚拟化)
- 3.10 Basic(基础服务)
- 3.10.1 Piwik-Matomo(用户行为分析)
- 1. Piwik前期分析
- 2. Piwik介绍和部署
- 2-1 Piwik-3.x版本(早期)
- 3. Piwik 功能配置
- 4. Piwik 模拟数据和压测
- 5. Piwik运转原理
- 6. Piwik数据库模式(一)
- 6-1 第一部分
- 6-2 第二部分
- 3.10.2 Cobbler(系统自动部署)
- 1. Cobbler 可以干什么?
- 2. Cobbler 基础原理
- 3. Cobbler 安装
- 3-1 Cobbler-2.8部署
- 4. Cobbler 基础配置
- 5. Cobbler 配置文件
- 6. 一键优化脚本
- 3.10.3 Rsync(数据同步服务)
- 1. Rsync基础
- 2. 案例:页面部署(服务端拉取)
- 3.10.4 NFS(共享存储)
- 1. NFS部署手册
- 2. 客户端NFS备份脚本
- 3.10.5 Grafana(可视化)
- 1. 安装(8.2.x)
- 3.11 Tools(软件工具)
- 3.11.1 基准测试
- 1. 基准测试方法论
- 2. 压测工具 - Siege
- 3. 压测工具 - http_load
- 3.12 DB(关系型数据库)
- 3.12.1 MySQL(关系数据库)
- 1. MySQL部署
- 1-1 MySQL-5.7部署
- 1-2 Percona-5.7 + TokuDB 部署
- 2. MySQL复制
- 2-1 MySQL异步复制
- 3. MySQL备份恢复
- 3-1 xtrabackup 备份恢复
- 4. MySQL 高可用
- 4-1 MHA(HA)
- 4-1-1 MHA 架构介绍和原理
- 4-1-2 MHA日常管理
- 4-1-3 MHA 自动Failover
- 4-1-4 MHA常用参数
- 4-1-5 MHA 报错
- 4-1-6 MHA相关配置文件和脚本
- 4-2 MyCAT
- 4-2-1 MyCAT 介绍和部署
- 4-1-3 MyCAT读写分离案例解析
- 5. MySQL 常用脚本
- 5-1 MySQL常用统计语句
- 5-2 MySQL性能分析脚本
- 6. MySQL 日常及故障处理
- 6-1 MySQL死锁排查
- 6-2 复制故障
- 6-3 MySQL 升级注意事项
- 6-3 MySQL授权
- 3.12.2 Oracle(关系数据库)
- 1. Oracle部署
- 1-1 Oracle11g单实例部署
- 1-2 Oracle12c单实例部署
- 2. Oracle常用脚本
- 3. Oracle 知识点
- 六、Ansible开源项目
- 6.1 项目初始化手册
- 6.1.1 Ansible错误处理
- 6.1.2 一种预先判断是否操作的方法
- 6.2 System初始化
- 6.3 Nginx/Tnginx部署
- 6.4 Python部署
- 6.5 PHP部署
- 6.6 MySQL部署
- 6.7 Docker部署
- 6.8 Haproxy部署
- 6.9 Redis部署
- 1. 变量和tags信息
- 3. Redis主从部署
- 4. Redis集群部署
- 5. 清理数据
- 6.10 Software软件部署
- 6.11 Zabbix部署
- 6.12 Elastic部署
- 6.13 Tomcat
- 6.14 Kafka部署
- 6.15 Zookeeper部署
- 6.16 Etcd集群部署
- 6.17 M3DB部署
- 6.18 Pormetheus部署
- 七、学习资源推荐
- 八、从瞎搞到放弃
- 8.1 CodeQL(语义代码分析引擎)
- 8.1.1 背景及计划
- 8.1.2 CodeQL概述
- 8.1.3 简单部署和使用
- 8.1.4 后续
- 8.2 dbdeployer(轻松部署MySQL)
- 归档笔记
- 三、常用服务部署(迁移中)
- 3.4 Nginx & PHP(Web服务)
- 3.4.1 Nginx(Web)
- 1. Nginx基础和部署
- 2. Nginx 我的一些思考
- 3. Nginx(Web)配置
- 4. Nginx(Proxy)配置
- 5. Nginx日常管理
- 3.4.3 PHP
- 1. PHP 7.1 部署
- 2. PHP5.6 部署
- 4. PHP原理
- 5. PHP 常用模块
- 二、运维项目实战(迁移中)
- 2.1 标准化 & 工具化项目
- 2.1.1 系统部署和优化
- 2.1.5 全网日志收集展示平台项目
- 1. 项目需求
- 2. 整体方案规划
- 3. 日志收集配置
- 4. 消息缓冲队列
- 5. 日志处理转发
- 6. 日志数据展示(待补充)
- 7. ELK安全配置(上)
- 8. ELK安全配置(下)
- 9. 项目总结
- 2.2 高性能Web项目
- 2.2.1 网站需求(完善中)