mysql高可用架构之MHA,haproxy实现读写分离详解

haproxy实现读写分离详解

 

                    

MHA实现机制:

              监控AB的状态

              完整的选举机制(看谁的数据跟master最接近)

              让一个B切换到新A

              保证数据的完整性(通过差异还原)

                    

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

   该软件由两部分组成: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从,但是master主机宕机后无法切换,以及无法补全binlog。master的mysqld进程crash后,还是可以切换成功,以及补全binlog的。

 

 

 

假如MySQL MHA架构运行正常,突然在上午10:00一个复制组中的A的MySQL服务 down了!

因为AB复制是异步复制,所以可能有一些数据尚没有被B拉到其relay_log中,即AB数据不一致,MHA是怎样解决这种情况的呢?

       1、mha_manager 使用scp命令将A当前binlog拷贝到mha_manager

       2、待新A(选举:依据谁的relay_log新)产生后,mha_manager再拿着旧A的binlog和新的relay_log做比对,并进行差异还原以保证新A和旧A数据的一致性

      3、mha_manager最后拿着老A的binlog去找复制组中其他B 做差异还原,保证数据的一致性

 

实验步骤:

1)            ssh证书户信任(ssh的密钥验证)

2)            ABB架构()

3)            安装mha_manager  、 mha_node

4)            测试

 

IP地址规划

Mysql_manager(18.240)—需要是64位的系统

MySQL_A(18.241) master

MySQL_B1(18.242) slave1

MySQL_B2(18.243) slave2

 

1、ssh证书互信脚本---每台机器上都要操作

1.1使用ssh-kegen生成公私钥(每台服务器上)

1.2执行脚本

#!/bin/bash

for i in 0 1 2 3

        do

                ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.18.24$i

        done

 

2、ABB搭建

2.1测试yum仓库的可用性脚本

#!/bin/bash

for i in 0 1 2 3

        do

                ssh 192.168.18.24$i     "

                if ( yum install telnet-server -y ) > /dev/null 2>&1;then

                                echo "192.168.18.24$i Yum is TURE"

                        else

                                echo "192.168.18.24$i Yum is FALSE "

                fi

                "

        done

 

2.2安装脚本:

#!/bin/bash

for i in 0 1 2 3

        do

                ssh 192.168.18.24$i     "

                if ( yum install mysql mysql-server perl-* -y ) > /dev/null 2>&1;then

                                echo "192.168.18.24$i installation finish"

                        else

                                echo "192.168.18.24$i installation error "

                fi

                "

        done

 

2.3所有的机器初始化MySQL,设置ABB架构:

MYSQL_A(241)上的操作:

vim /etc/my.cnf

server_id=1       //设置优先级最高

log_bin=binlog  //开启binlog日志

log_biin=binlog.index

 

MYSQL_B1、MYSQL_B2上的操作同mysql_a只是注意server_id的不同

 

2.4 设置用户

在msyql_a(241)中:因为前面已经开启二进制日志了,所以其他机器也能学到赋权语句!!故,其他机器就不用再赋权了!

> grant all on *.* to “root”@“%” identified by “123”;    //给mha_manager用,因为其在failover时需要登陆上来,并且拷贝binlog到所有的slave上去。

> grant replication slave on *.* to “sky”@“%”identified by “123”;  //复制专用用户

> flush privileges;    //刷新权限

> show master status\G        //看一下binlog日志到第几个文件

 

在mysql_b1(242)中:

  • slave stop;
  • change master to master_host=”192.168.18.241”,master_user=”sky”,master_passoword=”123”,master_log_file=”binlog.000001”;
  • slave start;
  • show slave status\G        //查看复制线程状态

 

在mysql_b2(243)做242上同样的操作!

 

 

3、安装配置启动mha_manager、mha_node

3.1安装

manager机器上:

#安装依赖
yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Config-IniFiles perl-Time-HiRes
#安装node
yum install -y mha4mysql-node-0.56-0.el6.noarch.rpm
#安装manager
yum install -y mha4mysql-manager-0.56-0.el6.noarch.rpm 

mha_manager的配置文件:(没找到就自己创建)

