MySQL双主复制,即互为Master-Slave(只有一个Master提供写操作),可以实现数据库服务器的热备,但是一个Master宕机后不能实现动态切换。而Keepalived通过虚拟IP,实现了双主对外的统一接口以及自动检查、失败切换机制。联合使用,可以实现MySQL数据库的高可用方案。

实验环境:
OS:centos 6.x x86_64系统
MySQL版本: :mysql 5.6.22   64 位
A: master :192.168.79.3 3306
B: slave :192.168.79.4 3306

操作系统时间一致更改:
# date -s "20150319 15:51:42"
# hwclock --systohc

 

AB数据库安装及主从配置

新建mysql用户,用户组,创建 datadir 
# groupadd mysql 
# useradd mysql -g mysql -s /sbin/nologin -d /opt/mysql 

解压mysql二进制安装包,对解压后的mysql目录加一个符号连接
# cd /opt/mysql
# tar -xvzf mysql-5.6.22-linux-glibc2.5-x86_64.tar.gz
# cd /usr/local/
# ln -s /opt/mysql/mysql-5.6.22-linux-glibc2.5-x86_64 mysql
# ls
bin etc games include lib lib64 libexec mysql sbin share src

 

创建mysql的安装目录并修改权限
# mkdir -p /data/mysql/mysql_3306/{data,logs,tmp}
chown -R mysql:mysql /data/mysql/
chown -R mysql:mysql /usr/local/mysql/

 

加环境变量,解决找不到mysql命令的问题
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> /etc/profile
source /etc/profile

创建修改mysql配置文件
修改my.cnf 

server_id
log_slave_updates
gtid-mode= off
binlog-ignore-db=mysql
replicate-ignore-db=mysql
auto_increment_offset= 1;
auto_increment_increment= 2;
ps:主从库的server_id不要一样。 如果从库是整个拷贝的uuid也不要一样,data下的auto.cnf.  从库:auto_increment_offset= 2;auto_increment_increment= 2;

初始化系统数据文件 ,在basedir下初始化
# ./scripts/mysql_install_db --user=mysql --defaults-file=/etc/my.cnf --datadir=/data/mysql/mysql_3306/data

安装mysql后的善后工作
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
/etc/init.d/mysql start

delete from mysql.user where user!='root' or host!='localhost';
truncate mysql.db;
drop database test;
grant all privileges on *.* to 'liyt'@'%' identified by 'liyt';
grant replication slave, replication client on *.* to 'repl'@'%' identified by 'replslave';
flush privileges;

reset master;

 

启动 slave mysql服务
A:
>show master status;
+-----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| mybinlog.000001 | 120 | | | |
+-----------------+----------+--------------+------------------+-------------------+
B:
change master to master_host='192.168.79.3', master_port=3306 ,master_user='repl', master_password='replslave', master_log_file='mybinlog.000001', master_log_pos=120;

 

B:
>show master status;
+-----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| mybinlog.000001 | 120 | | | |
+-----------------+----------+--------------+------------------+-------------------+
A:
change master to master_host='192.168.79.4', master_port=3306 ,master_user='repl', master_password='replslave', master_log_file='mybinlog.000001', master_log_pos=120;

 

测试双主同步:创建新的数据库和表看是否能同步

 

keepalived安装及配置
GRANT REPLICATION CLIENT ON *.* TO 'monitor'@'%' IDENTIFIED BY 'monitor';

#yum install keepalived

#yum install MySQL-python

配置A:
[root@taotao ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
router_id MYSQL_3
}
vrrp_script chk_mysql {
script "/etc/keepalived/checkMySQL.py -h 192.168.79.3 -P 3306"
interval 60 
}
vrrp_instance VI_MYSQL1 {
state BACKUP
nopreempt
interface eth0
virtual_router_id 82
priority 100
advert_int 5
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_mysql
}
virtual_ipaddress {
192.168.79.66
}
}
这里state不配置MASTER,是期望在MASTER宕机后再恢复时,不主动将MASTER状态抢过来,避免MySQL服务的波动。
由于不存在使用lvs进行负载均衡,不需要配置虚拟服务器virtual server,下同。


配置B:
[root@taotao ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
router_id MYSQL_4
}
vrrp_script chk_mysql {
script "/etc/keepalived/checkMySQL.py -h 192.168.79.4 -P 3306"
interval 60 
}
vrrp_instance VI_MYSQL1 {
state BACKUP
nopreempt
interface eth0
virtual_router_id 82
priority 90
advert_int 5
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_mysql
}
virtual_ipaddress {
192.168.79.66
}
}

checkMySQL.pyAB完全一样代码如下:

# cat /etc/keepalived/checkMySQL.py 
#!/usr/bin/python
#coding: utf-8
#

import sys
import os
import getopt
import MySQLdb
import logging



dbhost='localhost'
dbport=3306
dbuser='monitor'
dbpassword='monitor'


def checkMySQL():
        global dbhost
        global dbport
        global dbuser
        global dbpassword

        shortargs='h:P:'
        opts, args=getopt.getopt(sys.argv[1:],shortargs)
        for opt, value in opts:
                if opt=='-h':
                        dbhost=value
                elif opt=='-P':
                        dbport=value
        #print "host : %s, port: %d, user: %s, password: %s" % (dbhost, int(dbport), dbuser, dbpassword)
        db = instanceMySQL(dbhost, dbport, dbuser, dbpassword)
        st = db.ishaveMySQL()
        #if ( db.connect() != 0 ):
        #       return 1
        #db.disconnect()
        return st

class instanceMySQL:
        conn = None
        def __init__(self, host=None,port=None, user=None, passwd=None):
                self.dbhost= host
                self.dbport = int(port)
                self.dbuser = user
                self.dbpassword = passwd

        def ishaveMySQL(self):
                cmd="ps -ef | egrep -i \"mysqld\" | grep %s | egrep -iv \"mysqld_safe\" | grep -v grep | wc -l" % self.dbport
                mysqldNum = os.popen(cmd).read()
                cmd ="netstat -tunlp | grep \":%s\" | wc -l" % self.dbport
                mysqlPortNum= os.popen(cmd).read()
                #print mysqldNum, mysqlPortNum
                if ( int(mysqldNum) <= 0):
                        print "error"
                        return 1
                if ( int(mysqldNum) > 0 and  mysqlPortNum <= 0):
                        return 1
                return 0

        def connect(self):
        #       print "in db conn"
#               print "host : %s, port: %d, user: %s, password: %s" % (self.dbhost, self.dbport, self.dbuser, self.dbpassword)
                try:
                        self.conn=MySQLdb.connect(host="%s"%self.dbhost, port=self.dbport,user="%s"%dbuser, passwd="%s"%self.dbpassword)
                except Exception, e:
#                       print " Error"
                        print e
                        return 1
                return 0
        def disconnect(self):
                if (self.conn):
                        self.conn.close()
                        self.conn = None


if __name__== "__main__":
        st=checkMySQL()
        sys.exit(st)
View Code

相关文章: