http://blog.csdn.net/socho/article/details/51804720

解决Master单点问题,两台mysql互为主备,双向replication。当一master挂了,则将slave切换为master,继续工作。好,给定两台机器
主机A:192.168.1.201 
主机B:192.168.1.202

一、互为主从

1.配置

主机A上,vim /etc/my.cnf,添加:

  1. [mysqld]
  2. log-bin=mysql-bin
  3. server-id=1 #服务id要和B不同
  4. binlog_do_db=db1
  5. master-host = 192.168.1.202 #目标机器是B的地址
  6. master-user = user1
  7. master-password = pass1
  8. master-port = 3306
  9. master-connect-retry = 5

主机B上,vim /etc/my.cnf,添加:

  1. [mysqld]
  2. log-bin=mysql-bin
  3. server-id=2 #服务id要和A不同
  4. binlog_do_db=db1
  5. master-host = 192.168.1.201 #目标机器是A的地址
  6. master-user = user1
  7. master-password = pass1
  8. master-port = 3306
  9. master-connect-retry = 5

在A上开启binlog,创建复制帐号

每个slave使用标准的MySQL用户名和密码连接master。进行复制操作的用户会授予REPLICATION SLAVE权限。用户名的密码都会存储在文本文件master.info中。假如,你想创建user1用户,如下:

  1. GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO user1@'%' IDENTIFIED BY 'pass1';

在B上开启binlog,创建复制帐号

  1. GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO user1@'%' IDENTIFIED BY 'pass1';

为了方便,我们将用户名和密码两台机器都设成一致的。

