您的位置:首页 > 数据库 > SQL

MySQL多主多从架构实现及主从复制问题处理 推荐

2017-02-15 11:30 726 查看
一 测试架构设计和目标:




1)Master(192.168.31.230)为正常运行环境下的主库,为两个Slave(192.168.31.231和192.168.31.232)提供“主-从”复制功能;
2)Master_Backup(192.168.31.233)是Master的备份库,只要Master是正常的,它不对外提供服务。它与Master之间属于"主-主"复制关系,即自己既是主机,又是对方的从机;
3)同理,192.168.31.234和192.168.31.235为Slave_Backup,分别为192.168.31.231和 192.168.31.232的备份库,只要Slave是正常的,对应的备份机不对外提供服务;
4)Slave在此架构中的目的是为了实现读写分离,对应用程序来说,Master只负责写,两个Slave只负责读。Slave的数据来源于Master的复制操作;
5)如果Master由于某种原因(例如:宕机和断电等)导致不能正常运行,则此时需要让Master_Backup自动切换为新主机,而Slave和Slave_Backup也能自动切换数据源到Master_Backup;
6)同理,如果Slave由于某种原因(例如:宕机和断电等)导致不能正常运行,则此时需要让对应的Slave_Backup自动切换为新从机;
7)无论是Master还是切换后的Master_Backup,它们向客户端提供的连接地址应保持一致,如上图提供的VIP+Port,即192.168.31.201:3306,Slave和Slave_Backup也应如此,对外提供的连接地址始终是192.168.31.202:3306和192.168.31.203:3306。

二 实现部署测试

首先完成双主部署
1 在masterA上新建一个账户,用户masterB同步数据masterA操作> GRANT REPLICATION SLAVE ON *.* TO 'master'@'192.168.31..%' IDENTIFIED BY '123456'; > FLUSH PRIVILEGES;> FLUSH TABLES WITH READ LOCK; mysqldump -uroot -p123456 --databases test >/tmp/testA.sql scp /tmp/testA.sql 192.168.31.233:/tmp> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)
2 masterB:上同样的建立复制到账户,并导入数据mysql> GRANT REPLICATION SLAVE ON *.* TO 'master'@'192.168.31.%' IDENTIFIED BY '123456';mysql> FLUSH TABLES WITH READ LOCK;mysqldump -uroot -p123456 --databases test >/tmp/testB.sqlscp /tmp/testB.sql 192.168.31.230:/tmp/# 分别在master1 和 master2上分别导入对方的数据.但是存在一个问题: 因为存在主键冲突的情况,导出数据的时候,不要把主键给导出来了;如果是一方没有数据,那就直接导入数据就好了,不过也要跳过主键;
mysql -uroot -p123456 </tmp/testA.sql mysql -uroot -p123456 </tmp/testB.sql
3 修改master1和master2 的配置文件 ,只是server-id 不同
master1:的配置文件vim /etc/my.cnf[mysqld]datadir=/var/lib/mysql#datadir=/mysqldatasocket=/var/lib/mysql/mysql.sockuser=mysqlsymbolic-links=0

#### Master ####
server-id = 1log-bin = mysql-binlog-bin-index = mysql-bin.indexrelay-log = mysql-relayrelay-log-index = mysql-relay.indexexpire-logs-days = 10max-binlog-size = 100Mlog-slave-updates = 1binlog-do-db = testreplicate-do-db = testbinlog-ignore-db = mysqlreplicate-ignore-db = mysqlsync-binlog = 1auto-increment-increment = 2auto-increment-offset = 1

# master2:的配置文件
vim /etc/my.cnf [mysqld]datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.sockuser=mysqlsymbolic-links=0

