关于java:MySQL高可用架构MHA与Atlas读写分离

1.1 MHA简介

1.1.1 MHA软件介绍

  MHA(Master High Availability)目前在MySQL高可用方面是一个绝对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优良的作为MySQL高可用性环境下故障切换和主从晋升的高可用软件。在MySQL故障切换过程中,MHA能做到在10~30秒之内主动实现数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大水平上保证数据的一致性,以达到真正意义上的高可用。

  MHA可能在较短的工夫内实现主动故障检测和故障转移,通常在10-30秒以内;在复制 框架中,MHA可能很好地解决复制过程中的数据一致性问题,因为不须要在现有的 replication中增加额定的服务器,仅须要一个manager节点,而一个Manager能治理多套复制,所以能大大地节约服务器的数量;另外,安装简单,无性能损耗,以及不须要批改现 有的复制部署也是它的劣势之处。

  MHA还提供在线主库切换的性能,可能平安地切换以后运行的主库到一个新的主库中 (通过将从库晋升为主库),大略0.5-2秒内即可实现。

  该软件由两局部组成:MHA Manager(治理节点)和MHA Node(数据节点)。MHA Manager能够独自部署在一台独立的机器上治理多个master-slave集群,也能够部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,master呈现故障时,它能够主动将最新数据的slave晋升为新的master,而后将所有其余的slave从新指向新的master整个故障转移过程对应用程序齐全通明。

  在MHA主动故障切换过程中,MHA试图从宕机的主服务器上保留二进制日志,最大水平的保证数据的不失落,但这并不总是可行的。例如,如果主服务器硬件故障或无奈通过ssh拜访,MHA没法保留二进制日志,只进行故障转移而失落了最新的数据。应用MySQL 5.5的半同步复制,能够大大降低数据失落的危险。

  MHA能够与半同步复制联合起来。如果只有一个slave曾经收到了最新的二进制日志,MHA能够将最新的二进制日志利用于其余所有的slave服务器上,因而能够保障所有节点的数据一致性。

  目前MHA次要反对一主多从的架构,要搭建MHA,要求一个复制集群中必须起码有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至多须要三台服务器,出于机器老本的思考,淘宝也在该根底上进行了革新,目前淘宝TMHA曾经反对一主一从。

1.1.2 MHA工作原理

工作原理阐明: 1、保留master上的所有binlog事件 2、找到含有最新binlog地位点的slave 3、通过中继日志将数据恢复到其余的slave 4、将蕴含最新binlog地位点的slave晋升为master 5、将其余从库slave指向新的master原slave01 并开启主从复制 6、将保留下来的binlog复原到新的master上

1、监控所有node节点MHA性能阐明:

2、主动故障切换(failover)

前提是必须有三个节点存在,并且有两个从库

  (1)选主前提,依照配置文件的程序进行,然而如果此节点后主库100M以上relay-log 就不会选

  (2)如果你设置了权重,总会切换带此节点;个别在多地多核心的状况下,个别会把权重设置在本地节点。

  (3)抉择s1为新主

  (4)保留主库binlog日志

3、从新构建主从

  (1)将有问题的节点剔除MHA

    进行第一阶段数据弥补,S2缺失局部补全90

  (2)s1切换角色为新主,将s2指向新主S1

     s2 change master to s1

  (3) 第二阶段数据弥补

     将保留过去的新主和原有主缺失局部的binlog,利用到新主。

  (4)虚构IP漂移到新主,对利用通明无感知

   (5)告诉管理员故障切换

1.1.3 MHA高可用架构图

1.1.4 MHA工具介绍

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

  Manager工具包次要包含以下几个工具:

masterha_check_ssh             #检査 MHA 的 ssh-key^
masterha_check_repl            #检査主从复制状况
masterha_manger                #启动MHA
masterha_check_status          #检测MHA的运行状态^
masterha_mast er_monitor       #检测master是否宕机一
masterha_mast er_switch        #手动故障转移—
masterha_conf_host             #手动增加server倍息一
masterha_secondary_check       #建设TCP连贯从近程服务器v
masterha_stop                  #进行MHA

Node工具包次要包含以下几个工具:

save_binary_1ogs       #保留宕机的master的binlog
apply_diff_relay_logs   #辨认relay log的差别
filter_mysqlbinlog           #避免回滚事件一MHA已不再应用这个工具
purge_relay_logs           #革除中继曰志一不会阻塞SQL线程

1.1.5 MHA的长处

1、主动故障转移

2、主库解体不存在数据不统一的状况

3、不须要对以后的mysql环境做重大批改

4、不须要增加额定的服务器

5、性能优良,能够工作再半同步和异步复制框架

6、只有replication反对的存储引擎mha都反对

1.2 环境阐明

   在本次的试验中,共须要用到三台主机,零碎、软件阐明如下。

1.2.1 零碎环境阐明

db01主机(master)

[root@db01 ~]# cat /etc/redhat-release 
CentOS release 6.9 (Final)
[root@db01 ~]# uname -r
2.6.32-696.el6.x86_64
[root@db01 ~]# /etc/init.d/iptables status
iptables: Firewall is not running.
[root@db01 ~]# getenforce 
Disabled
[root@db01 ~]# hostname -I
10.0.0.51 172.16.1.51

db02主机(slave1)

 1 [root@db02 ~]# cat /etc/redhat-release 
 2 CentOS release 6.9 (Final)
 3 [root@db02 ~]# uname -r
 4 2.6.32-696.el6.x86_64
 5 [root@db02 ~]# /etc/init.d/iptables status
 6 iptables: Firewall is not running.
 7 [root@db02 ~]# getenforce 
 8 Disabled
 9 [root@db02 ~]# hostname -I
10 10.0.0.52 172.16.1.52

db03主机(slave1,MHA Manages、Atlas节点)

 1 [root@db02 ~]# cat /etc/redhat-release 
 2 CentOS release 6.9 (Final)
 3 [root@db02 ~]# uname -r
 4 2.6.32-696.el6.x86_64
 5 [root@db02 ~]# /etc/init.d/iptables status
 6 iptables: Firewall is not running.
 7 [root@db02 ~]# getenforce 
 8 Disabled
 9 [root@db02 ~]# hostname -I
10 10.0.0.52 172.16.1.52

1.2.2 mysql软件阐明

​ 三台服务器上都全新装置mysql 5.6.36 :

[root@db01 ~]# mysql --version
mysql  Ver 14.14 Distrib 5.6.36, for Linux (x86_64) using  EditLine wrapper

  对于mysql数据库具体的装置办法参考:http://www.cnblogs.com/clsn/p…

1.3 基于GTID的主从复制配置

1.3.1 先决条件

  ???? 主库和从库都要开启binlog

  ???? 主库和从库server-id必须不同

  ???? 要有主从复制用户

1.3.2 配置主从复制

db01 my.cnf文件

[root@db01 ~]# cat /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
secure-file-priv=/tmp 
server-id=51
skip-name-resolve  # 跳过域名解析
gtid-mode=on    # 启用gtid类型,否则就是一般的复制架构
enforce-gtid-consistency=true    #强制GTID的一致性
log-slave-updates=1     # slave更新是否记入日志(5.6必须的)
relay_log_purge = 0 
[mysql]
socket=/tmp/mysql.sock

db02 my.cnf文件

 1 [root@db02 ~]# cat /etc/my.cnf
 2 [mysqld]
 3 basedir=/application/mysql
 4 datadir=/application/mysql/data
 5 socket=/tmp/mysql.sock
 6 log-error=/var/log/mysql.log
 7 log-bin=/data/mysql/mysql-bin
 8 binlog_format=row
 9 secure-file-priv=/tmp 
10 server-id=52
11 skip-name-resolve
12 gtid-mode=on
13 enforce-gtid-consistency=true
14 log-slave-updates=1
15 relay_log_purge = 0 
16 [mysql]
17 socket=/tmp/mysql.sock

db03 my.cnf文件

 1 [root@db03 ~]# cat /etc/my.cnf
 2 [mysqld]
 3 basedir=/application/mysql
 4 datadir=/application/mysql/data
 5 socket=/tmp/mysql.sock
 6 log-error=/var/log/mysql.log
 7 log-bin=/data/mysql/mysql-bin
 8 binlog_format=row
 9 secure-file-priv=/tmp 
10 server-id=53
11 skip-name-resolve
12 gtid-mode=on
13 enforce-gtid-consistency=true
14 log-slave-updates=1
15 relay_log_purge = 0 
16 skip-name-resolve
17 [mysql]
18 socket=/tmp/mysql.sock

创立复制用户 (51作为主节点,52、53为从)

GRANT REPLICATION SLAVE ON *.* TO repl@'10.0.0.%' IDENTIFIED BY '123';

从库开启复制

change master to 
    master_host='10.0.0.51',
    master_user='repl',
    master_password='123',
    MASTER_AUTO_POSITION=1;

启动从库复制

start slave;

1.3.3 GTID复制技术阐明

MySQL GTID简介

  GTID的全称为 global transaction identifier ,能够翻译为全局事务标示符,GTID在原始master上的事务提交时被创立。GTID须要在全局的主-备拓扑构造中放弃唯一性,GTID由两局部组成:

 GTID = source_id:transaction_id

  source_id用于标示源服务器,用server_uuid来示意,这个值在第一次启动时生成,并写入到配置文件data/auto.cnf中

  transaction_id则是依据在源服务器上第几个提交的事务来确定。

GTID事件构造


GTID在二进制日志中的构造


一个GTID*的生命周期包含:*

1.事务在主库上执行并提交给事务调配一个gtid(由主库的uuid和该服务器上未应用的最小事务序列号),该GTID被写入到binlog中。

2.备库读取relaylog中的gtid,并设置session级别的gtid_next的值,以通知备库下一个事务必须应用这个值