在A上 
我们先在A上创建数据库db1,里面的表内容随便写点啥就行了:

  1. CREATE DATABASE db1;
  2. USE db1;
  3. CREATE TABLE `tb_2` (
  4. `id` int(11) NOT NULL AUTO_INCREMENT,
  5. `name` varchar(64) DEFAULT NULL,
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  8. INSERT INTO `tb_2` VALUES ('1', 'Michael');

查看下信息

  1. mysql> show variables like 'ser%';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | server_id | 1 |
  6. +---------------+-------+
  7. mysql> show master status;
  8. +------------------+----------+--------------+------------------+
  9. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  10. +------------------+----------+--------------+------------------+
  11. | mysql-bin.000001 | 447 | db1 | |
  12. +------------------+----------+--------------+------------------+

可以看到A要同步的是db1数据库,当前bin-log编号是000001,位置是447。 
查看A的数据

  1. mysql> select * from tb_2;
  2. +----+---------+
  3. | id | name |
  4. +----+---------+
  5. | 1 | Michael |
  6. +----+---------+

A有一条数据。 
在B上

  1. mysql> show variables like 'ser%';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | server_id | 2 |
  6. +---------------+-------+
  7. mysql> show master status;
  8. +------------------+----------+--------------+------------------+
  9. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  10. +------------------+----------+--------------+------------------+
  11. | mysql-bin.000001 | 106 | db1 | |
  12. +------------------+----------+--------------+------------------+

查看B的数据

  1. mysql> select * from tb_2;
  2. Empty set (0.00 sec)

B还没有数据,目前未同步。位置是000001:106,一会从A上同步过来。

2.开始同步

配置中已有replication的配置了,只要两个机器重启就行了,自动相互复制。 
在A上

  1. service mysqld restart
  • 1

在B上

  1. service mysqld restart

再在A上执行

  1. mysql> show slave status\G
  2. *************************** 1. row ***************************
  3. Slave_IO_State: Waiting for master to send event
  4. Master_Host: 192.168.1.202
  5. Master_User: user1
  6. Master_Port: 3306
  7. Connect_Retry: 5
  8. Master_Log_File: mysql-bin.000008
  9. Read_Master_Log_Pos: 106
  10. Relay_Log_File: mysqld-relay-bin.000001
  11. Relay_Log_Pos: 251
  12. Relay_Master_Log_File: mysql-bin.000008
  13. Slave_IO_Running: Yes
  14. Slave_SQL_Running: Yes
  15. Replicate_Do_DB:
  16. Replicate_Ignore_DB:
  17. Replicate_Do_Table:
  18. Replicate_Ignore_Table:
  19. Replicate_Wild_Do_Table:
  20. Replicate_Wild_Ignore_Table:
  21. Last_Errno: 0
  22. Last_Error:
  23. Skip_Counter: 0
  24. Exec_Master_Log_Pos: 106
  25. Relay_Log_Space: 552
  26. Until_Condition: None
  27. Until_Log_File:
  28. Until_Log_Pos: 0
  29. Master_SSL_Allowed: No
  30. Master_SSL_CA_File:
  31. Master_SSL_CA_Path:
  32. Master_SSL_Cert:
  33. Master_SSL_Cipher:
  34. Master_SSL_Key:
  35. Seconds_Behind_Master: 0
  36. Master_SSL_Verify_Server_Cert: No
  37. Last_IO_Errno: 0
  38. Last_IO_Error:
  39. Last_SQL_Errno: 0
  40. Last_SQL_Error:

A中的Slave_IO_Running 和 Slave_SQL_Running两个值都是YES,说明配置成功了。 
B的配置就不贴了,也是配置成功的。 
如果同步不成功: 
用命令行的方式手动复制,比如在B上输入命令

  1. change master to
  2. master_host='192.168.1.201',
  3. master_port=3306,
  4. master_user='user1',
  5. master_password='pass1';

然后使用start slave;开启从A向B的复制。 
还有指定从某个地址开始复制的话,加两个参数

  1. master_log_file='mysql-bin.000001',
  2. master_log_pos=106;

反过来,要从B同步到A,就要在A上执行

  1. change master to
  2. master_host='192.168.1.202',
  3. master_port=3306,
  4. master_user='user1',
  5. master_password='pass1';

同步好了之后,查看B的数据

  1. mysql> select * from tb_2;
  2. +----+---------+
  3. | id | name |
  4. +----+---------+
  5. | 1 | Michael |
  6. +----+---------+

好的,现在A和B数据一致了。

再看看A和B的状态 
A机器

  1. mysql> show master status;
  2. +------------------+----------+--------------+------------------+
  3. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  4. +------------------+----------+--------------+------------------+
  5. | mysql-bin.000001 | 447 | db1 | |
  6. +------------------+----------+--------------+------------------+

B机器

  1. mysql> show master status;
  2. +------------------+----------+--------------+------------------+
  3. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  4. +------------------+----------+--------------+------------------+
  5. | mysql-bin.000001 | 106 | db1 | |
  6. +------------------+----------+--------------+------------------+

B的bin-log位置没有变,还是000001:106,但是数据确实已经到了。

3.在A和B上操作

1.先把A当作Master,在A上操作数据 
从A上删除数据

  1. mysql> delete from tb_2 where name='Michael';
  2. Query OK, 1 row affected (0.00 sec)

此时A的bin-log位置是000001:546,而到B查看数据

  1. mysql> select * from tb_2;
  2. Empty set (0.00 sec)

确实已经同步删除了,不过B的bin-log位置依然是000001:106 
2.再把B当作Master,在B上操作数据

  1. INSERT INTO `tb_2`(name) VALUES ('Michael');
  2. Query OK, 1 row affected (0.00 sec)

成功后,到A上去查

  1. mysql> select * from tb_2;
  2. +----+---------+
  3. | id | name |
  4. +----+---------+
  5. | 2 | Michael |
  6. +----+---------+

A也同步到了数据,至此说明A和B互为主从,在一个上面修改数据,就会同步到另外一个机器上是可行的。 
查看下两机器状态 
这次A的bin-log地址没有变化,还是000001:546,而变的是B,成了000001:239了,说明从机只有变成主机数据被修改的时候,才会改变自己的bin-log地址,同步是不会改变bin-log地址的。 
接下来配置keepalived。

二、KeepAlived

上一步确保了互为主从设置成功后,接下来安装 
yum install keepalived 
看下版本 
[root@localhost ~]# keepalived -v 
Keepalived v1.2.13 (03/19,2015)

1.配置

然后在A服务器编辑KeepAlived的配置文件 
vim /etc/keepalived/keepalived.conf

  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id HA_MySQL #标识,双主相同
  4. }
  5. vrrp_instance VI_1 {
  6. state BACKUP #注意,主从两端都配置成了backup,因为使用了nopreempt,即非抢占模式
  7. interface eth0
  8. virtual_router_id 51 #分组,主备相同
  9. priority 100 #优先级,这个高一点则先把它作为master
  10. advert_int 1
  11. nopreempt #不主动抢占资源,设置非抢占模式
  12. authentication {
  13. auth_type PASS
  14. auth_pass 1111
  15. }
  16. virtual_ipaddress {
  17. 192.168.1.199
  18. }
  19. }
  20. virtual_server 192.168.1.199 3306 {
  21. delay_loop 2
  22. lb_algo wrr #带有权重的轮询
  23. lb_kind DR
  24. persistence_timeout 60 #同一IP的连接60秒内被分配到同一台真实服务器
  25. protocol TCP
  26. real_server 192.168.1.201 3306 {
  27. weight 3 #权重为3
  28. notify_down /data/keepalived_shutdown.sh #当mysq服down时,执行此脚本,杀死keepalived实现切换, 自杀脚本.
  29. TCP_CHECK {
  30. connect_timeout 10
  31. nb_get_retry 3
  32. delay_before_retry 3
  33. connect_port 3306
  34. }
  35. }
  36. }

