搭建mysql负载均衡及高可用环境

目标:使用两台主机实现 Mysql 的负载均衡及冗余,并做到双主互备;

环境:rhel5.8,mysql-5.0.77,keepalived-1.2.7,haproxy-1.4.20;

说明:

keepalived 实现通过 vrrp协议,通过使一个虚拟IP地址(或称浮动IP)在主备设备间的切换来达到主机冗余;

而客户机通过访问这个虚拟IP 来获取服务;

haproxy 是一款负载均衡软件,用于将请求按策略转发给不同主机,达到负载均衡的效果;

可以实现网络层或应用层上的判断分配;

mysql 开启二进制日志,做到数据库之间的双向复制,保持数据一致性;

#提醒一下,实际生产环境没人会这样搭建的,仅通过这个实验来理解这些概念,希望阅者能有所获;

server1_ip=192.168.5.11

server2_ip=192.168.5.12

server_vip=192.168.5.111

================================================

#此处关闭了防火墙,开启则另配置相应规则

service iptables stop

chkconfig iptables off

ls /opt/soft/ #提取准备软件到此处

haproxy-1.4.20.tar.gz  keepalived-1.2.7.tar.gz

mkdir /opt/keepalived

mkdir /opt/scripts/ #此实验用到脚本目录

mkdir /opt/log/ #此实验日志文件夹

=================================================

[install_mysql]

#在两台主机上安装 mysql ,此处使用 rpm 包安装,yum环境可以搭本地源;

yum install -y mysql-server

service mysqld start

=======================================================

[create_mysql_test_table]

#分别创建一张相同名称和字段的表,插入不同的值,方便中途测试 ha 和轮询是否成功;

#还有分别创建一个相同的用户

#server1

mysql

>use test;

>create table mywait(name char(9),phone char(14));

>insert into mywait(name,phone) values('wait',15000000000);

#server2

>use test;

>create table mywait(name char(9),phone char(14));

>insert into mywait(name,phone) values('chen',15611111111);

[new_mysql_test_user]

>mysql

>grant all on test.* to diaosi@'%' identified by '123456';

>flush privileges;

=======================================================

#从客户机上测试一下;

mysql -udiaosi -p123456 -h 192.168.5.11 -e "select * from test.mywait;"

mysql -udiaosi -p123456 -h 192.168.5.12 -e "select * from test.mywait;"

#至此,mysql 基础环境搭建完成;

=======================================================

[install_keepalived]

yum install -y libnl-devel #解决依赖关系

tar xf /opt/soft/keepalived-1.2.7.tar.gz -C /opt/soft

cd /opt/soft/keepalived-1.2.7/

#with-kernel 指定内核版本时,根据本机情况使用TAB键补全

./configure --prefix=/opt/keepalived --with-kernel-dir=/usr/src/kernels/2.6.18-308.el5-i686/

make && make install

[keepalived_config]

#因为没有安装在 / 目录下,所以这些启动和配置文件都需要再 copy 一下;

cp /opt/keepalived/sbin/keepalived /usr/sbin/

cp /opt/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

cp /opt/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

mkdir /etc/keepalived

cp /opt/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/

chkconfig keepalived on #设置开机启动

=======================================================

vim /etc/keepalived/keepalived.conf #keepalived 主配文件