3.备库查看该gtid是否曾经被其应用并记录到他本人的binlog中。slave须要担保之前的事务没有应用这个gtid,也要担保此时已分读取gtid,但未提交的事务也不恩呢过应用这个gtid.

4.因为gtid_next非空,slave不会去生成一个新的gtid,而是应用从主库取得的gtid。这能够保障在一个复制拓扑中的同一个事务gtid不变。因为GTID在全局的唯一性,通过GTID,咱们能够在主动切换时对一些简单的复制拓扑很不便的晋升新主库及新备库,例如通过指向特定的GTID来确定新备库复制坐标。

    GTID是用来代替以前classic的复制办法;

    MySQL5.6.2反对 MySQL5.6.10后欠缺;

GTID相比传统复制的长处:

1.一个事务对应一个惟一ID,一个GTID在一个服务器上只会执行一次

2.GTID是用来代替传统复制的办法,GTID复制与一般复制模式的最大不同就是不须要指定二进制文件名和地位

3.缩小手工干涉和升高服务故障工夫,当主机挂了之后通过软件从泛滥的备机中晋升一台备机为主机

GTID的限度:

1.不反对非事务引擎

2.不反对create table … select 语句复制(主库间接报错)

  原理:( 会生成两个sql,一个是DDL创立表SQL,一个是insert into 插入数据的sql。

  因为DDL会导致主动提交,所以这个sql至多须要两个GTID,然而GTID模式下,只能给这个sql生成一个GTID )  

3.不容许一个SQL同时更新一个事务引擎表和非事务引擎表

4.在一个复制组中,必须要求对立开启GTID或者是敞开GTID

5.开启GTID须要重启(5.7除外)

6.开启GTID后,就不再应用原来的传统复制形式

7.对于create temporary table 和 drop temporary table语句不反对

8.不反对sql_slave_skip_counter

1.3.4 COM_BINLOG_DUMP_GTID

从机发送到主机执行的事务的标识符的主范畴

   Master send all other transactions to slave

  同样的GTID不能被执行两次,如果有同样的GTID,会主动被skip掉。


  slave1:将本人的UUID1:1发送给master,而后接管到了UUID1:2,UUID1:3 event

  slave2:将本人的UUID1:1,UUID1:2发送给master,而后接管到了UUID1:3事件

GTID组成

  GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的惟一标识。TID代表了该实例上曾经提交的事务数量,并且随着事务提交枯燥递增

GTID = source_id :transaction_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29

1.3.5 【示例二】MySQL GTID复制配置

主节点my.cnf文件

# vi /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
server-id=1
log-bin=mysql-bin
socket=/tmp/mysql.sock
binlog-format=ROW
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1

从节点my.cnf文件

# vi /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
server-id=2
binlog-format=ROW
gtid-mode=on
enforce-gtid-consistency=true
log-bin=mysql-bin
log_slave_updates = 1
socket=/tmp/mysql.sock

配置文件注解

server-id=x                    # 同一个复制拓扑中的所有服务器的id号必须惟一
binlog-format=RO               # 二进制日志格局,强烈建议为ROW
gtid-mode=on                   # 启用gtid类型,否则就是一般的复制架构
enforce-gtid-consistency=true  # 强制GTID的一致性
log-slave-updates=1            # slave更新是否记入日志

  复制用户筹备(Master主节点)

mysql>GRANT REPLICATION SLAVE ON *.* TO rep@'10.0.0.%' IDENTIFIED BY '123';

  开启复制(Slave从节点)

mysql>start slave;
mysql>show slave status\G

  当初就能够进行主从复制测试。

1.4 部署MHA

  本次MHA的部署基于GTID复制胜利构建,一般主从复制也能够构建MHA架构。

1.4.1 环境筹备(所有节点操作)

装置依赖包

yum install perl-DBD-MySQL -y

   下载mha软件,mha官网:https://code.google.com/archi…

​ github下载地址:https://github.com/yoshinorim…

*下载软件包*

mha4mysql-manager-0.56-0.el6.noarch.rpm

mha4mysql-manager-0.56.tar.gz

mha4mysql-node-0.56-0.el6.noarch.rpm

mha4mysql-node-0.56.tar.gz

在所有节点装置node

rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm

创立mha治理用户

grant all privileges on *.* to mha@'10.0.0.%' identified by 'mha';

\# 主库上创立,从库会主动复制(在从库上查看)

  创立命令软连贯(重要)

  如果不创立命令软连贯,检测mha复制状况的时候会报错

ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /application/mysql/bin/mysql /usr/bin/mysql

1.4.2 部署治理节点(mha-manager)

在mysql-db03上部署治理节点

# 装置epel源,软件须要
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo 
# 装置manager 依赖包
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
# 装置manager管理软件
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm

创立必须目录

mkdir -p /etc/mha
mkdir -p /var/log/mha/app1    ----》能够治理多套主从复制

编辑mha-manager*配置文件*

[root@db03 ~]# cat  /etc/mha/app1.cnf
[server default]                        
manager_log=/var/log/mha/app1/manager
manager_workdir=/var/log/mha/app1
master_binlog_dir=/data/mysql
user=mha
password=mha
ping_interval=2
repl_password=123
repl_user=repl
ssh_user=root

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306

