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

66次阅读

共计 24507 个字符,预计需要花费 62 分钟才能阅读完成。

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 干货,也会分享收费的学习材料课程和面试宝典

正文完
 0