#以下的配置适合 keepalived 本身便是服务提供者的情况;

  
  
  
  
  1. ! Configuration File for keepalived  
  2.  
  3. #简单的头部,这里主要可以做邮件通知报警等的设置,此处就暂不配置了;  
  4. global_defs {  
  5.         notificationd LVS_DEVEL  
  6. }  
  7.  
  8. #预先定义一个脚本,方便后面调用,也可以定义多个,方便选择;  
  9. vrrp_script mysql_chk {  
  10.         script "/opt/scripts/mysql_chke.sh" 
  11.         interval 2      #脚本循环运行间隔  
  12.         weight 2        #脚本的结果导致优先级变更,成功+2  
  13. }  
  14. #VRRP虚拟路由冗余协议配置  
  15. vrrp_instance VI_1 {            #VI_1 是自定义的名称;  
  16.         state MASTER            #表明这是一台主设备,备用设备为 BACKUP  
  17.         interface eth0              #指定VIP需要绑定的物理网卡  
  18.         virtual_router_id 11        #VRID虚拟路由标识,也叫做分组名称,该组内的设备需要相同  
  19.         priority 150            #定义这台设备的优先级 1-254;  
  20.         advert_int 1            #生存检测时的组播信息发送间隔,组内一致  
  21.  
  22.         authentication {        #设置验证信息,组内一致  
  23.                 auth_type PASS          #有PASS 和 AH 两种,常用 PASS  
  24.                 auth_pass 111           #密码  
  25.         }  
  26.  
  27.         virtual_ipaddress {     #指定VIP地址,组内一致,可以设置多个IP  
  28.                 192.168.5.111/24  
  29.         }  
  30.  
  31.         track_script {      #使用在这个域中使用预先定义的脚本  
  32.                 mysql_chk  
  33.         }  
  34.  
  35.     #此部分所载入的脚本为外部脚本,不需要预先定义;  
  36.     #也可不添加,此实验在后半部分安装haproxy后,才有添加;  
  37.         notify_master /opt/scripts/start_haproxy.sh #表示当切换到master状态时,要执行的脚本  
  38.         notify_fault /opt/scripts/stop_keepalived.sh    #故障时执行的脚本  
  39.         notify_stop /opt/scripts/stop_haproxy.sh        #keepalived停止运行前运行的脚本  

#keepalived 主和备的配置文件基本相同;只需要修改:

state BACKUP #修改为备份设备

priority 100 #优先级要比主低

#其它地方根据实际情况也可以做调整;

=======================================================

#新建刚才配置keepalived 时所定义的脚本,用于在mysql 死亡后结束 keepalived

  
  
  
  
  1. #!/bin/bash  
  2. #mysql_chke.sh  
  3. #  
  4. a=`ps -C mysqld --no-header | wc -l`  
  5. if [ $a -eq 0 ];then 
  6.         sleep 3  
  7.                 /sbin/service keepalived stop  
  8.                 echo "`date +%c` stop keepalived" >> /opt/log/stop_keepalived.log  
  9.         fi  
  10. fi 

service keepalived start #在两台设备上面启动

#开始测试

ip address

#查看主设备 11 上是否有生成 vip 地址;

#注意事项,keepalived 生成的 VIP 对 ifconfig 命令不可见,所以需要使用 ip 命令;

mysql -udiaosi -p123456 -h 192.168.5.111 -e "select * from test.mywait;"

#正常情况是只能查询到 MASTER 的数据库的数据;

1、尝试将 MASTER 的keepalived 停掉

2、down 掉 MASTER 的网卡

3、让mysql 启动不了,比如先注释掉mysql这个用户,后killall mysqld ,

查看mysql_chke 脚本是否会把 keepalived 结束掉;

#这个时后 vip 地址会移动到 Slave 主机上; HA 搭建的是否成功体现于查询所获取值的变化;

#当将 MASTER 恢复后,VIP 又会回到 11 的设备上;

#至此 keepalived 为 mysql 做HA 模式成功;

========================================================================

[install_haproxy]

#用于将请求分别轮询到 192.168.5.11 192.168.5.12

tar xf /opt/soft/haproxy-1.4.20.tar.gz -C /opt/soft/

cd /opt/soft/haproxy-1.4.20/

make TARGET=linux26 PREFIX=/opt/haproxy install

mkdir /opt/haproxy/conf

mkdir /opt/haproxy/logs

touch /opt/haproxy/conf/haproxy.cfg

========================================================================

[mysql_config]

#修改 mysql 监听,使 mysql 避开 192.168.5.111,因为 haproxy 也要监听 111:3306 这个IP地址和端口;

vim /etc/my.cnf

#server1

[mysqld]

bind-address=192.168.5.11 #mysql 的监听,添加这一句就好了

#server2

[mysqld]

bind-address=192.168.5.12

#重启mysql

service mysqld restart

#到现在已经不能通过 192.168.5.111 访问数据库了,接下来配置 haproxy

========================================================================

[config_haproxy]

#主备服务器的主配文件一致;

vim /opt/haproxy/conf/haproxy.cfg

  
  
  
  
  1. global          #全局系统配置  
  2.         log 127.0.0.1 local0 info   #定义日志级别[err warning info debug]  
  3.                     #local0 是日志设备,必须为24种标准syslog设备之一;  
  4.         maxconn 4096        #最大链接数  
  5.         uid 0           #运行该程序的用户,此处没有其它用户了,就用的 root  
  6.         gid 0  
  7.         daemon          #以后台形式运行  
  8.         nbproc 1        #进程数量  
  9.  
  10. defaults            #默认配置  
  11.         mode tcp        #所处理的类别 http | tcp | health  
  12.         option redispatch   #serverId对应的服务器挂掉后,强制定向到其他健康的服务器  
  13.         retries 3       #三次连接失败则服务器不用  
  14.         timeout connect 5000    #连接超时  
  15.         timeout client 50000    #客户端超时  
  16.         timeout server 50000    #服务器超时  
  17.         timeout check 2000  #心跳检测超时  
  18.  
  19. listen proxy  
  20.         bind 192.168.5.111:3306     #监听地址  
  21.         mode tcp  
  22.         balance roundrobin      #定义负载方式,此处为轮询  
  23.  
  24.         log 127.0.0.1 local0 info   #定义日志类型  
  25.     #rise 3三次正确表示服务器可用,fall 3表示3次失败表示服务器不可用  
  26.         server db1 192.168.5.11:3306 check inter 1200 rise 2 fall 3 weight 1  
  27.         server db2 192.168.5.12:3306 check inter 1200 rise 2 fall 3 weight 1  
  28.  
  29. #服务器状态监控配置,可以通过定义的地址查看集群状态;  
  30. listen haproxy_stats  
  31.         log 127.0.0.1 local0 info  
  32.         mode http  
  33.         bind 192.168.5.111:8888  
  34.         option httplog  
  35.         stats uri /status  
  36.         stats realm Haproxy Manager  
  37.         stats auth admin:admin      #设置监控地址的帐号与密码 

#在keepalived 主配文件中添加刚才在其末端说明的外部定义脚本

#启动服务

/opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg

#说明事项,keepalived 的服务主备设备上都可以同时运行,实则只有获得VIP的服务器才有效;

#但是 haproxy 启动的时候需要监听 VIP 地址,所以第一次备用设备是手动起不了服务的;

#需要在 keepalived 的notify_master配置项中设定脚本,当此设备获得VIP地址后才启动 haproxy;

#有个问题在这里,我们只设定了当keepalived 停止服务时,才结束 haproxy ,没有设定移交VIP时是否结束;

#其实这也不用担心,因为主机上已经没有VIP地址了,即便是监听也无效果,并无干扰;

========================================================================

##开始测试

#检测监听

netstat -tunlp | grep ha

netstat -tunlp | grep 3306

# master 设备上才会有两个程序监听不同地址的 3306;

#暂未配置 mysql 互为主备就是为了方便这一阶段的排错,这样能更准确的测试;

mysql -udiaosi -p123456 -h 192.168.5.111 -e "select * from test.mywait;"

#返回值应该是在 server1 server2 之间徘徊;

sed -i 's/^mysql.*$/#&/' /etc/passwd #注释掉mysql的用户

service mysqld stop

#这个时候 mysql 服务已经启动不起了,mysql_chke.sh 脚本会把 keepalived 停止掉;

keepalived 停止前,又会把 haproxy 杀死;当备份的设备获得 vip 后,则会通过start_haproxy.sh 脚本将 haproxy 启动起来;

于是并不会因为服务器当机或mysql故障,影响我们客户端对 111 的查询操作,实验完成一半了;

#但是测试时,在VIP地址切换过程中,客户端会有那么2-3秒不能访问到数据库,这个暂时忽略不计;

sed 's/^#//' /etc/passwd #测试完后,记得恢复mysql用户哦;

#恢复mysql 后,启动主设备的 mysqld keepalived ,然后使用 ip a 查看VIP 地址是否有返回来;

#在其中一台设备上 killall haproxy ,之后查看集群状态;

http://192.168.5.111:8888/status

#查看后再将 haproxy 启动

#至此,已经完成 负载均衡 + 高可用 两部分,负载方式为轮询

========================================================================

##三个脚本,很简单,就不再介绍了哈;主要是做日志和结束服务;

  
  
  
  
  1. #!bin/bash  
  2. #start_haproxy.sh  
  3.  
  4. sleep 5  
  5. get=`ip addr  |grep 192.168.5.111 |wc -l`  
  6. echo $get >> /opt/log/start_haproxy.log  
  7.  
  8. if [ $get -eq 1 ]  
  9. then 
  10.         echo "`date +%c` success to get vip" >> /opt/log/start_haproxy.log  
  11.         /opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg  
  12. else 
  13.         echo "`date +%c` can not get vip" >> /opt/log/start_haproxy.log  
  14. fi 
  
  
  
  
  1. #!bin/bash  
  2. #stop_haproxy.sh  
  3.  
  4. pid=`pidof haproxy`  
  5. echo "`date +%c` stop haproxy" >> /opt/log/stop_haproxy.log  
  6. kill -9 $pid 
  
  
  
  
  1. #!bin/bash  
  2. #stop_keepalived.sh  
  3.  
  4. pid=`pidof keepalived`  
  5. if [ $pid == "" ]  
  6. then 
  7.         echo "`date +%c` no keepalived process id"  >> /opt/log/stop_keepalived.log  
  8. else 
  9.         echo "`date +%c` will stop keepalived "  >> /opt/log/stop_keepalived.log  
  10.         /etc/init.d/keepalived stop  
  11. fi 

=======================================================

[mysql Manager Slave]

#mysql 主备配置;两台设备上添加用户哦;

root#mysql

create database db1;

GRANT REPLICATION SLAVE ON *.* TO 'diaosi1'@'%' IDENTIFIED BY '123456';

#此处注意哦,Slave 权限必须的,我最初使用 all 权限,结果主备始终不同步,改成 Slave 就OK了;

flush privileges;

show grants for diaosi1@'%';

==================================================================

#server1 的 mysql 配置

server_id=1 #服务器标识,唯一

log_bin=mysqlbinlog #启用二进制日志

log_bin_index=mysqlbinlog-index #日志索引文件

log_slave_updates=1 #让从服务器把自身复制的事件和记录都写到自己的二进制日志里

relay_log=relay-log #中继日志位置;存放slave端获取到master端的二进制文件信息

replicate_do_db=db1 ##指定需要同步的数据库

#server2 的 mysql 配置

server_id=2

log_bin=mysqlbinlog

log_bin_index=mysqlbinlog-index

log_slave_updates=1

relay_log=relay-log

replicate_do_db=db1

#分别重启两服务

service mysqld restart

mysql> show master status; #查看mysql 的当前二进制日志文件

+--------------------+----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+--------------------+----------+--------------+------------------+

| mysqlbinlog.000001 | 98 | | |

+--------------------+----------+--------------+------------------+

1 row in set (0.28 sec)

#分别连接对方 mysql 日志,开始备份;记得替换 Master_Host 和日志名及MASTER_LOG_POS;

>CHANGE MASTER TO MASTER_HOST='192.168.5.12',master_port=3306,MASTER_USER='diaosi1',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysqlbinlog.000001',MASTER_LOG_POS=98;

>START SLAVE; #开始同步

mysql> SHOW SLAVE STATUS\G #查看mysql同步状态

*************************** 1. row ***************************

Slave_IO_State: Waiting for master to send event
                Master_Host: 192.168.5.11
                Master_User: mywait
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysqlbinlog.000001
        Read_Master_Log_Pos: 98
             Relay_Log_File: relay-log.000002
              Relay_Log_Pos: 237
      Relay_Master_Log_File: mysqlbinlog.000001
           Slave_IO_Running: Yes #表明获取对方日志文件的连接成功;
          Slave_SQL_Running: Yes #将获取到的日志转成sql语句回写本地数据库成功;
            Replicate_Do_DB: db1
        Replicate_Ignore_DB:
         Replicate_Do_Table:
     Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                 Last_Errno: 0
                 Last_Error:
               Skip_Counter: 0
        Exec_Master_Log_Pos: 98
            Relay_Log_Space: 237
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: 0
1 row in set (0.00 sec)

#主要就是看 Slave_IO_Running,Slave_SQL_Running

#这里错误的话,多数情况是 Slave_IO_Running 的问题,防火墙,用户权限,日志是否有启用等都需要判断;

=====================================================================

=====================================================================

#至此 mysql 双主互备搭建完成,我们的全部实验规划也全部完成;

#进入全面测试阶段;

#在 server1 的DB1里新建一张表,并赋值

>use db1;

>create table mywait(name char(9),phone char(14));

>insert into mywait(name,phone) values('wait',15888888888);

#新建一个具有 db1 权限的用户

grant all on db1.* to diaosi2@'%' identified by '123456';

>flush privileges;

#切换到 test 库,在mywait 表中插入一条数据;

use test;

insert into mywait(name,phone) values ('diaosi',15002839961);

#在 server2做验证;

>use db1;

>show tables;

>select * from mywait;

#此时数据与 server1 的会数据一致,表示mysql同步成功;

select user,host,password from mysql.user;

#在 server1 创建的用户也会被 server2 所同步;

#select * from test.mywait

#可以看到 server1上的 test 库并没有被同步;

#客户机上测试

mysql -udiaosi2 -p123456 -h 192.168.5.111 -e "select * from db1.mywait;"

#完毕;

=======================================================

#存在的问题;

在做mysql_chke 脚本时,本打算使用检查进程的形式判断服务是否启动;

`ps -C mysqld --no-header | wc -l`

当检查mysql 进程不存在的时候,先试着启动一次mysqld ,然后再检测,如果还是启动不了服务,再结束 keepalived ;

但是在使用 /etc/rc.d/init.d/mysqld start 启动后,出现一些问题;

比如mysql 配置文件错误或是注销用户等,mysql服务已然起不来了,虽然手动起不来服务;

但使用 ps -C mysqld 还是可以检查出一条mysqld 的进程来,这是什么情况没弄明白,希望能得到指点;

可优化项,haproxy 的功能很多,可以做成基于权重的分配方式,或是根据访问地址的,甚至可以使用 cookie 做判断;

大家都可以多测试一下;

有些地方是需要在两台服务器上同时配置的,大家看的时候多留意一下,测试过程中多看日志是最好的排错方式;

#ip a | ip addr | ip address 效果是一样的;

这篇博客是我第一次写,有些粗糙,可能有些地方注释得还有错误,欢迎留言;

这社区里还有很多比较好的类似文章,大家可以参考着学习,这样效率更好,谢谢;

原文链接:http://my.oschina.net/wait716/blog/170902



你可能感兴趣的:(mysql,负载均衡)