【配置文件详解】

 [server default]
 2 #设置manager的工作目录
 3 manager_workdir=/var/log/masterha/app1
 4 #设置manager的日志
 5 manager_log=/var/log/masterha/app1/manager.log 
 6 #设置master 保留binlog的地位,以便MHA能够找到master的日志,我这里的也就是mysql的数据目录
 7 master_binlog_dir=/data/mysql
 8 #设置主动failover时候的切换脚本
 9 master_ip_failover_script= /usr/local/bin/master_ip_failover
10 #设置手动切换时候的切换脚本
11 master_ip_online_change_script= /usr/local/bin/master_ip_online_change
12 #设置mysql中root用户的明码,这个明码是前文中创立监控用户的那个明码
13 password=123456
14 #设置监控用户root
15 user=root
16 #设置监控主库,发送ping包的工夫距离,尝试三次没有回应的时候主动进行failover
17 ping_interval=1
18 #设置远端mysql在产生切换时binlog的保留地位
19 remote_workdir=/tmp
20 #设置复制用户的明码
21 repl_password=123456
22 #设置复制环境中的复制用户名 
23 repl_user=rep
24 #设置产生切换后发送的报警的脚本
25 report_script=/usr/local/send_report
26 #一旦MHA到server02的监控之间呈现问题,MHA Manager将会尝试从server03登录到server02
27 secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=10.0.0.51 --master_port=3306
28 #设置故障产生后敞开故障主机脚本(该脚本的次要作用是敞开主机放在产生脑裂,这里没有应用)
29 shutdown_script=""
30 #设置ssh的登录用户名
31 ssh_user=root 
32 
33 [server1]
34 hostname=10.0.0.51
35 port=3306
36 
37 [server2]
38 hostname=10.0.0.52
39 port=3306
40 #设置为候选master,如果设置该参数当前,产生主从切换当前将会将此从库晋升为主库,即便这个主库不是集群中事件最新的slave
41 candidate_master=1
42 #默认状况下如果一个slave落后master 100M的relay logs的话,MHA将不会抉择该slave作为一个新的master,因为对于这个slave的复原须要破费很长时间,通过设置check_repl_delay=0,MHA触发切换在抉择一个新的master的时候将会疏忽复制延时,这个参数对于设置了candidate_master=1的主机十分有用,因为这个候选主在切换的过程中肯定是新的master
43 check_repl_delay=0

配置ssh信赖(密钥散发,在所有节点上执行)

# 生成密钥
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
# 散发公钥,包含本人
for i in 1 2 3 ;do ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.5$i ;done

​ 散发实现后测试散发是否胜利