### Master ####
[mysqld]datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.sockuser=mysqlsymbolic-links=0
server-id = 2log-bin = mysql-binlog-bin-index = mysql-bin.indexrelay-log = mysql-relayrelay-log-index = mysql-relay.indexexpire-logs-days = 10max-binlog-size = 100Mlog-slave-updatesskip-slave-startslave-skip-errors = all
binlog-do-db = testreplicate-do-db = testbinlog-ignore-db = mysqlreplicate-ignore-db = mysql
sync-binlog = 1auto-increment-increment = 2auto-increment-offset = 2
4 分别在master1和master2上获取File和Position位置master1:>flush tables with read lock;>show matser status;+------------------+----------+--------------+------------------+| File | Position | Binlog_Do_DB |Binlog_Ignore_DB +------------------+----------+--------------+------------------+| mysql-bin.000002| 106 | test | mysql +------------------+----------+--------------+------------------+>unlock tables;master2:>flush tables with read lock;>show matser status;+------------------+----------+--------------+------------------+| File | Position | Binlog_Do_DB |Binlog_Ignore_DB +------------------+----------+--------------+------------------+| mysql-bin.000003| 106 | test | mysql+------------------+----------+--------------+------------------+>unlock tables;
5 配置主从,分别在master1和 master2上配置对方的从master1上:> CHANGE MASTER TO -> MASTER_HOST='192.168.31.233', -> MASTER_USER='master', -> MASTER_PASSWORD='123456', -> MASTER_PORT=3306, -> MASTER_LOG_FILE='mysql-bin.000003', -> MASTER_LOG_POS=106, -> MASTER_CONNECT_RETRY=10;Query OK, 0 rows affected (0.02 sec)
mysql> START SLAVE;Query OK, 0 rows affected (0.00 sec)master2上:> CHANGE MASTER TO -> MASTER_HOST='192.168.31230', -> MASTER_USER='master', -> MASTER_PASSWORD='123456', -> MASTER_PORT=3306, -> MASTER_LOG_FILE='mysql-bin.000002', -> MASTER_LOG_POS=106, -> MASTER_CONNECT_RETRY=10;Query OK, 0 rows affected (0.02 sec)
mysql> START SLAVE;Query OK, 0 rows affected (0.00 sec)用>show processlist查看进程状态 接着为双主机器各部署两个从机并测试是否主从正常(主从部署略,其步骤与双主大致相同,注意修改部分参数即可,这里不在详细写出可参考http://superleedo.blog.51cto.com/12164670/1897681
6 测试结果1)当Master和Master_Backup都正常运行时,在任意一端更新数据后都会同步到两个Slave上
2)当Master处于正常时,无论Master_Backup是否正常,在此端更新数据后都会同步到两个Slave上
3)当Master处于不可运行时,Master_Backup通过Monitor(Keepalived)成为接管者,在Master_Backup更新数据后不会同步到所有Slave上,即使后来在Slave上将MASTER_HOST指定为Keepalived提供的VIP(192.168.31.201)也无用。
究其原因,Master_Server_Id指向的是已经处于不可运行的Master,而预期结果是希望它能自动的更新定位到Master_Backup(233)上达到自动切换目的,然而测试结果并能不满足快速响应容灾切换的目的。

三 修改架构及部署
选择mysql-mmm结合半同步机制来实现容灾自动切换




1 在master(230和233)上安装semisync master并设置
mysql代码:

>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
>SET GLOBAL rpl_semi_sync_master_enabled = 1;
>SET GLOBAL rpl_semi_sync_slave_enabled = 1;
vim /ect/my.cnf后加入如下配置:

rpl_semi_sync_master_enabled = 1
rpl_semi_sync_slave_enabled = 1

2 在slave(231、232、234和235)上安装slave插件并设置

mysql代码:
>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
>SET GLOBAL rpl_semi_sync_slave_enabled = 1;
vim /ect/my.cnf后加入如下配置:
rpl_semi_sync_slave_enabled = 1

3 所有mysql实例停止slave并开启slave,使半同步机制生效

mysql代码 :
>stop slave;
>start slave;

4 查看semisync状态
mysql代码:
>show status like '%emi%';
重点关注:
1)Rpl_semi_sync_master_clients:与当前master建立半同步连接的客户端数
2)Rpl_semi_sync_master_status:作为半同步master端的就绪状态(ON:就绪,OFF:未就绪)
3)Rpl_semi_sync_slave_status:作为半同步slave端的就绪状态(ON:就绪,OFF:未就绪)

5 安装mysql-mmm
5.1新增一台专门用于监控mysql的服务器(mysql_monitor),IP为192.168.31.250
5.2在mysql_monitor、master、master_backup、slave和slave_backup上安装epel网络源
yum install http://mirrors.hustunique.com/epel//6/x86_64/epel-release-6-8.noarch.rpm 5.3在mysql_monitor上安装mysql-mmm-monitor
yum -y install mysql-mmm-monitor

5.4 编辑mysql_monitor上的配置文件mmm_mon.conf

vi /etc/mysql-mmm/mmm_mon.conf
include mmm_common.conf

<monitor>
# 本机IP
ip 192.168.31.250
port 9988
pid_path /var/run/mysql-mmm/mmm_mond.pid
bin_path /usr/libexec/mysql-mmm
status_path /var/lib/mysql-mmm/mmm_mond.status
ping_ips 192.168.31.230, 192.168.31.231, 192.168.31.232, 192.168.31.233, 192.168.31.234, 192.168.31.235 # 所有MySQL服务器的IP
auto_set_online 0
</monitor>
<host default>
# GRANT REPLICATION CLIENT ON语句创建的账号和密码
monitor_user mmm_monitor
monitor_password monitor
</host>
<check mysql>

check_period 5 # 每5秒检查一次
trap_period 10
timeout 2 # 检查超时秒数
restart_after 10000
max_backlog 60
</check>
<code># 设置为1,开启调试模式,打印日志到前台,ctrl+c将结束进程,对于调试有帮助</code>
debug 0

6 在master、master_backup、slave和slave_backup上安装和配置

1)安装mysql-mmm-agent
yum -y install mysql-mmm-agent

2)授权monitor访问
mysql代码 :
>GRANT REPLICATION CLIENT ON *.* TO 'mmm_monitor'@'192.168.31.%' IDENTIFIED BY 'monitor';
>GRANT SUPER,REPLICATION CLIENT, PROCESS ON *.* TO 'mmm_agent'@'192.168.31.%' IDENTIFIED BY'agent';

