微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

mycat结合MySQL双主实现读写分离

《mycat结合MysqL双主实现读写分离》要点:
本文介绍了mycat结合MysqL双主实现读写分离,希望对您有用。如果有疑问,可以联系我们。

作者介绍

牛恒博,一线运维人,擅长为中小企业快速实现运维从无到有,再到自动化.现就职于某医疗大数据公司.

服务器拓扑

MySQL

服务器架构

mycat结合MySQL双主实现读写分离

安装MysqL

创建MysqL用户

groupadd MysqL
useradd -r -g MysqL -s /bin/false MysqL

安装MysqL

yum install -y libaio
cd /usr/local/src/
wget http://mirrors.sohu.com/MysqL/MysqL-5.7/MysqL-5.7.17-linux-glibc2.5-x86_64.tar.gz
tar -zxf MysqL-5.7.17-linux-glibc2.5-x86_64.tar.gz 
cp -rf MysqL-5.7.17-linux-glibc2.5-x86_64 /data/app/MysqL-3306
cp -rf MysqL-5.7.17-linux-glibc2.5-x86_64 /data/app/MysqL-3307
chown -R MysqL:MysqL /data/app/MysqL-3306
chown -R MysqL:MysqL /data/app/MysqL-3307
/data/app/MysqL-3306/bin/MysqLd --initialize-insecure --user=MysqL --basedir=/data/app/MysqL-3306 --datadir=/data/app/MysqL-3306/data
/data/app/MysqL-3307/bin/MysqLd --initialize-insecure --user=MysqL --basedir=/data/app/MysqL-3307 --datadir=/data/app/MysqL-3307/data

修改my.cnf

需要修改的参数: 

  • server-id:保证每个配置文件唯一
  • 两台master的自增长ID必须不同

linux-node2

master

cat > /data/app/MysqL-3306/my.cnf<<EOF
[client]
port = 3306
socket = /data/app/MysqL-3306/MysqL.sock
[MysqLd]

port = 3306
user = MysqL
server-id = 1
bind-address = 0.0.0.0
basedir = /data/app/MysqL-3306
datadir = /data/app/MysqL-3306/data
socket = /data/app/MysqL-3306/MysqL.sock
pid-file = /data/app/MysqL-3306/MysqL.pid
log-error = /data/app/MysqL-3306/MysqLd.log

skip-name-resolve
log_bin = MysqL-bin
log-slave-updates
auto-increment-increment = 2 
auto-increment-offset = 1

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 
EOF
chown MysqL.MysqL /data/app/MysqL-3306/my.cnf

slave

cat > /data/app/MysqL-3307/my.cnf<<EOF
[client]
port = 3307
socket = /data/app/MysqL-3307/MysqL.sock
[MysqLd]

port = 3307
user = MysqL
server-id = 11
bind-address = 0.0.0.0
basedir = /data/app/MysqL-3307
datadir = /data/app/MysqL-3307/data
socket = /data/app/MysqL-3307/MysqL.sock
pid-file = /data/app/MysqL-3307/MysqL.pid
log-error = /data/app/MysqL-3307/MysqLd.log

skip-name-resolve
log_bin = MysqL-bin


sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 
EOF
chown MysqL.MysqL /data/app/MysqL-3307/my.cnf

linux-node3

master

cat > /data/app/MysqL-3306/my.cnf<<EOF
[client]
port = 3306
socket = /data/app/MysqL-3306/MysqL.sock
[MysqLd]

port = 3306
user = MysqL
server-id = 2
bind-address = 0.0.0.0
basedir = /data/app/MysqL-3306
datadir = /data/app/MysqL-3306/data
socket = /data/app/MysqL-3306/MysqL.sock
pid-file = /data/app/MysqL-3306/MysqL.pid
log-error = /data/app/MysqL-3306/MysqLd.log

skip-name-resolve
log_bin = MysqL-bin
log-slave-updates
auto-increment-increment = 2 
auto-increment-offset = 2

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 
EOF
chown MysqL.MysqL /data/app/MysqL-3306/my.cnf

slave

cat > /data/app/MysqL-3307/my.cnf<<EOF
[client]
port = 3307
socket = /data/app/MysqL-3307/MysqL.sock
[MysqLd]