for i in 1 2 3 ;do ssh 10.0.0.5$i  date ;done
或
[root@db03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
最初一行信息为如下字样即为散发胜利:
Thu Dec 28 18:44:53 2017 - [info] All SSH connection tests passed successfully.

1.4.3 启动mha

通过下面的部署过后,mha架构曾经搭建实现

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

​ 启动胜利后,查看主库状态

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

1.4.4 切换master测试

查看当初的主库是哪个

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

手动进行主库

[root@db01 ~]# /etc/init.d/mysqld stop 
Shutting down MySQL..... SUCCESS!

再进行数据的同时查看日志信息的变动

[root@db03 ~]# tailf /var/log/mha/app1/manager

Fri Dec 29 15:51:14 2017 – [info] All other slaves should start replication from
here. Statement should be: CHANGE MASTER TO MASTER_HOST=’10.0.0.52′, MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER=’repl’, MASTER_PASSWORD=’xxx’;


**修复主从**

① 启动原主库,增加change master to 信息

[root@db01 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
mysql> CHANGE MASTER TO MASTER_HOST=’10.0.0.52′, MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER=’repl’, MASTER_PASSWORD=’123′;
mysql> start slave;


② 查看主从复制状态

mysql> show slave status\G

               Master_Host: 10.0.0.52
         Slave_IO_Running: Yes
        Slave_SQL_Running: Yes

**修复mha**

① 批改app1.cnf配置文件,增加回被剔除主机

[root@db03 ~]# cat /etc/mha/app1.cnf
[binlog1]
hostname=10.0.0.53
master_binlog_dir=/data/mysql/binlog/
no_master=1

[server default]
manager_log=/var/log/mha/app1/manager
manager_workdir=/var/log/mha/app1
master_binlog_dir=/data/mysql
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=mha
ping_interval=2
repl_password=123
repl_user=repl
ssh_user=root
user=mha

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306


② mha查看复制状态

[root@db03 ~]# 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 > /var/log/mha/app1/manager.log 2>&1 &


**到此主库切换胜利**

[root@db03 ~]# masterha_check_status –conf=/etc/mha/app1.cnf
app1 (pid:11978) is running(0:PING_OK), master:10.0.0.52


**试验完结将主库切换回db01.**

① 进行mha

[root@db03 ~]# masterha_stop –conf=/etc/mha/app1.cnf
Stopped app1 successfully.


② 进行所有从库slave(所有库操作)

stop slave;
reset slave all;


③ 重做主从复制(db02、db03)

CHANGE MASTER TO
  MASTER_HOST=’10.0.0.51′,
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1,
  MASTER_USER=’repl’,
  MASTER_PASSWORD=’123′;


④ 启动slave

start slave;


​         启动之后查看从库是否为两个yes show slave status\G 

⑤ mha查看主从复制

[root@db03 ~]# 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 > /var/log/mha/app1/manager.log 2>&1 &


  查看切换是否胜利

[root@db03 ~]# masterha_check_status –conf=/etc/mha/app1.cnf
app1 (pid:12127) is running(0:PING_OK), master:10.0.0.51


​     到此主主节点有切回到db01

### 1.4.5 设置权重

批改[server1]的权重

[server1]
hostname=10.0.0.51
port=3306
candidate_master=1
check_repl_delay=0


配置阐明

candidate_master=1 —-》不管怎样都切到优先级高的主机,个别在主机性能差别的时候用
check_repl_delay=0 —-》不论优先级高的备选库,数据延时多久都要往那切


**注:**

> 1、多地多核心,设置本地节点为高权重
>
> 2、在有半同步复制的环境中,设置半同步复制节点为高权重
>
> 3、你觉着哪个机器适宜做主节点,配置较高的 、性能较好的

## 1.5 配置VIP漂移

### 1.5.1 IP漂移的两种形式

  ???? 通过keepalived的形式,治理虚构IP的漂移

   ???? 通过MHA自带脚本形式,治理虚构IP的漂移

### 1.5.2 MHA脚本形式

**批改mha****配置文件**

[root@db03 ~]# grep “script” /etc/mha/app1.cnf
[server default]
master_ip_failover_script=/usr/local/bin/master_ip_failover


​     再主配置中增加VIP脚本

**脚本内容**

[root@db03 ~]# cat /usr/local/bin/master_ip_failover

!/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 = ‘10.0.0.55/24’;
my $key = ‘0’;
my $ssh_start_vip = “/sbin/ifconfig eth0:$key $vip”;
my $ssh_stop_vip = “/sbin/ifconfig eth0:$key down”;

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" ) {

    my $exit_code = 1;
    eval {
        print "Disabling the VIP on old master: $orig_master_host \n";
        &stop_vip();
        $exit_code = 0;
    };
    if ($@) {
        warn "Got Error: $@\n";
        exit $exit_code;
    }
    exit $exit_code;
}
elsif ( $command eq "start" ) {

    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";
    exit 0;
}
else {
    &usage();
    exit 1;
}

}

sub start_vip() {

`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;

}
sub stop_vip() {

 return 0  unless  ($ssh_user);
`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";

}


  *该脚本为软件自带,脚本获取办法:再mha**源码包中的samples**目录下有该脚本的模板,对该模板进行批改即可应用。门路如: mha4mysql-manager-0.56/samples/scripts* 

  脚本批改内容

my $vip = ‘10.0.0.55/24’;
my $key = ‘0’;
my $ssh_start_vip = “/sbin/ifconfig eth0:$key $vip”;
my $ssh_stop_vip = “/sbin/ifconfig eth0:$key down”;


脚本增加执行权限否则mha无奈启动

chmod +x /usr/local/bin/master_ip_failover


**手动绑定VIP(****主库)**

ifconfig eth0:0 10.0.0.55/24


  查看

[root@db01 ~]# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

link/ether 00:0c:29:6c:7a:11 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0
inet6 fe80::20c:29ff:fe6c:7a11/64 scope link 
   valid_lft forever preferred_lft forever

​     **至此vip****漂移配置实现** 

### 1.5.3 测试虚构IP漂移

查看db02的slave信息

![img](/img/bVErc7) View Code 当初主从状态

停掉主库

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


在db03上查看从库slave信息

![img](/img/bVErc7) View Code 停掉主库后的主从信息

在db01上查看vip信息

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

link/ether 00:0c:29:6c:7a:11 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
inet6 fe80::20c:29ff:fe6c:7a11/64 scope link 
   valid_lft forever preferred_lft forever

在db02上查看vip信息

[root@db02 ~]# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

link/ether 00:0c:29:d6:0a:b3 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.52/24 brd 10.0.0.255 scope global eth0

inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0

inet6 fe80::20c:29ff:fed6:ab3/64 scope link 
   valid_lft forever preferred_lft forever

​     至此,VIP漂移就测试胜利

## 1.6 配置binlog-server

### 1.6.1 配置binlog-server

1)后期筹备:

> 1、筹备一台新的mysql实例(db03),GTID必须开启。
>
> 2、未来binlog接管目录,不能和主库binlog目录一样

2)进行mha

masterha_stop –conf=/etc/mha/app1.cnf


