首页 > 数据库 > 文库 > 正文

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

2022-08-01 18:56:58
字体:
来源:转载
供稿:网友
      当从库宕机后,读请求会全部转移到主库上,对业务无影响。
1、当主库宕机后
     目前,我们的writehost只设置了一个主库,当主库宕机后,通过mycat的 读写请求会全部报错,如下所示:
 
     读请求:
 
mysql> select * from t1;
ERROR  1184  (HY000): 拒绝连接
    写请求:
 
mysql> insert into t1 values ( 2 );
ERROR  1184  (HY000): 拒绝连接
2、设置多个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" />
    这样配置后,当主库宕机后,写请求就会自动转移到从库上,从而保证业务正常可用。
 
3、当原主库恢复后的处理
     当原主库恢复后,它将不能纳入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 纳管进来了。
 
     也就是说,当主库恢复后,需要手工重新配置主从同步。
 
4、读写分离的条件
   读写分离必须满足如下条件,读操作才能发往从节点执行。
 
  a)必须在schema.xml中配置readHost, 而且balance配置不为0。
  b)SQL语句为select 或者show。
  c)   在非事务中。当然,也可以通过注释/#mycat:db_type=slave, ... / 强制发从。
 
   下面我们测试一下在事务中和在非事务中,select的表现。
 
     先说明一下我的环境,3306是主库,3307是从库。
 
   在 非事务中,可以看到通过mycat查询的是3307 从库的数据:
 
mysql> select * from t1;   //查到的是从库数据
+------+
| id   |
+------+
|  3307  |
+------+
1  row in set ( 0.00  sec)
  在 事务中,可以看到通过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)
   使用 注解,让 事务中的查询, 强制读从库:
 
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)

(编辑:错新网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选