然后编辑B的配置文件 
vim /etc/keepalived/keepalived.conf

  1. ! Configuration File for keepalived
  2. global_defs {
  3. router_id HA_MySQL
  4. }
  5. vrrp_instance VI_1 {
  6. state BACKUP
  7. interface eth0
  8. virtual_router_id 51
  9. priority 90 #优先级,这个低一点
  10. advert_int 1
  11. nopreempt
  12. authentication {
  13. auth_type PASS
  14. auth_pass 1111
  15. }
  16. virtual_ipaddress { #虚拟IP (VIP)
  17. 192.168.1.199
  18. }
  19. }
  20. virtual_server 192.168.1.199 3306 {
  21. delay_loop 2 #每2秒检查一次real_server存活
  22. lb_algo wrr
  23. lb_kind DR
  24. persistence_timeout 60
  25. protocol TCP
  26. real_server 192.168.1.202 3306 {
  27. weight 3
  28. notify_down /data/keepalived_shutdown.sh
  29. TCP_CHECK {
  30. connect_timeout 10 #连接超时时间
  31. nb_get_retry 3 #重连次数
  32. delay_before_retry 3 #重连间隔时间
  33. connect_port 3306 #健康检查端口,配置自己mysql服务端口
  34. }
  35. }
  36. }

有一点要注意的是,主从两端的state,都配置成了backup,因为使用了nopreempt,即非抢占模式。 
举个例子,当主端先启动mysql实例和keepalived后,如果此时从端也启动了mysql实例和keepalived,那么vip不会跳到从端上去,即使它的优先级为100,要大于主端的90 
而如果不设置nopreempt,那么这个时候,又分2种情况: 
1.state相同,即都是master或都是backup 
优先级高的,会占有vip,和角色无关 
2.state不同,即master->backup或backup->master 
优先级高的,会占有vip,和角色无关 
前提不同,结果都是一样的,即优先级是主导,谁的优先级高,vip就漂到谁那里

可以看到A和B配置的共同点,就是virtual_ipaddress都是,这样当我们使用mysql的时候,就连接到这个虚拟ip上,由它进行转发到实体机。priority值高的先被访问,作为Master。这样实体机mysql的down机重启和转换主从角色则由keepalived来完成,对应用层透明,让应用无法感知。两台机器要通局域网,虚拟IP会被设置在他们共有的局域网内,不通的话两台机器各设置各的虚拟IP。

杀死keepalived的脚本 
vim /data/keepalived_shutdown.sh

  1. #!/bin/bash
  2. #kill掉keepalived进程,以防止脑裂问题。
  3. pkill keepalive

2测试

先给个图说下目前的状况,应用程序连接VIP,VIP连接到A机器,从A向B执行Replication同步。 
 