port = 3307
user = MysqL
server-id = 22
bind-address = 0.0.0.0
basedir = /data/app/MysqL-3307
datadir = /data/app/MysqL-3307/data
socket = /data/app/MysqL-3307/MysqL.sock
pid-file = /data/app/MysqL-3307/MysqL.pid
log-error = /data/app/MysqL-3307/MysqLd.log

skip-name-resolve
log_bin = MysqL-bin


sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 
EOF
chown MysqL.MysqL /data/app/MysqL-3307/my.cnf

启动MysqL

启动服务

linux-node2和linux-node3都执行如下命令

touch /data/app/MysqL-3306/MysqLd.log && chown MysqL.MysqL /data/app/MysqL-3306/MysqLd.log
sed -i 's#/usr/local/MysqL#/data/app/MysqL-3306#g' /data/app/MysqL-3306/bin/MysqLd_safe 
/data/app/MysqL-3306/bin/MysqLd_safe --defaults-file=/data/app/MysqL-3306/my.cnf --basedir=/data/app/MysqL-3306 --datadir=/data/app/MysqL-3306/data --user=MysqL &


touch /data/app/MysqL-3307/MysqLd.log && chown MysqL.MysqL /data/app/MysqL-3307/MysqLd.log
sed -i 's#/usr/local/MysqL#/data/app/MysqL-3307#g' /data/app/MysqL-3307/bin/MysqLd_safe 
/data/app/MysqL-3307/bin/MysqLd_safe --defaults-file=/data/app/MysqL-3307/my.cnf --basedir=/data/app/MysqL-3307 --datadir=/data/app/MysqL-3307/data --user=MysqL &

检查端口

ss -lntup |egrep '3306|3307'
tcp    LISTEN     0      80                     *:3306                  *:*      users:(("MysqLd",19973,22))
tcp    LISTEN     0      80                     *:3307                  *:*      users:(("MysqLd",20537,22))

配置双主

配置主从

linux-node2

master

cd /data/app/MysqL-3306/
./bin/MysqL -uroot -p -S MysqL.sock -P 3306
MysqL> CREATE USER 'repl'@'192.%' IDENTIFIED BY 'MysqL';
Query OK,0 rows affected (0.05 sec)

MysqL> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.%';
Query OK,0 rows affected (0.00 sec)

MysqL> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | binlog_Do_DB | binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| MysqL-bin.000001 |      613 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

slave

cd /data/app/MysqL-3307/
./bin/MysqL -uroot -p -S MysqL.sock -P 3307
MysqL> CHANGE MASTER TO MASTER_HOST='192.168.56.12',   ->                  MASTER_PORT=3306,   ->                  MASTER_USER='repl',   ->                  MASTER_PASSWORD='MysqL',   ->                  MASTER_LOG_FILE='MysqL-bin.000001',   ->                  MASTER_LOG_POS=613;
Query OK,0 rows affected,2 warnings (0.04 sec)

MysqL> start slave;
Query OK,0 rows affected (0.02 sec)
MysqL> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.56.12
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: MysqL-bin.000001
          Read_Master_Log_Pos: 613
               Relay_Log_File: linux-node2-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: MysqL-bin.000001
             Slave_IO_Running: Yes
            Slave_sql_Running: Yes

linux-node3

master

cd /data/app/MysqL-3306/
./bin/MysqL -uroot -p -S MysqL.sock -P 3306
MysqL> CREATE USER 'repl'@'192.%' IDENTIFIED BY 'MysqL';
Query OK,0 rows affected (0.00 sec)

MysqL> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | binlog_Do_DB | binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| MysqL-bin.000001 |      613 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

slave

cd /data/app/MysqL-3307/
./bin/MysqL -uroot -p -S MysqL.sock -P 3307
MysqL> 
CHANGE MASTER TO MASTER_HOST='192.168.56.13',                MASTER_PORT=3306,                MASTER_USER='repl',                MASTER_PASSWORD='MysqL',                MASTER_LOG_FILE='MysqL-bin.000001',                MASTER_LOG_POS=613;
Query OK,0 rows affected (0.02 sec)
MysqL> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.56.13
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: MysqL-bin.000001
          Read_Master_Log_Pos: 613
               Relay_Log_File: linux-node2-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: MysqL-bin.000001
             Slave_IO_Running: Yes
            Slave_sql_Running: Yes