mha目录下主要有以下两个文件

mha.cnf   mha_start

mkdir /etc/mha/

[root@localhost mha]# vim /etc/mha/mha.cnf            //mha配置文件

[server default]
#mysql admin account and password

user=root
password=123

#mha workdir  and worklog

manager_workdir=/etc/mha
manager_log=/etc/mha/manager.log

#mysql A/B account and pw

repl_user=sky
repl_password=123

#check_mha_node time
ping_interval=1

#ssh account
ssh_user=root


[server1]
hostname=192.168.18.241
ssh_port=22
master_binlog_dir=/var/lib/mysql
candidate_master=1


[server2]
hostname=192.168.18.242
ssh_port=22
master_binlog_dir=/var/lib/mysql
candidate_master=1


[server3]
hostname=192.168.18.243
ssh_port=22
master_binlog_dir=/var/lib/mysql
candidate_master=1

 

vim /etc/mha/mha_start       //启动脚本

nohup masterha_manager --conf=/etc/mha/mha.cnf > /etc/mha/manager.log </dev/null 2>&1 &

 

 

其他节点:

       安装mha4mysql-node…rpm包(直接rpm安装即可)

 

3.2 检测ssh互信有没有问题

[root@localhost src]# masterha_check_ssh --conf=/etc/mha/mha.cnf

Tue Jun 13 02:21:31 2017 - [info] All SSH connection tests passed successfully.

 

3.3 检测ABB主从状态

[root@localhost src]# masterha_check_repl --conf=/etc/mha/mha.cnf

MySQL Replication Health is OK.

 

3.4 启动

[root@localhost src]# cat /etc/mha/mha_start    //先看一下启动方式

nohup masterha_manager --conf=/etc/mha/mha.cnf > /etc/mha/manager.log </dev/null 2>&1 &

运行:

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

 

3.5 测试

现在两个slave的Master_Host同为241,把241干掉后,就会选举新的master了!

 

先在mha_manager上打开日志:

# tailf /etc/mha/manager.log

 

到241上关闭MySQL服务:

service mysqld stop

 

查看manager.log日志输出:

…           //此处省略

----- Failover Report -----

 

mha: MySQL Master failover 192.168.18.241 to 192.168.18.242 succeeded

 

Master 192.168.18.241 is down!

 

Check MHA Manager logs at localhost.localdomain:/etc/mha/manager.log for details.

 

Started automated(non-interactive) failover.

The latest slave 192.168.18.242(192.168.18.242:3306) has all relay logs for recovery.

Selected 192.168.18.242 as a new master.

192.168.18.242: OK: Applying all logs succeeded.

192.168.18.243: This host has the latest relay log events.

Generating relay diff files from the latest slave succeeded.

192.168.18.243: OK: Applying all logs succeeded. Slave started, replicating from 192.168.18.242.

192.168.18.242: Resetting slave info succeeded.

Master failover to 192.168.18.242(192.168.18.242:3306) completed successfully.

 

看来242变成了master!~

       可以去新主上创建个库或到243上查看一下master.info来验证!!

 

老master恢复后如果想要它再做master,要先将新master的数据同步,之后删除下面两个文件,再重新开启MHA功能,令新master宕掉即可(实验可行,实际操作不推荐)如下:

注意:mha_manager每执行一次failover后,该进程自动退出。如果还想测试failover需要重新开启---开启前要将下面两个文件删掉:

[root@MHA_243 mha]# cd /etc/mha/

[root@MHA_243 mha]# rm -fr mha.failover.complete saved_master_binlog_from_192.168.19.241_3306_20170817154913.binlog

             

 

下面演示old_master回来,如何保证old_master同步new_master新产生的数据:

当old_master服务宕掉后,去mha_monitor上执行:

[root@mha_master mha]# grep -i change /etc/mha/manager.log (-i 是不区分大小写)

Tue Jun 13 02:30:23 2017 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='192.168.18.242', MASTER_PORT=3306, MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=106, MASTER_USER='sky', MASTER_PASSWORD='xxx';

 

然后在old_master上执行:

mysql> slave stop;

