欢迎光临
我们一直在努力

对mycat读写分离主从切换策略的调研

    当从库宕机后,读请求会全部转移到主库上,对业务无影响。

2、当主库宕机后

    目前,我们的writehost只设置了一个主库,当主库宕机后,通过mycat的
读写请求会全部报错,如下所示:

   读请求:

mysql> select * from t1;

ERROR 
1184 
(HY000): 拒绝连接

    写请求:

mysql> insert into t1 values (
2
);

ERROR 
1184 
(HY000): 拒绝连接

3、设置多个writehost,实现主库宕机后,写请求自动切换到从库

    上面看到,如果只设置一个writehost,主库宕机后,并不会自动切换,所有的
读写请求全部受影响。

    为了解决这个我们,我们可以设置多个writehost,当主库宕机后,自动把写请求切换到从节点。

    我们的生产环境是一主一从,我们可以把两个节点都设置为writehost,这样如果writehost1(主库)宕机后,mycat会自动把
请求全部转移到writehost2(从库)上。

    原来配置:

[root
@demo
-init conf]# cat 
schema.xml

<?xml version=
"1.0"
?>

<!DOCTYPE mycat:schema SYSTEM 
"
schema.dtd"

>

<mycat:schema xmlns:mycat=
"
http://io.mycat/"

>

    
<schema name=
"db1" 
checkSQLschema=
"false" 
sqlMaxLimit=
"500" 
dataNode=
"dn1"
></schema>

    
<dataNode name=
"dn1" 
dataHost=
"localhost1" 
database=
"db1" 
/>

    
<dataHost name=
"localhost1" 
maxCon=
"1000" 
minCon=
"10" 
balance=
"3" 
writeType=
"0" 
dbType=
"mysql" 
dbDriver=
"native" 
switchType=
"-1" 
slaveThreshold=
"100"
>

        
<heartbeat>select user()</heartbeat>

        
<!-- can have multi write hosts -->

    
<writeHost host=
"hostM1" 
url=
"
192.168.174.30:3306"
 
user=
"root" 
password=
"123456"
>

    
<readHost  host=
"hostS1" 
url=
"
192.168.174.30:3307"
 
user=
"root" 
password=
"123456" 
/>

    
</writeHost>

    
</dataHost>

</mycat:schema>

  修改后配置:

[root
@demo
-init conf]# cat 
schema.xml

<?xml version=
"1.0"
?>

<!DOCTYPE mycat:schema SYSTEM 
"
schema.dtd"

>

<mycat:schema xmlns:mycat=
"
http://io.mycat/"

>

    
<schema name=
"db1" 
checkSQLschema=
"false" 
sqlMaxLimit=
"500" 
dataNode=
"dn1"
></schema>

    
<dataNode name=
"dn1" 
dataHost=
"localhost1" 
database=
"db1" 
/>

    
<dataHost name=
"localhost1" 
maxCon=
"1000" 
minCon=
"10" 
balance=
"3" 
writeType=
"0" 
dbType=
"mysql" 
dbDriver=
"native" 
switchType=
"1" 
slaveThreshold=
"100"
>

        
<heartbeat>select user()</heartbeat>

        
<!-- can have multi write hosts -->

    
<writeHost host=
"hostM1" 
url=
"
192.168.174.30:3306"
 
user=
"root" 
password=
"123456"
>

    
<readHost  host=
"hostS1" 
url=
"
192.168.174.30:3307"
 
user=
"root" 
password=
"123456" 
/>

    
</writeHost>

    
<writeHost host=
"hostM2" 
url=
"
192.168.174.30:3307"
 
user=
"root" 
password=
"123456"
/>

    
</dataHost>

</mycat:schema>

   就改了两处:

  a)把 switchType="-1"改成 switchType="1";

        说明: switchType:

<writeHost host=
"allinmd-mysql-3" 
url=
"
192.168.174.30:3307"
 
user=
"root" 
password=
"123456"
/>

    这样配置后,当主库宕机后,写请求就会自动转移到从库上,从而保证业务正常可用。

4、当原主库恢复后的处理

     当原主库恢复后,它将不能纳入mycat的管理(blance=3)。也就是说,原主库恢复后,mycat不会把写请求发送到原主库。这是由conf/dnindex.properties来决定的。

    下面是mycat官方文档的说明,摘录在这。

     正常情况下,Mycat 会将第一个 writeHost 作为写节点,所有的 DML SQL 会发送给此节点,若 Mycat 开启了读写分离,则查询节点会根据读写分离的策略发readHost(+writeHost)上执行,当一个 dataHost 里面配置了两个或多个 writeHost 的情况下,如果第一个 writeHost 宕机,则 Mycat 会在默认的3 次心跳检查失败后,自动切换到下一个可用的 writeHost 执行 DML SQL 语句,并在 conf/dnindex.properties文件里记录当前所用的 writeHost 的 index(第一个为 0,第二个为 1,依次类推),注意,此文件不能删除和擅自改变,除非你深刻理解了它的作用以及你的目的。

     那么问题来了,当原来配置的 MySQL 写节点宕机恢复以后,怎么重新加入 Mycat,要不要恢复为原来的写节点?关于这个问题,我们也曾与 DBA 讨论很久,最终的建议方案是,保持现有状态不变,改旗易帜,恢复后的MySQL 节点作为从节点,跟随新的主节点,重新配置主从同步,原先跟随该节点做同步的其他节点也同样换帅,重新配置同步源,这些节点的数据手完成同步以后,再加入 Mycat 里。目前 1.3 版本的 Mycat 还没有实现监控MySQL 主从同步状态的功能,因此这个过程里,DBA 可以先修改 MySQL 的密码,让 Mycat 无法链接故障服务器,等同步完成以后,恢复密码,这样 Mycat 就自动重新将修复好的 Mycat 纳管进来了。

     也就是说,当主库恢复后,需要手工重新配置主从同步。

5、读写分离的条件

   读写分离必须满足如下条件,读操作才能发往从节点执行。

  a)必须在schema.xml中配置readHost, 而且balance配置不为0。

  b)SQL语句为select 或者show。

  c)  
在非事务中。当然,也可以通过注释/#mycat:db_type=slave, … / 强制发从。

   下面我们测试一下在事务中和在非事务中,select的表现。

   
 先说明一下我的环境,3306是主库,3307是从库。

    1、在
非事务中,可以看到通过mycat查询的是3307
从库的数据:

mysql> select * from t1;  
//查到的是从库数据

+------+

| id   |

+------+


3307 
|

+------+

1 
row in set (

0.00
 
sec)

   2、在
事务中,可以看到通过mycat查询的是3306
主库的数据:

mysql> begin;

Query OK, 
0 
rows affected (

0.00
 
sec)
 

mysql> select * from t1; 
//查到的是主库数据

+------+

| id |

+------+


3306 
|

+------+

1 
row in set (

0.00
 
sec)

   3、使用
注解,让
事务中的查询,
强制读从库

mysql> begin;

Query OK, 
0 
rows affected (

0.00
 
sec)
 

mysql> select * from t1;  
//看到select 在事务中读了主库

+------+

| id |

+------+


3306 
|

+------+

1 
row in set (

0.00
 
sec)
 

mysql> 
/*!mycat:db_type=slave*/
select * from t1;    
//看到加了注解后,select 在事务中读了从库

+------+

| id |

+------+


3307 
|

+------+

1 
row in set (

0.01
 
sec)
 

mysql> select * from t1;  
//看到select 在事务中读了主库

+------+

| id |

+------+


3306 
|

+------+

1 
row in set (

0.00
 
sec)

6、官方建议的mycat读写分离架构


赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。