3)编辑mmm_agent.conf配置文件
vim /etc/mysql-mmm/mmm_agent.conf
include mmm_common.conf # 包含公用配置文件

<span style="color: #000000;">mmm_common.conf中定义的某个host名称</span></span></code> # 对应<code><span style="color: #008000;">
this db1 # 设置成1时,将打印日志到前台,按ctrl+c将结束进程
debug 0
max_kill_retries 1

4)编辑mmm_common.conf配置文件
vim /etc/mysql-mmm/mmm_common.conf
active_master_role writer

<host default>
# 对应当前主机的网络接口名
cluster_interface eth2
pid_path /var/run/mysql-mmm/mmm_agentd.pid
bin_path /usr/libexec/mysql-mmm/
mysql_port 3306
agent_port 9989
# 对应GRANT REPLICATION SLAVE ON语句创建的账号和密码
replication_user slave
replication_password slave123
# GRANT SUPER,REPLICATION CLIENT, PROCESS ON语句创建的账号和密码
agent_user mmm_agent
agent_password agent
</host>
# master的配置

# 其中host后面的值定义的是某台数据库服务的别名,一般就用服务器的主机名即可
<host db1>
ip 192.168.31.230
mode master
# db1的master对等点
peer db2
</host>
# master_backup的配置
<host db2>
ip 192.168.31.233
mode master
# db2的master对等点
peer db1
</host>
# slave的配置

<host db3>
ip 192.168.31.231
mode slave
</host>
# slave的配置

<host db4>
ip 192.168.31.232
mode slave
</host>
# slave_backup的配置

<host db5>
ip 192.168.31.234
mode slave
</host>
# slave_backup的配置

<host db6>
ip 192.168.31.235
mode slave
</host>
# 定义writer角色,即架构中的master和master_backup
# ips为writer对外提供的vip
<role writer>
hosts db1, db2
ips 192.168.31.201
mode exclusive
</role>
# 定义reader角色,即架构中的两个slave和两个slave_backup
# ips为reader对外提供的vip
<role reader>
hosts db3, db4, db5, db6
ips 192.168.31.202, 192.168.31.203
mode balanced
</role>
注意,也需要将此配置文件复制到mysql_monitor的同名目录下

5) 在master、master_backup、slave和slave_backup上启动mmm agent服务,并设置为开机服务
/etc/init.d/mysql-mmm-agent start
vim /etc/rc.d/rc.local后,将上述命令行添加到mysql启动命令的下面

7 在上mysql_monitor开启mmm monitor监控,并设置为开机服务
/etc/init.d/mysql-mmm-monitor start

vi /etc/rc.d/rc.local后,将上述命令行添加

8 然后重启所有服务器系统后测试
1)在mysql_monitor上执行如下命令,查看各监控机的运行状态
执行mmm_control show 查看

2)测试结果
1)当Master和Master_Backup都正常运行时,在任意一端更新数据后都会同步到两个Slave上
2)当Master处于正常时,无论Master_Backup是否正常,在此端更新数据后都会同步到两个Slave上
3)当Master处于不可运行时,Master_Backup通过Monitor(Keepalived)成为接管者,在Master_Backup更新数据后会同步到所有Slave上,符合预期

四 问题处理总结

1 架构图中看出,Mmm_Mnitor存在单点问题,当Mmm_Mnitor处于不可运行时,整个主从结构将不能正常运行。可以部署多个监控,结合Keepalived来扩展。
2 读写分离会带来数据延迟达到的问题。假设有一个业务,当数据插入到数据库后要立即又从数据库中将此数据查询出来,因此当数据插入到Master库后,由于网络的延迟,Slave库中不会立即得到这条最新的数据,此时应用程序查询Slave库将得不到预期结果。
解决问题:将此类业务控制在一个数据库事务中进行,读写都在master中进行。因此,在mmm_common.conf配置文件中,还需要将db1和db2同时配置在reader组:
<role writer>

hosts db1, db4
ips 192.168.31.201
mode exclusive
</role>
<role reader>
hosts db1, db4, db2, db3, db5, db6
ips 192.168.31.202, 192.168.31.203
mode balanced
</role>
3 主从复制差距的问题。有时候因为主服务器的更新过于频繁,造成了从服务器更新速度较慢,当然问题是多种多样,有可能是网络搭建的结构不好或者硬件的性能较差,从而使得主从服务器之间的差距越来越大,最终对某些应用产生了影响。
解决问题:定期进行主从服务器的数据同步,具体步骤如下在主服务器上
mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.03 sec)
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000004
Position: 102
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)
记录出日志的名字和偏移量,这些是从服务器复制的目的目标;在从服务器上,使用MASTER_POS_WAIT()函数得到复制坐标值

mysql> select master_pos_wait('mysql-bin.000004','102');
+-------------------------------------------+
| master_pos_wait('mysql-bin.000004','102') |
+-------------------------------------------+
| 0 |
+-------------------------------------------+
1 row in set (0.00 sec)
这个select 语句会阻塞直到从服务器达到指定日志文件和偏移量后,返回0,如果是-1,则表示超时退出,查询是0时,表示从服务器与主服务器已经同步
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL 架构 多主多从