mysql> change master to  master_host='192.168.18.242', master_port=3306, master_log_file='binlog.000001', master_log_pos=106, master_user='sky', master_password='123';(只需要修改密码即可)

mysql> slave start;

 

 

4、MHA failover(master故障)后VIP漂移

       MHA架构中,master来承担写请求,但是如果发生了failover,那么就应该让new_master来承担写请求,有哪些方式可以实现呢?

1、     改变master的IP:在web上修改PHP页面的代码(所有写请求修改成new_master的IP)

2、     使用虚拟IP(VIP),将VIP漂移给new_master

       显然,第二种方案要更加容易实现、高效。

       实现起来,大家可能会首当其冲的想到keepalived,但是在这里不适用,因为我们不好判断哪一个salve会在failover后变成master(在keepalived中,VIP根据物理路由器的优先级来确定,万一漂到一台slave上那可如何是好!)。不过我们可以通过脚本的方式来实现将VIP绑定到new_master上。

       脚本思路如下:

       脚本(/etc/mha/check_mysql)运行在manager上,它来管理VIP

       判断谁是主,确保它有VIP,并继续判断,如果slave有VIP,则收回。

 

脚本名称:master_vip_drift.sh

 脚本需要根据前面设置的数据库密码对应修改,此处设置的为用户root,密码123

#!/bin/bash
VIP=192.168.18.245
NETMASK=255.255.255.0
MUSER=root
MPW=123
MYSQL_IP="192.168.18.241 192.168.18.242 192.168.18.243"
NIC=eth0
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~main program~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#check_master_mysql
check_master() {       #检测谁是master
for IP in $MYSQL_IP
do
      if ssh $IP "lsof -i :3306" &>/dev/null;then
      ssh $IP "mysql -uroot -p123 -e 'show slave status \G'|grep -w 'Slave_IO_Running'" &>/dev/null
       if [ $? -eq 1 ];then
        MY_master=$IP
    echo "$MY_master"
       fi
     fi
done
}

check_master_alive() {  #检测master的存活状态
for IP in $MYSQL_ip 
do
      if ssh $IP "ip add show eth0"|grep inet|grep "$VIP" &>/dev/null;then
    ssh $IP "lsof -i:3306" &>/dev/null
      if [ $? -ne 0 ];then
    ssh $IP "ifconfig $NIC:245 down "
      fi
      fi
done
}


VIP () {    #给master赋予VIP,不是master收回VIP
for IP in $MYSQL_IP
     do
          ssh $IP "ip add show eth0"|grep inet|grep "$VIP" &>/dev/null
            if [ $? -eq 0 ] && [ $MY_master != "$IP" ];then       #如果有VIP但是不是master,收回VIP
                ssh $IP "ifconfig $NIC:245 down"
            elif [ $? -eq 1 ] && [ $MY_master == "$IP" ];then    #如果没有VIP却是master,赋予其VIP
                ssh $IP "ifconfig $NIC:245 $VIP netmask $NETMASK up"
            fi
done
}

while true
   do
      check_master
      check_master_alive
      VIP
      sleep 1
done

 

 

当前实验环境:

241              mysql_A

243              mysql_B2    

242              mysql_B1           新 master

245              VIP

240              mha_monitor    

 

1. 重新运行masterha_manager:

[root@mha_master mha]# nohup masterha_manager --conf=/etc/mha/mha.cnf > /tmp/mha_manager.log </dev/null 2>&1 &

 

2. 重新运行脚本master_vip_drift.sh

[root@mha_master mha]# ./master_vip_drift.sh  &

 

3. 去242上检查VIP有没有绑定上

 

4. 模拟242的MySQL服务宕掉

 

5. 看看monitor上的日志,找出谁是新master

 

6、验证241上有没有VIP,242上的VIP有没有被收回

 

***monitor进行一次failover后自动关闭,还需手动运行

***需手动删除/etc/mha/下的失败切换文件failover file和binlog,否则failover不成功!

 

5、分析failover日志—了解MHA工作流程

5.1 tailf /etc/mha/manager.log

5.2 到master上关闭MySQL服务