配置双主

master的binlog位置

linux-node2 master端

d /data/app/MysqL-3306/
./bin/MysqL -uroot -p -S MysqL.sock -P 3306
MysqL> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | binlog_Do_DB | binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| MysqL-bin.000001 |      613 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

linux-node3 master端

cd /data/app/MysqL-3306/
./bin/MysqL -uroot -p -S MysqL.sock -P 3306
MysqL> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | binlog_Do_DB | binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| MysqL-bin.000001 |      613 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

linux-node2 master配置跟linux-node3 master同步

MysqL> CHANGE MASTER TO MASTER_HOST='192.168.56.13',                MASTER_LOG_POS=613;
MysqL> start slave;
Query OK,0 rows affected (0.03 sec)

MysqL> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.56.13
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: MysqL-bin.000001
          Read_Master_Log_Pos: 613
               Relay_Log_File: linux-node2-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: MysqL-bin.000001
             Slave_IO_Running: Yes
            Slave_sql_Running: Yes         

linux-node3 master配置跟linux-node2 master同步

MysqL> CHANGE MASTER TO MASTER_HOST='192.168.56.12',0 rows affected (0.00 sec)

MysqL> 
MysqL> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.56.12
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: MysqL-bin.000001
          Read_Master_Log_Pos: 613
               Relay_Log_File: linux-node3-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: MysqL-bin.000001
             Slave_IO_Running: Yes
            Slave_sql_Running: Yes

验证

从linux-node2上验证

在linux-node2 master上创建数据

MysqL> create database test;
Query OK,1 row affected (0.01 sec)

MysqL> use test;
Database changed

MysqL> create table temp(id int,name varchar(64));
Query OK,0 rows affected (0.11 sec)

MysqL> insert into temp values(1,'aaa');
Query OK,1 row affected (0.28 sec)

MysqL> CREATE TABLE temp2(id INT PRIMARY KEY  NOT NULL AUTO_INCREMENT,nname VARCHAR(64));
Query OK,0 rows affected (0.01 sec)

MysqL> insert into temp2(nname) values('bbb');
Query OK,1 row affected (0.01 sec)

MysqL> select * from test.temp;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
+------+------+
1 row in set (0.01 sec)

在linux-node2 slave上查看数据

MysqL> select * from test.temp;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
+------+------+
1 row in set (0.00 sec)

在linux-node3 master上查看数据

MysqL> select * from test.temp;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
+------+------+
1 row in set (0.00 sec)

在linux-node3 slave上查看数据

MysqL> select * from test.temp;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
+------+------+
1 row in set (0.00 sec)

从linux-node3上验证

在linux-node3 master上创建数据

MysqL> use test;

MysqL> insert into temp2(nname) values('ddd');
Query OK,1 row affected (0.02 sec)
MysqL>  insert into temp2(nname) values('fff');
Query OK,1 row affected (0.00 sec)

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
+----+-------+

在linux-node3 slave上查看数据

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
+----+-------+
3 rows in set (0.00 sec)

在linux-node2 master上查看数据

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
+----+-------+
3 rows in set (0.00 sec)

在linux-node2 slave上查看数据

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
+----+-------+
3 rows in set (0.00 sec)

结论

  • 在任意一个master端更新数据,其他任意端都可以更新数据
  • 两台服务器配置了间隔自增长,数据不同冲突

linux-node1上安装mycat

安装mycat

cd /usr/local/src
wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
tar -zxf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz 
mv mycat /data/app/mycat-1.6
ln -s /data/app/mycat-1.6 /data/app/mycat

修改schema.xml

  • balance="1"
    全部的readHost与stand by writeHost参与select语句的负载均衡
  • writeType="0"
    所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个 writeHost,重新启动后以切换后的为准,切换记录在配置文件中:dnindex.properties
  • switchType="1"
    认值为1,自动切换
