MHA高可用及读写分离

一.软件简介

MHA是用prel编写的一套非常流行和使用的MySQL高可用解决方案软件,它的作用是保证MySQL主从复制集群中主库的高可用性,同时保证整个集群的业务不受影响。MHA能够在较短的时间内实现自动故障检测和故障转移,通常在10-30秒以内;在复制框架中,MHA能够很好地解决复制过程中的数据一致性问题,由于不需要在现有的replication中添加额外的服务器,仅需要一个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量;另外,安装简单,无性能损耗,以及不需要修改现有的复制部署也是它的优势之处。

MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。

MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以独立部署在一台独立的机器上管理多个Master-Slave集群,也可以部署在一台Slave上。当Master出现故障时,它可以自动将最新数据的Slave提升为新的Master,然后将所有其他的Slave重新指向新的Master。整个故障转移过程对应用程序是完全透明的。在主从复制集群架构中,MHA方案能够很好地解决主从复制宕机切换过程中业务持续服务和数据一致性的问题。

二.MHA架构图

4.png

三.工作流程

1)把宕机的master二进制日志保存下来。
2)找到binlog位置点最新的slave。
3)在binlog位置点最新的slave上用relay log(差异日志)修复其它slave。
4)将宕机的master上保存下来的二进制日志恢复到含有最新位置点的slave上。
5)将含有最新位置点binlog所在的slave提升为master。
6)将其它slave重新指向新提升的master,并开启主从复制。

四.MHA工具介绍

MHA软件由两部分组成,Manager工具包和Node工具包,具体的说明如下:

#下载tar包解压后可以查看
Manager工具包主要包括以下几个工具:
masterha_check_ssh              #检查MHA的ssh-key
masterha_check_repl             #检查主从复制情况
masterha_manger                 #启动MHA
masterha_check_status           #检测MHA的运行状态
masterha_master_monitor         #检测master是否宕机
masterha_master_switch          #手动故障转移
masterha_conf_host              #手动添加server信息
masterha_secondary_check        #建立TCP连接从远程服务器
masterha_stop                   #停止MHA

Node工具包主要包括以下几个工具:
save_binary_logs                #保存宕机的master的binlog
apply_diff_relay_logs           #识别relay log的差异
filter_mysqlbinlog              #防止回滚事件
purge_relay_logs                #清除中继日志

MHA优点总结

1)Masterfailover and slave promotion can be done very quickly
自动故障转移快

2)Mastercrash does not result in data inconsistency
主库崩溃不存在数据一致性问题

3)Noneed to modify current MySQL settings (MHA works with regular MySQL)
不需要对当前mysql环境做重大修改

4)Noneed to increase lots of servers
不需要添加额外的服务器(仅一台manager就可管理上百个replication)

5)Noperformance penalty
性能优秀,可工作在半同步复制和异步复制,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。

6)Works with any storage engine
只要replication支持的存储引擎,MHA都支持,不会局限于innodb

五.环经准备以及地址分配

主机名 wanIP lanIP 角色
db01 10.0.0.151 172.16.1.151 主库,MHA客户端
db02 10.0.0.152 172.16.1.152 从库,MHA客户端
db03 10.0.0.153 172.16.1.153 从库,MHA客户端
db04 10.0.0.154 172.16.1.154 从库,MHA客户端
MHA-manager 10.0.0.152 172.16.1.152 MHA服务端

六.基于GTID的MAH

传统主从复制

1.主库要开启binlog,从库不用开启binlog

2.主库要有中从复制用户,从库不需要创建主从复制用户

3.主库server_id=5,从库只要不等于5即可,从库之间可以相同


基于MHA的主从复制

1.主库要开启binlog,从库也要开启binlog

2.主库要创建主从复制用户,从库也必须创建主从复制用户

3.主库server_id=5,从库只要不等于5即可,从库之间必须不相同

从库随时会被提升为新的主库

1.基于GTID的主从复制