5.3 查看日志并从头往下捋一遍

 

以上操作可得出脚本能实现在master宕机后,VIP重新漂移绑定至新的master,下面完成slave集群的读写分离实验。

 

6、MySQL MHA读写分离后将slave做成集群

用的是HAProxy这款支持七层和四层分发的将slave做成集群,来承担读请求

 

实现读写分离:

       如:通过修改PHP页面中绑定的IP地址,master承担请求用VIP,slave集群承担请求用haproxyIP

 

实验环境:

241              mysql_a              //master

242              mysql_b1   

243              mysql_b2          

245              VIP(master)

246              mha_monitor

247              HAProxy

248              client/httpd(lamp)

 

大致结构图如下:

 

 

结构图说明:

a.MHA对abb架构实行监控,发现a宕之后选出新a(实现VIP漂移,仅a有VIP)

b.haproxy对slave集群实现负载均衡,承担读请求

c.web集群请求后台数据,写请求传给a(VIP),读请求传给haproxy,haproxy再对读请求实现分发达到负载均衡

 

6.1  安装HAProxy

yum install gcc -y

tar xf haproxy-1.5.3.tar

make TARGET=linux26 PREFIX=/usr/local/haproxy

make install PREFIX=/usr/local/haproxy

cp /usr/src/haproxy/haproxy-1.5.3/examples/haproxy.cfg /usr/local/haproxy/

cp /usr/src/haproxy/haproxy-1.5.3/examples/haproxy.init /etc/init.d/haproxy

chmod 755 /etc/init.d/haproxy

ln -s /usr/local/haproxy/sbin/* /usr/sbin/

mkdir /etc/haproxy

mkdir /usr/share/haproxy

ln -s /usr/local/haproxy/haproxy.cfg /etc/haproxy/

cd ..

 

6.2  设置配置文件

6.2.1 拷贝配置文件

[root@HAProxy_247 haproxy]# cp haproxy.cfg  /usr/local/haproxy/

cp: overwrite `/usr/local/haproxy/haproxy.cfg'? y

 

6.2.2      编辑配置文件

[root@HAProxy_247 haproxy]# vim /usr/local/haproxy/haproxy.cfg

注意修改RS的IP:

# this config needs haproxy-1.1.28 or haproxy-1.2.1

global
    log 127.0.0.1    local0
    log 127.0.0.1    local1 notice
    #log loghost    local0 info
    maxconn 4096
    chroot /usr/share/haproxy
    uid 99
    gid 99
    daemon
    #debug
    #quiet

defaults
    log    global
    mode    http
    #option    httplog
    option    dontlognull
    retries    3
    option redispatch
    maxconn    2000
    contimeout    5000
    clitimeout    50000
    srvtimeout    50000


listen    MySQL 0.0.0.0:3306
    mode tcp
    maxconn    200
    balance roundrobin
    option mysql-check user root
    server mysql_1 192.168.18.242:3306  inter 1s rise 2 fall 2
    server mysql_2 192.168.18.243:3306  inter 1s rise 2 fall 2


listen  admin_status
        mode  http
        bind 0.0.0.0:8899
        option httplog
        log global
        stats enable
        stats refresh 10s
        stats hide-version
        stats realm Haproxy\ Statistics
        stats uri  /admin-status 
        stats auth  admin:123456 
        stats admin if TRUE

注:值得一提的是:如果haproxy配置集群的slave机被选做了新的master,需要修改配置文件将这台新master地址去掉,

并加上旧master(宕掉后重启已做slave)地址,然后重启haproxy。 (当然也可以不即时操作,master也可以承担部分读请求,在访问量少的时候再修改)

 

6.3  启动HAProxy服务

[root@HAProxy_247 haproxy]# service haproxy start

 

6.4  访问HAProxy的网页

http://localhost:8899/admin-status

用户名密码查看配置文件设置

 

6.5  客户端测试---密码123 

 

6.6 回到HAProxy管理界面,可以看到那台slave响应的请求

 

 

实验完成!

 

posted @ 2017-12-13 15:59  叮伱格斐呃  阅读(6918)  评论(0编辑  收藏  举报
Live2D