cd /data/app/mycat
cp conf/schema.xml conf/schema.xml.bak
cat > conf/schema.xml <<EOF
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYstem "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checksqlschema="true" sqlMaxLimit="100" datanode="dn1"></schema>
    <datanode name="dn1" dataHost="node1" database="test" />
    <dataHost name="node1" maxCon="10" minCon="5" balance="1" writeType="0" dbType="MysqL" dbDriver="native" switchType="1">
        <heartbeat>select user()</heartbeat>
        <writeHost host="master1" url="192.168.56.12:3306" user="root" password="MysqL">
            <readHost host="slave2" url="192.168.56.13:3307" user="root" password="MysqL" />
        </writeHost>
        <writeHost host="master2" url="192.168.56.13:3306" user="root" password="MysqL">
            <readHost host="slave2" url="192.168.56.13:3307" user="root" password="MysqL" />
        </writeHost>
    </dataHost>
</mycat:schema>
EOF

启动mycat

./bin/mycat start 
ss -lntup |egrep  '(8066|9066)'  
tcp    LISTEN     0      100                   :::8066                 :::*      users:(("java",16546,79))
tcp    LISTEN     0      100                   :::9066                 :::*      users:(("java",75))

验证mycat服务是否正常

在linux-node2-master端配置mycat连接账号

MysqL> GRANT ALL PRIVILEGES ON *.* TO root@'192.%' IDENTIFIED BY 'MysqL'; 
Query OK,1 warning (0.07 sec

在mycat服务器上安装MysqL服务,但是不启动

步骤省略,详细内容可以参考上面的MysqL安装

使用MysqL的客户端连接mycat

cd /data/app/MysqL/
./bin/MysqL -uroot -p -P 8066 -h 192.168.56.11 ##连接mycat,初始密码123456
MysqL> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+
1 row in set (0.00 sec)

MysqL> use TESTDB;

MysqL> insert into temp2(nname) values('eee');
Query OK,1 row affected (0.09 sec)
MysqL> insert into temp2(nname) values('ggg');
Query OK,1 row affected (0.01 sec)

linux-node3 slave端查看数据是否同步

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
|  5 | eee   |
|  7 | ggg   |
+----+-------+
5 rows in set (0.00 sec)

结果发现数据写入到了linux-node2 slave端

测试

服务自动迁移

关闭linux-node2 master的MysqL服务

MysqL> shutdown;
Query OK,0 rows affected (0.01 sec)

shell > ss -lntup |grep 3306

mycat端插入新的数据查看数据是否同步

MysqL> insert into temp2(nname) values('mmmm');
Query OK,1 row affected (0.07 sec)

MysqL> insert into temp2(nname) values('nnnn');
Query OK,1 row affected (0.01 sec)

linux-node3 slave端查看数据是否同步

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
|  5 | eee   |
|  7 | ggg   |
|  8 | mmmm  |
| 10 | nnnn  |
+----+-------+
7 rows in set (0.00 sec)

linux-node2 slave端查看数据是否同步

MysqL> select * from test.temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
|  5 | eee   |
|  7 | ggg   |
+----+-------+
5 rows in set (0.00 sec)
 发现因为linux-node2的master端已经挂了,数据不能同步了

数据访问是否正常

登录到mycat服务器上执行如下命令:

MysqL> select * from temp2;
+----+-------+
| id | nname |
+----+-------+
|  1 | bbb   |
|  2 | ddd   |
|  4 | fff   |
|  5 | eee   |
|  7 | ggg   |
|  8 | mmmm  |
| 10 | nnnn  |
+----+-------+
7 rows in set (0.00 sec) 
执行多次发现结果一样,说明在一台master端挂掉的情况下,其连接的slave端也被剔除,因此数据完整性可以保证

故障汇总

第一次配置的时候maser端没有配置log-slave-updates,导致node3-slave上没有node2-master端的数据.
解释:
从库开启log-bin参数,如果直接往从库写数据,是可以记录log-bin日志的,但是从库通过I0线程读取主库二进制日志文件,然后通过sql线程写入的数据,是不会记录binlog日志的.也就是说从库从主库上复制的数据,是不写入从库的binlog日志的.所以从库做为其他从库的主库时需要在配置文件添加log-slave-updates参数.

解决办法:

[MysqLd]
log-slave-updates

文章来自微信公众号: DevOps视角

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