1.连接虚拟ip 
先查看下虚拟ip有没有,在设置的priority值高,也就是主机的那台机器上,这里是A机器,调用如下命令

  1. [root@localhost data]# ip addr
  2. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
  3. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  4. inet 127.0.0.1/8 scope host lo
  5. inet6 ::1/128 scope host
  6. valid_lft forever preferred_lft forever
  7. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
  8. link/ether 08:00:27:eb:92:52 brd ff:ff:ff:ff:ff:ff
  9. inet 192.168.1.201/24 brd 192.168.1.255 scope global eth0
  10. inet 192.168.1.199/32 scope global eth0
  11. inet6 fe80::a00:27ff:feeb:9252/64 scope link
  12. valid_lft forever preferred_lft forever

可以看到已经有虚拟ip了,被绑定到了eth0上了。同时在B上面执行,则发现没有虚拟ip,说明现在A机器被选择了承担虚拟ip。接下来ping下它 
[root@localhost data]# ping 192.168.1.199 
PING 192.168.1.199 (192.168.1.199) 56(84) bytes of data. 
64 bytes from 192.168.1.199: icmp_seq=1 ttl=64 time=0.104 ms 
可以ping通哦,可以连接了!

用客户端连接共同的入口,虚拟ip 
myslq -uroot -h192.168.1.119 -p 
OK,连接上了,查下当前后端接入的是哪个实体机

  1. mysql> show variables like 'server_id';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | server_id | 1 |
  6. +---------------+-------+

server_id=1是A机器。此时两台机器上的数据都是

  1. mysql> select * from tb_2;
  2. +----+---------+
  3. | id | name |
  4. +----+---------+
  5. | 2 | Michael |
  6. +----+---------+

2.修改数据 
好,我们修改下数据看看

  1. update tb_2 set name='andy' where name='Michael';
  2. Query OK, 1 row affected (0.00 sec)
  3. Rows matched: 1 Changed: 1 Warnings:

然后查看

  1. mysql> select * from tb_2;
  2. +----+------+
  3. | id | name |
  4. +----+------+
  5. | 2 | andy |
  6. +----+------

单独开个客户端去查看A和B的机器,得到同样的效果,数据得到了同步

  1. mysql> select * from tb_2;
  2. +----+------+
  3. | id | name |
  4. +----+------+
  5. | 2 | andy |
  6. +----+------+

3.制造down机 
把mysql进程直接杀掉,类似于机器down的情况。 
ps -ef|grep mysql 
分析结果,得到两个mysql的进程id,都给它杀掉 
kill -9 7282 
kill -9 7408 
或者直接执行killall mysqld

然后再次查看server_id,短暂的失去连接,即使毫秒就恢复了

  1. mysql> show variables like 'server_id';
  2. No connection. Trying to reconnect...
  3. Connection id: 751
  4. Current database: *** NONE ***
  5. +---------------+-------+
  6. | Variable_name | Value |
  7. +---------------+-------+
  8. | server_id | 2 |

看样子是虚拟ip迁移了,在B上ip addr下

  1. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
  2. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  3. inet 127.0.0.1/8 scope host lo
  4. inet6 ::1/128 scope host
  5. valid_lft forever preferred_lft forever
  6. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
  7. link/ether dc:85:de:9f:f3:27 brd ff:ff:ff:ff:ff:ff
  8. inet 192.168.1.202/24 brd 192.168.1.255 scope global wlan0
  9. inet 192.168.1.199/32 scope global wlan0
  10. inet6 fe80::de85:deff:fe9f:f327/64 scope link
  11. valid_lft forever preferred_lft forever

server_id=2,并且B机器加载上了虚拟ip,同时我们在A机器上使用ip addr看到虚拟ip已经不存在了,A机器的keepalived进程也死了。充分证明了现在虚拟ip迁移到了B机器上。当然要让A机器复活,自己另外写脚本重启吧。现在的情况变成了应用程序连接VIP,VIP连接到B机器,从B向A执行Replication同步。 
 
3.复活机器 
重启A机器上的mysql和keepalived 
service mysqld start 
service keepalived start 
再次查看server_id,发现还是2,说明虚拟ip没有迁移回到A机器,这样就避免了脑裂问题

  1. mysql> show variables like 'server_id';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | server_id | 2 |
  6. +---------------+-------+
 