#主库配置
mysql> show variables like '%gtid%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| binlog_gtid_simple_recovery     | OFF       |
| enforce_gtid_consistency        | OFF       |## 开启
| gtid_executed                   |           |
| gtid_mode                       | OFF       |## 开启
| gtid_next                       | AUTOMATIC |
| gtid_owned                      |           |
| gtid_purged                     |           |
| simplified_binlog_gtid_recovery | OFF       |
+---------------------------------+-----------+

[root@db01 data]# vim /etc/my.cnf
[mysqld]
gtid_mode=on
enforce_gtid_consistency
log-bin=mysql-bin
binlog_format=row
log-slave-updates
relay_log_purge = 0
skip_name_resolve
server_id=1  #剩余从库配置需要修改server_id ,从库server_id不能相同。
#需要配置log-slave-updates参数的场景
1.级联复制
2.双主+keepalived
3.gtid

[root@db01 data]# /etc/init.d/mysqld restart‘

#创建主从复制用户
mysql> grant replication slave on *.* to rep@'%' identified by '123';

#从库执行change master
change master to
master_host='10.0.0.151', #剩余从库需要只需修改ip
master_user='rep',
master_password='123',
master_auto_position=1;

#开启主从复制
mysql> start slave;

#检查主从复制状态
mysql> show slave status\G
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes


mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000004 |      191 |              |                  | 6b898418-23ec-11ea-9271-000c29e98743:1 |
+------------------+----------+--------------+------------------+----------------------------------------+

2.关闭所有数据库自动清除relay log 的功能

  • 主库要关闭
  • 从库也要关闭
  • 临时+永久关闭
#临时关闭自动清除relay log功能(所有库)
mysql> set global relay_log_purge = 0;
#永久关闭自动清除relay log功能(所有库)
[root@db01 data]# vim /etc/my.cnf
relay_log_purge = 0
注意:只需要登录数据库执行临时设置即可,my.cnf中已经配置全局设置

3.从库要设置为只读 开启read-only功能

  • 主库不开启
  • 从库要开启
  • 临时开启
#临时开启只读功能(所有从库)
mysql> set global read_only=1;

4.部署MHA

下载mha软件

mha官网:https://code.google.com/archive/p/mysql-master-ha/
github下载地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads

服务安装

[root@db01 ~]# ll
-rw-r--r-- 1 root root 36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

[root@db02 ~]# ll
-rw-r--r--  1 root root     87119 Dec 16 08:35 mha4mysql-manager-0.56-0.el6.noarch.rpm
-rw-r--r--  1 root root     36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

[root@db03 ~]# ll
-rw-r--r-- 1 root root 36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

[root@db04 ~]# ll
-rw-r--r-- 1 root root 36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