3)在app1.cnf开启binlogserver性能
[binlog1]
no_master=1
hostname=10.0.0.53                         ----> 主机DB03
master_binlog_dir=/data/mysql/binlog/  ----> binlog保留目录

4)开启binlog接管目录,留神权限

mkdir -p /data/mysql/binlog/
chown -R mysql.mysql /data/mysql

进入目录启动程序

cd /data/mysql/binlog/ &&\
mysqlbinlog -R –host=10.0.0.51 –user=mha –password=mha –raw –stop-never mysql-bin.000001 &


  参数阐明:-R 近程主机

5)启动mha

nohup masterha_manager –conf=/etc/mha/app1.cnf –remove_dead_master_conf –ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &


### 1.6.2 测试binlog备份

\#查看binlog目录中的binlog

[root@db03 binlog]# ll
total 44
-rw-r–r– 1 root root 285 Mar 8 03:11 mysql-bin.000001


\#登录主库

[root@mysql-db01 ~]# mysql -uroot -p123


\#刷新binlog

mysql> flush logs;


\#再次查看binlog目录

[root@db03 binlog]# ll
total 48
-rw-r–r– 1 root root 285 Mar 8 03:11 mysql-bin.000001
-rw-r–r– 1 root root 143 Mar 8 04:00 mysql-bin.000002


## 1.7 mysql中间件Atlas

### 1.7.1 atlas简介

  Atlas是由 Qihoo 360公司Web平台部基础架构团队开发保护的一个基于MySQL协定的数据中间层我的项目。它在MySQL官网推出的MySQL-Proxy 0.8.2版本的根底上,批改了大量bug,增加了很多性能个性。目前该我的项目在360公司外部失去了广泛应用,很多MySQL业务曾经接入了Atlas平台,每天承载的读写申请数达几十亿条。

  同时,有超过50家公司在生产环境中部署了Atlas,超过800人已退出了咱们的开发者交换群,并且这些数字还在一直减少。而且装置不便。配置的正文写的蛮具体的,都是中文。

  Atlas官网链接: https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md

  Atlas下载链接: https://github.com/Qihoo360/Atlas/releases

### 1.7.2 次要性能

  读写拆散、从库负载平衡、主动分表、IP过滤

  SQL语句黑白名单、DBA可平滑高低线DB、主动摘除宕机的DB

*Atlas**绝对于官网MySQL-Proxy**的劣势*

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

### 1.7.3 应用场景

  Atlas是一个位于前端利用与后端MySQL数据库之间的中间件,它使得利用程序员无需再关怀读写拆散、分表等与MySQL相干的细节,能够专一于编写业务逻辑,同时使得DBA的运维工作对前端利用通明,高低线DB前端利用无感知。

![file](/img/bVcLBxB)
  Atlas是一个位于应用程序与MySQL之间中间件。在后端DB看来,Atlas相当于连贯它的客户端,在前端利用看来,Atlas相当于一个DB。

  Atlas作为服务端与应用程序通信,它实现了MySQL的客户端和服务端协定,同时作为客户端与MySQL通信。它对应用程序屏蔽了DB的细节,同时为了升高MySQL累赘,它还保护了连接池.

### 1.7.4 企业读写拆散及分库分表其余计划介绍

>   Mysql-proxy(oracle)
>
>   Mysql-router(oracle)
>
>   Atlas (Qihoo 360)
>
>   Atlas-sharding (Qihoo 360)
>
>   Cobar(是阿里巴巴(B2B)部门开发)
>
>   Mycat(基于阿里开源的Cobar产品而研发)
>
>   TDDL Smart Client的形式(淘宝)
>
>   Oceanus(58同城数据库中间件)
>
>   OneProxy(原支付宝首席架构师楼方鑫开发 )
>
>   vitess(谷歌开发的数据库中间件)
>
>   Heisenberg(百度)
>
>   TSharding(蘑菇街白辉)
>
>   Xx-dbproxy(金山的Kingshard、当当网的sharding-jdbc )
>
>   amoeba

### 1.7.5 装置Atlas

  软件获取地址:https://github.com/Qihoo360/Atlas/releases

*留神:*

> 1、Atlas只能装置运行在64位的零碎上
>
> 2、Centos 5.X装置 Atlas-XX.el5.x86_64.rpm,Centos 6.X装置Atlas-XX.el6.x86_64.rpm。
>
> 3、后端mysql版本应大于5.1,倡议应用Mysql 5.6以上
>
>   Atlas (一般) : Atlas-2.2.1.el6.x86_64.rpm
>
>   Atlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm

 下载安装atlas

wget https://github.com/Qihoo360/A…
rpm -ivh Atlas-2.2.1.el6.x86_64.rpm


​     至此装置实现

### 1.7.6 配置Atlas配置文件

  atlas配置文件中的明码须要加密,能够应用,软件自带的加密工具进行加密

cd /usr/local/mysql-proxy/conf/
/usr/local/mysql-proxy/bin/encrypt 明码 —->制作加密明码


生产密文明码:

[root@db03 bin]# /usr/local/mysql-proxy/bin/encrypt 123
3yb5jEku5h4=
[root@db03 bin]# /usr/local/mysql-proxy/bin/encrypt mha
O2jBXONX098=


编辑配置文件

vim /usr/local/mysql-proxy/conf/test.cnf
[mysql-proxy]
admin-username = user
admin-password = pwd
proxy-backend-addresses = 10.0.0.55:3306
proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306
pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098=
daemon = true
keepalive = true
event-threads = 8
log-level = message
log-path = /usr/local/mysql-proxy/log
sql-log=ON
proxy-address = 0.0.0.0:33060
admin-address = 0.0.0.0:2345
charset=utf8


配置文件内为全中文正文,这里有一份较为具体的解释:

![img](/img/bVErc7) View Code Atlas配置文件阐明

### 1.7.7 启动Atlas

编写一个atlas的治理脚本,当然也能够写脚本,能够间接手动的治理:

/usr/local/mysql-proxy/bin/mysql-proxyd test start #启动
/usr/local/mysql-proxy/bin/mysql-proxyd test stop #进行
/usr/local/mysql-proxy/bin/mysql-proxyd test restart #重启


  留神:test是配置文件的名称

脚本内容:

![img](/img/bVErc7) View Code Atas治理脚本

查看端口是否失常

[root@db03 ~]# netstat -lntup|grep mysql-proxy
tcp 0 0 0.0.0.0:33060 0.0.0.0:* LISTEN 2125/mysql-proxy
tcp 0 0 0.0.0.0:2345 0.0.0.0:* LISTEN 2125/mysql-proxy


### 1.7.8 Atlas治理操作

  登入治理接口

[root@db03 ~]# mysql -uuser -ppwd -h127.0.0.1 -P2345


  查看帮忙信息

mysql> SELECT * FROM help;


  查看后端的代理库
mysql> SELECT * FROM backends;
backend_ndx address state type
1 10.0.0.55:3306 up rw
2 10.0.0.52:3306 up ro
3 10.0.0.53:3306 up ro

3 rows in set (0.00 sec)


  平滑摘除mysql

mysql> REMOVE BACKEND 2;
Empty set (0.00 sec)


   查看是否摘除
mysql> SELECT * FROM backends;
backend_ndx address state type
1 10.0.0.55:3306 up rw
2 10.0.0.53:3306 up ro

2 rows in set (0.00 sec)


  保留到配置文件中

mysql> SAVE CONFIG;


  将节点再增加回来

mysql> add slave 10.0.0.52:3306;
Empty set (0.00 sec)


  查看是否增加胜利
mysql> SELECT * FROM backends;
backend_ndx address state type
1 10.0.0.55:3306 up rw
2 10.0.0.53:3306 up ro
3 10.0.0.52:3306 up ro

3 rows in set (0.00 sec)


 保留到配置文件中

mysql> SAVE CONFIG;


### 1.7.9 连贯数据库查看负载

通过atlas登陆数据,留神,应用的是数据库上的用户及明码

shell> mysql -umha -pmha -h127.0.0.1 -P33060


第一次查问server_id
mysql> show variables like “server_id”;
Variable_name Value
server_id 53

1 row in set (0.00 sec)


第二次查问server_id
mysql> show variables like “server_id”;
Variable_name Value
server_id 52

1 row in set (0.00 sec)


​     ***通过下面能够看到负载胜利\***

### 1.7.10 读写拆散的阐明

  Atlas会通明的将事务语句和写语句发送至主库执行,读语句发送至从库执行。具体以下语句会在主库执行:

显式事务中的语句

> autocommit=0时的所有语句
>
> 含有select GET_LOCK()的语句
>
> 除SELECT、SET、USE、SHOW、DESC、EXPLAIN外的。

**从库负载平衡配置**

proxy-read-only-backend-addresses=ip1:port1@权重,ip2:port2@权重


### 1.7.11 Atlas高级性能

**主动分表**

  应用Atlas的分表性能时,首先须要在配置文件test.cnf设置tables参数。

tables参数设置格局:数据库名.表名.分表字段.子表数量,比方:

> 你的数据库名叫school,表名叫stu,分表字段叫id,总共分为2张表,那么就写为school.stu.id.2,如果还有其余的分表,以逗号分隔即可。
>
> 用户须要手动建设2张子表(stu_0,stu_1,留神子表序号是从0开始的)。
>
> 所有的子表必须在DB的同一个database里。
>
> 当通过Atlas执行(SELECT、DELETE、UPDATE、INSERT、REPLACE)操作时,Atlas会依据分表后果(id%2=k),定位到相应的子表(stu_k)。
>
> 例如,执行select * from stu where id=3;,Atlas会主动从stu_1这张子表返回查问后果。
>
> 但如果执行SQL语句(select * from stu;)时不带上id,则会提醒执行stu表不存在。

Atles性能的阐明

> Atlas暂不反对主动建表和跨库分表的性能。
>
> Atlas目前反对分表的语句有SELECT、DELETE、UPDATE、INSERT、REPLACE。