KeepAlived+MySQL互为主从的更多相关文章

  1. Keepalived与MySQL互为主从自动切换配置

    为解决Mysql数据库单点问题,实现两台MySQL数据库互为主备,双向replication.当一Master出现问题,则将Slave切换为Master继续工作. 环境说明 系统版本:CentOS L ...

  2. mysql互为主从实战设置详解及自动化备份(Centos7.2)

    mysql互为主从实战设置详解(Centos7.2) 第一步:mysql配置  my.cnf配置 服务器1 (10.89.10.90) [mysqld]  server-id=1  log-bin=/ ...

  3. mysql互为主从

    摘自:http://flash520.blog.163.com/blog/static/3441447520101029114016823/ A B 为两台MySQL服务器,均开启二进制日志,数据库版 ...

  4. Docker配置mysql互为主从

    配置准备 两台机器 两台机器:A(193.168.10.101)  B(193.168.10.102) 做好ssh免密登录 mysql大版本需要一致,小版本可忽略 并且两台机器已经安装好了docker ...

  5. MySql互为主从配置文件及配置方法

    # Example MySQL config file for medium systems. # # This is for a system with little memory (32M - 6 ...

  6. mysql互为主从(双主)配置

    环境: ubuntu18.04.2 mysql5.7.21 #创建mysql属组 groupadd mysql useradd -g mysql mysql #查看属组 tail /etc/passw ...

  7. 利用Keepalived+mysql构建高可用MySQL双主自动切转

    转载:http://www.it300.com/index.php/article-15266.html 关于MySQL-HA,目前有多种解决方案,比如heartbeat.drbd.mmm.共享存储, ...

  8. MySQL 高可用性—keepalived+mysql双主(有详细步骤和全部配置项解释)

    博主QQ:819594300 博客地址:http://zpf666.blog.51cto.com/ 有什么疑问的朋友可以联系博主,博主会帮你们解答,谢谢支持! 前言:生产环境中一台mysql主机存在单 ...

  9. MySQL高可用之——keepalived+互为主从

    目标:配置一个keepalived双机热备架构,并配置主从复制 规划: master1     zlm177     192.168.17.177 master2     zlm188     192 ...

随机推荐

  1. 'mysql' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    1.C:\Users\Aiyufei>mysql -h 127.0.0.1 -u root'mysql' 不是内部或外部命令,也不是可运行的程序或批处理文件.解决方法: 配置环境变量即可,我的问 ...

  2. [转] mongoose 之Shema

    总 之见到我写点啥简直是奇迹,由于现在喜欢上玩转node.js +mongoose,个人爱好,靠近前端的又是英文文档,苦逼得很,悟出来一个写一个吧.之前喜欢误打误撞,网上搜索一点解决一下问题,后来实在 ...

  3. 数据库vertica 脚本方式的导入导出

    需要进入vsql下的: 导入: copy emp from '/tmp/emp.csv' DELIMITER ',' ESCAPE AS '\' ENCLOSED BY '"' DIRECT ...

  4. zTree的使用教程

    1.首先去官网下载http://www.ztree.me/v3/main.php#_zTreeInfo 2.之后引入: <script src="js/jquery.ztree.all ...

  5. Python_冒泡排序

    从小到大的排序:(最前面的数和一步步和后面的数比较,如果大于则交换,如果不大于则继续循环) 方法1: data = [65, 1, 45, 77, 3, 9, 43, 23, 7, 53, 213, ...

  6. 通过ping命令查看服务器是linux还是windows系列

    通过ping命令识别服务器类型

  7. Bean Shell常用内置变量总结

    JMeter在它的BeanShell中内置了变量,用户可以通过这些变量与JMeter进行交互,其中主要的变量及其使用方法如下: log:写入信息到jmeber.log文件,使用方法:log.info( ...

  8. Filebeat6.31整合Kafka集群消息队列(三)

    wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.3.2-linux-x86_64.tar.gz [root@ ...

  9. python3改版后的特征

    1.原始数据类型和运算符 # 整数 3 # => 3 # 算术没有什么出乎意料的 1 + 1 # => 2 8 - 1 # => 7 10 * 2 # => 20 # 但是除法 ...

  10. Spring AOP中args()、arg-names、argNames

    先小结一下: args()是用来匹配并且接收目标方法的参数的. argNames(用在注解中)与arg-names(用在XML中),他们是同一个东西. argNames用来接收AspectJ表达式中的 ...