# 安装node
[root@db01 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db02 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db03 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db04 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm

#安装manager
[root@db02 ~]# yum localinstall -y mha4mysql-manager-0.56-0.el6.noarch.rpm 

#创建MHA管理用户(所有库都要创建。这里主库创建即可以实现同步)
mysql> grant all on *.* to mha@'%' identified by 'mha';

#做命令的软链接(默认的二进制安装的路径是在/usr/bin下,mha设置路径与官方一致)
[root@db01 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db01 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

[root@db02 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db02 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

[root@db03 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db03 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

[root@db04 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db04 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

#创建密钥对
[root@db01 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.151
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.152
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.153
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.154

----

[root@db02 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.151
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.152
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.153
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.154

----

[root@db03 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.151
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.152
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.153
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.154

----

[root@db04 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.151
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.152
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.153
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.154


# 写MHA配置文件
[root@db02 ~]# mkdir /etc/mha
[root@db02 ~]# mkdir /etc/mha/app1
[root@db02 ~]# vim /etc/mha/app1.cnf
#全局配置,如果有多个集群可以配置单独的default.cnf文件
[server default]
manager_log=/etc/mha/app1/manager.log
manager_workdir=/etc/mha/app1
master_binlog_dir=/application/mysql/data #路径不一致的服务可以对应配置在对应的标签位置
user=mha
password=mha
ping_interval=2
repl_password=123
repl_user=rep
ssh_user=root
ssh_port=22

[server1]
hostname=10.0.0.151
port=3306
#master_binlog_dir=/usr/local/mysql/data #举例说明,没有不一致的情况可以忽略。 

[server2]
#candidate_master=1
#check_repl_delay=0
hostname=10.0.0.152
port=3306


[server3]
hostname=10.0.0.153
port=3306

[server4]
hostname=10.0.0.154
port=3306

## 启动前测试
[root@db02 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
Mon Dec 16 12:12:11 2019 - [info] All SSH connection tests passed successfully.

[root@db02 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.

#启动MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

#检测MHA启动状态
[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:121442) is running(0:PING_OK), master:10.0.0.151

#停止MHA
[root@db02 ~]# masterha_stop --conf=/etc/mha/app1.cnf

###如果条件允许可以将MHA服务单独安装在一台服务器,安装步骤如下:
单独安装的服务器不需要安装mysql服务端,只需要安装mysql的客户端。
1)安装node
[root@db05 ~]# yum -y localinstall mha4mysql-node-0.56-0.el6.noarch.rpm
2)安装manager
[root@db05 ~]# yum -y localinstall mha4mysql-manager-0.56-0.el6.noarch.rpm
3) 创建MHA管理用户(所有库都要创建。这里主库创建即可以实现同步)
    mysql> grant all on *.* to mha@'%' identified by 'mha';
4)做命令的软链接(默认的二进制安装的路径是在/usr/bin下,mha设置路径与官方一致)
[root@db05 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db05 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql
5)创建密钥对
[root@db05 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db05 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.151
[root@db05 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.152
[root@db05 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.153
[root@db05 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.154
# 写MHA配置文件
[root@db05 ~]# mkdir /etc/mha
[root@db05 ~]# vim /etc/mha/app1.cnf
#全局配置,如果有多个集群可以配置单独的default.cnf文件
[server default]
manager_log=/etc/mha/app1/manager.log
manager_workdir=/etc/mha/app1
master_binlog_dir=/application/mysql/data #路径不一致的服务可以对应配置在对应的标签位置
user=mha
password=mha
ping_interval=2
repl_password=123
repl_user=rep
ssh_user=root
ssh_port=22

[server1]
hostname=10.0.0.151
port=3306
#master_binlog_dir=/usr/local/mysql/data #举例说明,没有不一致的情况可以忽略。 

[server2]
#candidate_master=1
#check_repl_delay=0
hostname=10.0.0.152
port=3306


[server3]
hostname=10.0.0.153
port=3306

[server4]
hostname=10.0.0.154
port=3306

## 启动前测试
[root@db05 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
Mon Dec 16 12:12:11 2019 - [info] All SSH connection tests passed successfully.

[root@db05 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.

#启动MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

#检测MHA启动状态
[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:121442) is running(0:PING_OK), master:10.0.0.151

MHA启动命令详解

#后台管理进程
nohup
#MHA启动命令脚本
masterha_manager
#指定配置文件
--conf=/etc/mha/app1.cnf
#从配置文件中,移除宕机的主库信息
--remove_dead_master_conf
#忽略最后一次切换
--ignore_last_failover

#MHA工作机制:在MHA做完一次切换后,会在工作目录(/etc/mha/app1)中,会生成`app1.failover.complete`,可以理解是锁文件,8小时之内,不会做第二次切换。另外,每次切换都会自动杀死服务进程并且清空日志,所以需要在宕机恢复中注意操作的顺序。

MHA配置文件详解

#这里并没有配置所有的参数,后期可自行根据需要添加
[server default]
#设置manager的工作目录
manager_workdir=/etc/mha/app1
#设置manager的日志
manager_log=/etc/mha/app1/manager.log 
#设置master 保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录
master_binlog_dir=/application/mysql/data/
#设置自动failover时候的切换脚本
master_ip_failover_script= /usr/local/bin/master_ip_failover
#设置手动切换时候的切换脚本
master_ip_online_change_script= /usr/local/bin/master_ip_online_change
#设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码
password=123
#设置监控用户root
user=root
#设置监控主库,发送ping包的时间间隔,尝试三次没有回应的时候自动进行failover
ping_interval=1
#设置远端mysql在发生切换时binlog的保存位置
remote_workdir=/tmp
#设置复制用户的密码
repl_password=123
#设置复制环境中的复制用户名 
repl_user=rep
#设置发生切换后发送的报警的脚本
report_script=/usr/local/send_report
#一旦MHA到server02的监控之间出现问题,MHA Manager将会尝试从server03登录到server02
secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=192.168.0.50 --master_port=3306
#设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)
shutdown_script=""
#设置ssh的登录用户名
ssh_user=root 

[server1]
hostname=10.0.0.151
port=3306

[server2]
hostname=10.0.0.152
port=3306
#设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave。
candidate_master=1
#默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master
check_repl_delay=0

5.MHA集群恢复

1.修复宕机的主库,启动数据库

[root@db01 ~]# /etc/init.d/mysqld start

2.在日志中,找到change master语句

[root@db02 ~]# grep -i 'change master to' /etc/mha/app1/manager.log 

3.拿着change master语句在旧主库中执行

CHANGE MASTER TO MASTER_HOST='10.0.0.152', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='123';

4.开启主从复制

start slave;

5.修复MHA配置文件

[server_1]
hostname=10.0.0.151
port=3306

[server_2]
hostname=10.0.0.152
port=3306

[server_3]
hostname=10.0.0.153
port=3306

[server_4]
hostname=10.0.0.154
port=3306

6.启动MHA

[root@db02 mha]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

脚本修复MAH

#!/bin/bash

change=`ssh 10.0.0.152 "grep -i 'change master to' /etc/mha/app1/manager.log"|awk -F: '{print $NF}'|sed
 's#xxx#123#g'`

/etc/init.d/mysqld start

mysql -e "$change start slave;"

ssh 10.0.0.152 '\cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf'
#脚本执行完成后手动启动MHA服务
[root@db02 mha]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

注意:不建议将MHA的启动也写入脚本中,这样会清空日志记录

七.传统主从复制MHA

注意:这里基于之前的环境进行修改既可完成转换
1.停止MHA

[root@db02 ~]# masterha_stop --conf=/etc/mha/app1.cnf

2.取消所有从库的身份

mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

mysql> reset slave all;
Query OK, 0 rows affected (0.01 sec)

3.注释GTID相关参数

#主库从库都需要修改
[mysqld]
#gtid_mode=ON
#enforce_gtid_consistency
#log-slave-updates

4.重启数据库

[root@db04 ~]# /etc/init.d/mysqld restart

5.记录主库的binlog和position

mysql> show master status;
+------------------+----------+
| File             | Position |
+------------------+----------+
| mysql-bin.000008 |      120 |
+------------------+----------+

6.在从库上执行,change master语句

change master to
master_host='10.0.0.151',
master_user='rep',
master_password='123',
master_log_file='mysql-bin.000008',
master_log_pos=120;

7.开启主从复制

mysql> start slave;

8.查看主从复制状态

mysql> show slave status\G
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

9.启动MHA

[root@db02 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

10.查看MHA状态

[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:33304) is running(0:PING_OK), master:10.0.0.151

八.MHA选主

(1) 如果判断从库(position或者GTID),数据有差异,最接近于Master的slave,成为备选主。
(2) 如果判断从库(position或者GTID)数据一致,MHA切换在数据一致的情况下,默认查找配置文件中的server标签,server标签越小,优先级越高。
(3) 如果设定有权重(candidate_master=1),按照权重强制指定备选主。
1. 默认情况下如果一个slave落后master 100M的relay logs的话,即使有权重,也会失效。
2. 如果check_repl_delay=0的化,即使落后很多日志,也强制选择其为备选主。
标签配置如下:
[server4]
hostname=10.0.0.154
port=3306
candidate_master=1
check_repl_delay=0
注意:生产场景中不建议这样使用,relay logs相差太大也就意味着丢失数据。

九. VIP管理

1.管理vip的方式:keepalived

使用keppalived方式实现vip管理存在很多问题,并且费用较高。

  • 1.如何保证,一定从151切到153

    • 在MHA的配置文件中,加入候选主库的参数
    candidate_master=1
    check_repl_delay=0
    
  • 2.如何保证53一定是数据最新的从库

    • 半同步
  • 3.影响主库性能,超时就恢复成异步复制

    • 买配置高的机器(磁盘性能高,内存/cpu:1核2G、2核4G、4核8G)
    • 半同步复制的从库,不提供服务
    • 费用高,花钱多

2.管理vip的方式:MHA自带脚本

说明:如果条件允许建议单独使用管理节点,方便读写分离以及处理binlog保存的问题。

#自带管理脚本?(tar包解压之后可以查看)
[root@db05 ~/mha4mysql-manager-0.56/samples/scripts]# ll
total 32
-rwxr-xr-x 1 4984 users  3648 Apr  1  2014 master_ip_failover  #vip管理脚本
-rwxr-xr-x 1 4984 users  9870 Apr  1  2014 master_ip_online_change
-rwxr-xr-x 1 4984 users 11867 Apr  1  2014 power_manager
-rwxr-xr-x 1 4984 users  1360 Apr  1  2014 send_report

1.上传管理脚本

[root@db05 /etc/mha/app1]# ll
-rwxr-xr-x 1 root root 2253 Dec 31 11:03 master_ip_failover

2.添加vip

#在该行下面添加如下四行
my (
    $command,          $ssh_user,        $orig_master_host, $orig_master_ip,
    $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port
);
...............
my $vip = '10.0.0.157/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";

3.处理权限问题与格式问题

[root@db05 ~]# chmod +x /etc/mha/app1/master_ip_failover
[root@db05 ~]# yum install -y dos2unix
[root@db05 ~]# dos2unix /etc/mha/app1/master_ip_failover 
dos2unix: converting file /etc/mha/app1/master_ip_failover to Unix format ...

4.修改配置文件

[root@db05 /etc/mha]# vim app1.cnf 
[server default]
master_ip_failover_script=/etc/mha/app1/master_ip_failover

5.停止MHA

[root@db05 ~]# masterha_stop --conf=/etc/mha/app1.cnf

6.启动MHA

[root@db05 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

7.手动添加vip

[root@db01 ~]# ifconfig eth0:0 10.0.0.157/24
[root@db01 ~]# ip a
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:93:da:62 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.151/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.0.0.157/24 brd 10.0.0.255 scope global secondary eth0:0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe93:da62/64 scope link 
       valid_lft forever preferred_lft forever

3.MHA VIP管理切换测试

#模拟程序连接诶数据库vip
[root@db05 ~]# vim insert.sh
#!/bin/bash

num=1
while true;do
        mysql -uroot -p123 -h10.0.0.157 -e 'insert into rep.rep values('"$num"');commit;'
        let num++
        sleep 1
done
#启动程序
[root@db05 ~]# sh a.sh 
#关闭db02和db03的IO线程,之后再开启,实现漂移至db04
mysql> stop slave io_thread;

MHA VIP管理实现自动化恢复集群

#每台机器上放recover

#!/bin/bash

#old_master=`ssh 10.0.0.52 "sed -nr 's#^Master (.*)\(.*!$#\2#gp' /etc/mha/app1/manager.log"`
change=`ssh 10.0.0.52 "grep -i 'change master to' /etc/mha/app1/manager.log"|awk -F: '{print $NF}'|sed 's#xxx#123#g'`

/etc/init.d/mysqld start

mysql -uroot -p123 -e "$change start slave;"

ssh 10.0.0.155'\cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf'
#引用recover脚本配置
[root@db05 ~]# vim /etc/mha/app1/master_ip_failover
......
sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
    `ssh $ssh_user\@$orig_master_host \" /bin/sh /server/scripts/recovery_mha.sh \"`;
}
......

MHA binlog server

说明:mha高可用存在两个问题:1.relaylog自动清除。2.binlog保存问题,如果出现断电,断网,主节点binlog日志如何实时保存的问题。
之前已经设置了禁止relaylog自动清除,这里就来解决binlog保存的问题。

#添加一个binlog server
[root@db05 ~]# vim /etc/mha/app1.cnf
....
[binlog1]
no_master=1
hostname=10.0.0.155
master_binlog_dir=/data/mysql/binlog/

#创建实时备份binlog的目录
[root@db05 ~]#  mkdir /data/mysql/binlog/ -p
#实时拉取binlog
[root@db05 ~]# cd /data/mysql/binlog/

[root@db03 binlog]# mysqlbinlog  -R --host=10.0.0.157 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &
total 4
-rw-r----- 1 root root 120 Dec 31 18:25 mysql-bin.000001

十.MySQL中间件Atlas

Atlas简介

Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。

读写分离中间件产品

1.Atlas

2.mysql-proxy(官方)

3.mycat

Atlas主要功能

  • 1.读写分离
  • 2.从库负载均衡
  • 3.IP过滤
  • 4.自动分表
  • 5.DBA可平滑上下线DB
  • 6.自动摘除宕机的DB

相对于官方的优势

  • 1.将主流程中所有Lua代码用C重写,Lua仅用于管理接口
  • 2.重写网络模型、线程模型
  • 3.实现了真正意义上的连接池
  • 4.优化了锁机制,性能提高数十倍

Atlas安装和配置

官方提供的Atlas有两种:
1)Atlas (普通) : Atlas-2.2.1.el6.x86_64.rpm
2)Atlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm
这里我们只需要下载普通的即可。

#下载安装二进制包
[root@db05 ~]# wget httpss://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
#安装
[root@db05 ~]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:Atlas-2.2.1-1                    ################################# [100%]

Atlas配置文件说明

[root@db05 /usr/local/mysql-proxy]# ll
total 0
drwxr-xr-x 2 root root  75 Dec 18 11:38 bin         #工具命令
drwxr-xr-x 2 root root  22 Dec 18 11:43 conf                #配置文件
drwxr-xr-x 3 root root 331 Dec 18 11:38 lib         #库文件
drwxr-xr-x 2 root root   6 Dec 17  2014 log         #日志文件

编辑配置文件
说明:应用服务默认使用连接数据库的端口为3306,这里就需要将集群的数据库的端口统一改为3307或者其他端口,Atlas的工作端口应使用3306。之前的配置均为3306,这里需要自行修改后绑定端口,重新建立主从关系进行使用。

#密码加密
[root@db05 /usr/local/mysql-proxy]# cd bin/
[root@db05 /usr/local/mysql-proxy/bin]# ll
total 44
-rwxr-xr-x 1 root root  9696 Dec 17  2014 encrypt
-rwxr-xr-x 1 root root 23564 Dec 17  2014 mysql-proxy
-rwxr-xr-x 1 root root  1552 Dec 17  2014 mysql-proxyd
-rw-r--r-- 1 root root     6 Dec 17  2014 VERSION
[root@db05 /usr/local/mysql-proxy/bin]# ./encrypt 123
3yb5jEku5h4=
[root@db05 /usr/local/mysql-proxy/bin]# ./encrypt mha
O2jBXONX098=

#配置文件配置如下
[root@db05 ~]# vim /usr/local/mysql-proxy/conf/test.cnf   #配置Atlas多实例,启动多个配置文件即可
[mysql-proxy]

#带#号的为非必需的配置项目

#管理接口的用户名
admin-username = user

#管理接口的密码
admin-password = pwd

#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses = 10.0.0.157:3307    #注意:一般使用直接配置vip地址。

#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
proxy-read-only-backend-addresses = 10.0.0.151:3307,10.0.0.153:3307,10.0.0.154:3307

#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!
pwds = rep:3yb5jEku5h4=,mha:O2jBXONX098=

#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
daemon = true

keepalive = true

#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置
event-threads = 8

#日志级别,分为message、warning、critical、error、debug五个级别
log-level = error

#日志存放的路径
log-path = /usr/local/mysql-proxy/log

#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF
sql-log = ON

#慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该参数则输出全部日志。
sql-log-slow = 10

#实例名称,用于同一台机器上多个Atlas实例间的区分
instance = test  #注意:如果管理多实例,请于配置文件保持一致

#Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:3306  #如果管理多Atlars实例,配置端口不能冲突

#Atlas监听的管理接口IP和端口
admin-address = 0.0.0.0:2345  #如果管理多Atlas实例,配置端口不能冲突

#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3

#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
charset = utf8

#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1

启动Atlas

[root@db05 ~]# /usr/local/mysql-proxy/bin/mysql-proxyd test start

连接测试

#连接工作接口
[root@db01 ~]# mysql -urep -p123 -h10.0.0.155 -P3306
#连接管理接口
[root@db05 ~]# mysql -uuser -ppwd -h127.0.0.1 -P2345

管理操作命令解释


实际操作

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.0.157:3307 | up    | rw   |
|           2 | 10.0.0.151:3307 | up    | ro   |
|           3 | 10.0.0.153:3307 | up    | ro   |
|           4 | 10.0.0.154:3307 | up    | ro   |
+-------------+-----------------+-------+------+
4 rows in set (0.00 sec)

mysql> set offline 3;
+-------------+-----------------+---------+------+
| backend_ndx | address         | state   | type |
+-------------+-----------------+---------+------+
|           3 | 10.0.0.153:3307 | offline | ro   |
+-------------+-----------------+---------+------+
1 row in set (0.00 sec)

mysql> select * from backends;
+-------------+-----------------+---------+------+
| backend_ndx | address         | state   | type |
+-------------+-----------------+---------+------+
|           1 | 10.0.0.157:3307 | up      | rw   |
|           2 | 10.0.0.151:3307 | up      | ro   |
|           3 | 10.0.0.153:3307 | offline | ro   |
|           4 | 10.0.0.154:3307 | up      | ro   |
+-------------+-----------------+---------+------+
4 rows in set (0.00 sec)

mysql> set online 3;
+-------------+-----------------+---------+------+
| backend_ndx | address         | state   | type |
+-------------+-----------------+---------+------+
|           3 | 10.0.0.153:3307 | unknown | ro   |
+-------------+-----------------+---------+------+
1 row in set (0.00 sec)

mysql> set online 3;
+-------------+-----------------+---------+------+
| backend_ndx | address         | state   | type |
+-------------+-----------------+---------+------+
|           3 | 10.0.0.153:3307 | unknown | ro   |
+-------------+-----------------+---------+------+
1 row in set (0.00 sec)

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.0.157:3307 | up    | rw   |
|           2 | 10.0.0.151:3307 | up    | ro   |
|           3 | 10.0.0.153:3307 | up    | ro   |
|           4 | 10.0.0.154:3307 | up    | ro   |
+-------------+-----------------+-------+------+
4 rows in set (0.00 sec)
mysql> add master 10.0.0.152:3307;
Empty set (0.00 sec)

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.0.157:3307 | up    | rw   |
|           2 | 10.0.0.152:3307 | up    | rw   |
|           3 | 10.0.0.153:3307 | up    | ro   |
|           4 | 10.0.0.154:3307 | up    | ro   |
|           5 | 10.0.0.151:3307 | up    | ro   |
+-------------+-----------------+-------+------+
5 rows in set (0.00 sec)
mysql> add master 10.0.0.152:3307;
mysql> select * from backends; #并未写入配置文件
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.0.157:3307 | up    | rw   |
|           2 | 10.0.0.152:3307 | up    | rw   |
|           3 | 10.0.0.153:3307 | up    | ro   |
|           4 | 10.0.0.154:3307 | up    | ro   |
|           5 | 10.0.0.151:3307 | up    | ro   |
+-------------+-----------------+-------+------+
mysql> save config #写入配置文件。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容