**IP****过滤:client-ips**

  该参数用来实现IP过滤性能。

  在传统的开发模式中,应用程序间接连贯DB,因而DB会对部署利用的机器(比方web服务器)的IP作拜访受权。

在引入中间层后,因为连贯DB的是Atlas,所以DB改为对部署Atlas的机器的IP作拜访受权,如果任意一台客户端都能够连贯Atlas,就会带来潜在的危险。

  client-ips参数用来管制连贯Atlas的客户端的IP,能够是准确IP,也能够是IP段,以逗号分隔写在一行上即可。

  如: client-ips=**192.168**.**1.2**, **192.168**.**2** 

  这就代表192.168.1.2这个IP和192.168.2.*这个段的IP能够连贯Atlas,其余IP均不能连贯。如果该参数不设置,则任意IP均可连贯Atlas。如果设置了client-ips参数,且Atlas后面挂有LVS,则必须设置lvs-ips参数,否则能够不设置lvs-ips。

**SQL****语句黑白名单性能:** Atlas会屏蔽不带where条件的delete和update操作,以及sleep函数。

## 1.8 Atlas-Sharding版本

### 1.8.1 版本介绍

  Sharding的根本思维就是把一个数据表中的数据切分成多个局部, 寄存到不同的主机下来(切分的策略有多种), 从而缓解单台机器的性能跟容量的问题.

  sharding是一种程度切分, 实用于单表数据宏大的情景. 目前atlas反对动态的

  sharding计划, 临时不反对数据的主动迁徙以及数据组的动静退出.

  Atlas以表为单位sharding, 同一个数据库内能够同时共有sharding的表和不sharding的表, 不sharding的表数据存在未sharding的数据库组中.

  目前Atlas sharding反对insert, delete, select, update语句, 只反对不跨shard的事务. 所有的写操作如insert, delete, update只能一次命中一个组, 否则会报"ERROR 1105 (HY000):write operation is only allow to one dbgroup!"谬误.

  因为sharding取替了Atlas的分表性能, 所以在Sharding分支外面, Atlas单机分表的性能曾经移除, 配置tables将不会再无效.

### 1.8.2 Atlas-Sharding架构

![file](/img/bVcLBxC)
### 1.8.3 Sharding配置示例

  Atlas反对非sharding跟sharding的表共存在同一个Atlas中, 2.2.1之前的配置能够间接运行. 之前的配置如

proxy-backend-addresses = 192.168.0.12:3306
proxy-read-only-backend-addresses = 192.168.0.13:3306,192.168.0.14:3306 …


  这配置了一个master和两个slave,这属于非sharding的组, 所有非sharding的表跟语句都会发往这个组内. 

  所以之前没有Sharding的Atlas的表能够无缝的在新版上应用,

​     **留神:** 非Sharding的组只能配置一个, 而sharding的组能够配置多个. 上面的配置, 配置了Sharding的组, 留神与下面的配置辨别

[shardrule-0]
table = test.sharding_test


  分表名,有数据库+表名组成 t

ype = range


  sharding类型:range 或 hash

shard-key = id


  sharding 字段

groups = 0:0-999,1:1000-1999


  分片的group,如果是range类型的sharding,则groups的格局是:group_id:id范畴。如果是hash类型的sharding,则groups的格局是:group_id。例如groups = 0, 1

[group-0]
proxy-backend-addresses=192.168.0.15:3306
proxy-read-only-backend-addresses=192.168.0.16:3306
[group-1]
proxy-backend-addresses=192.168.0.17:3306
proxy-read-only-backend-addresses=192.168.0.18:3306


### 1.8.4 Sharding限度

**对于反对的语句**

  Atlas sharding只对sql语句提供无限的反对, 目前反对根本的Select, insert/replace, delete,update语句,反对全副的Where语法(SQL-92规范), 不反对DDL(create drop alter)以及一些治理语句,DDL请直连MYSQL执行, 请只在Atlas上执行Select, insert, delete, update(CRUD)语句.

  对于以下语句, 如果语句命中了多台dbgroup, Atlas均未做反对(如果语句只命中了一个dbgroup, 如 select count(*) from test where id < 1000, 其中dbgroup0范畴是0 - 1000, 那么这些个性都是反对的)Limit Offset(反对Limit) 

> Order by
>
> Group by Join
>
> ON
>
> Count, Max, Min等函数

**减少节点**

  留神: 临时只反对range形式的节点扩大, hash形式因为须要数据迁徙, 临时未做反对.

  扩大节点在保障原来节点的范畴不扭转的状况下, 如已有dbgroup0为范畴0 - 999, dbgroup1为范畴 1000-1999, 这个时候能够减少范畴>2000的节点. 如减少一个节点为2000 - 2999, 批改配置文件, 重启Atlas即可.


> 起源:博客园  http://dwz.date/d8qV

>  欢送关注公众号 【码农开花】一起学习成长
> 我会始终分享Java干货,也会分享收费的学习材料课程和面试宝典

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理