Mycat面试知识点总结

  现在的面试越来越变态了,不少公司还是会考分库分表的,倒不一定会考多深,但是如果一点答不上来那就让面试官的印象很差,本文是自己搭建mycat的经验外加参考网上他人的经验写成,目的很简单应付面试的。

一 Mycat基本概念

  先看schema.xml这个配置文件

<mycat:schema xmlns:mycat="http://io.mycat/">
  <schema name="RDRS_MYCAT_POC" checkSQLschema="true" sqlMaxLimit="100000">
    <table name="MYCAT_SOURCETABLE" primaryKey="USERID" subTables="mycat_sourcetable_$0-7" rule="mycatrule8" dataNode="mysql_node_1,mysql_node_2" selDbColumn="USERID"></table>
    <table name="mycat_sourcetable_0,mycat_sourcetable_1,mycat_sourcetable_2,mycat_sourcetable_3" primaryKey="USERID" dataNode="mysql_node_1"/>
    <table name="mycat_sourcetable_4,mycat_sourcetable_5,mycat_sourcetable_6,mycat_sourcetable_7" primaryKey="USERID" dataNode="mysql_node_2"/>
    <table name="LL_SOURCE_TABLE" subTables="ll_source_table_$00-03" rule="mycatrule4" dataNode="mysql_node_1,mysql_node_2" selDbColumn="USERID"></table>
    <table name="ll_source_table_00,ll_source_table_01" dataNode="mysql_node_1"/>
    <table name="ll_source_table_02,ll_source_table_03" dataNode="mysql_node_2"/>
  </schema>
  <dataNode name="mysql_node_1" dataHost="mysql_1" database="rdrsshard_001"/>
  <dataNode name="mysql_node_2" dataHost="mysql_2" database="rdrsshard_002"/>
  <dataHost name="mysql_1" maxCon="500" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <writeHost host="mysql_1" url="10.47.147.44:3306" user="rdrsuser" password="************"/>
  </dataHost>
  <dataHost name="mysql_2" maxCon="500" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <writeHost host="mysql_2" url="10.47.147.43:3306" user="rdrsuser" password="************"/>
  </dataHost>
</mycat:schema>

  从上面的xml节点也能看的出来,mycat主要有四大节点类型

  1.Schema:逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table。
  2.Table:逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。
分片表:是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。
  3.DataNode:分片节点、数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点。
  4.DataHost:节点主机,数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。
  5.rule:分片规则,前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。

二 Mycat写原理

  看一组新的配置

  rule.xml

<tableRule name="role1">
        <rule>
         <!--columns分片字段,algorithm取模算法-->
            <columns>id</columns>
            <algorithm>mod-long</algorithm>
        </rule>
    </tableRule>
 
    <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
        <!--指定分片数量也就是几个库,不可以被更改-->
        <property name="count">3</property>
</function>

  schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- TESTDB1 是mycat的逻辑库名称,链接需要用的 -->
    <schema name="mycat_testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
     
    <table name="area_info" dataNode="dn1,dn2,dn3" rule="role1"/>
    
    </schema>
        <!-- database 是MySQL数据库的库名 -->
    <dataNode name="dn1" dataHost="localhost" database="userdb_1" />
    <dataNode name="dn2" dataHost="localhost" database="userdb_2" />
    <dataNode name="dn3" dataHost="localhost" database="userdb_3" />
    <!--
    dataNode节点中各属性说明:
    name:指定逻辑数据节点名称;
    dataHost:指定逻辑数据节点物理主机节点名称;
    database:指定物理主机节点上。如果一个节点上有多个库,可使用表达式db$0-99,     表示指定0-99这100个数据库;

    dataHost 节点中各属性说明:
        name:物理主机节点名称;
        maxCon:指定物理主机服务最大支持1000个连接;
        minCon:指定物理主机服务最小保持10个连接;
        writeType:指定写入类型;
            0,只在writeHost节点写入;
            1,在所有节点都写入。慎重开启,多节点写入顺序为默认写入根据配置顺序,第一个挂掉切换另一个;
        dbType:指定数据库类型;
        dbDriver:指定数据库驱动;
        balance:指定物理主机服务的负载模式。
            0,不开启读写分离机制;
            1,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡;
            2,所有的readHost与writeHost都参与select语句的负载均衡,也就是说,当系统的写操作压力不大的情况下,所有主机都可以承担负载均衡;
-->
    <dataHost name="localhost" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <!-- 可以配置多个主从 -->
        <writeHost host="hostM1" url="192.168.223.141:3306" user="root" password="123456">
            <!-- 可以配置多个从库 -->
            <readHost host="hostS2" url="192.168.223.142:3306" user="root" password="123456" />
        </writeHost>
    </dataHost>
</mycat:schema>

  假如现在有记录 id 1 2 3 4 5 10

  插入时的逻辑如下

1%3 取模 后1,userdb_2
2 %3取模 后2,userdb_3
3 %3取模 后0,userdb_1
4 %3取模 后1,userdb_2
5 %3取模 后2,userdb_3
10 %3取模 后1,userdb_2

  第一种情况相对来说简单,是直接对某一个字段值进行分片路由的。还有第二种情况,这种情况会稍微复杂一些,先在一个文件里写明某一个字段值做映射后的值,然后再做映射。

  使用场景:比如QQ注册用户上亿,我们可以按地区注册分表,这样单表的数据量就没有那么大了。
  partition-hash-int.txt (名字随意,但是要和配置文件里的一致)

wuhan=0
shanghai=1
suzhou=2

  

<tableRule name="role2">
             <rule>
                <!--上面columns 标识将要分片的表字段,algorithm 分片函数-->
                  <columns>name</columns>
                <algorithm>hash-int</algorithm>
                </rule>
    </tableRule>
    
    <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
        <!--其中分片函数配置中,mapFile标识配置文件名称,type默认值为0,0表示Integer,非零表示String-->
        <property name="mapFile">partition-hash-int.txt</property>
        <!--
        所有的节点配置都是从0开始,及0代表节点1
        defaultNode 默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点,结点为指定的值
        默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点
        如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到
        不识别的枚举值就会报错,
        like this:can't find datanode for sharding column:column_name val:ffffffff    
        -->
        <property name="type">1</property>
        <property name="defaultNode">1</property>
    </function>

  按照上面的配置后,数据分配就会像下面的示例那样分配

wuhan      userdb_1
shanghai   nanjing   xian   userdb_2
suzhou     userdb_3

三 Mycat读原理

  1 where条件是分片字段

    如果where条件是分片字段,那么根据分片字段直接请求其对应的物理库进行查询,也就是说只会查询一个库

  2 where条件不是分片字段

    会在所有物理库中执行语句,再把结果集返回

  3 limit分页查询 假设语句是 select * from area_info desc limit 0,2

    向所有库查询,每个库返回两条数据,然后由mycat组装成数据集合,然后从mycat组装数据中随机抽取两条数据。

·   4  select * from area_info ORDER BY id desc limit 0,2

    查询三个库,返回每个库中最大的两条,mycat组装成数据集合,最后选取组装的数据中,最大的两条数据

四 Mycat配置读写分离 

Balance参数设置:

1. balance=“0”, 所有读操作都发送到当前可用的writeHost上。

2. balance=“1”,所有的readHost和stand by writeHost参与select语句的负载均衡,当双主双从模式(M1->S1,M2->S2,并且M1和M2互为主备),这样M2,S1,S2都会参与select语句的负载均衡

3. balance=“2”,所有读操作都随机的在writeHost、readhost上分发

4. balance="3" 所有的读请求随机的分发到readhost执行,writeHost不担负读压力

WriteType参数设置:

1. writeType=“0”, 所有写操作都发送到可用的writeHost上。可用于双主双从的模式下,一个主挂了不影响整个mysql+集群

2. writeType=“1”,所有写操作都随机的发送到readHost。

3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。

SwitchType参数:

  1. 1 默认值,自动切换
  2. -1 表示不自动切换
  3. 2 基于MySql主从同步的状态决定是否自动切换

五 双主模式如何配置

  所谓的双主模式,假设有四台MYSQL,机器M1,M2,S1,S2.首先将M1,S1配成一主一从,相同的M2,S2配成一主一从。然后M1和M2配成互为对方的从,这就准备好了物理机。

  然后在mycat的Schema.xml中这样配置

<mycat:schema xmlns:mycat="http://io.mycat/">
  <schema name="RDRS_MYCAT_POC" checkSQLschema="true" sqlMaxLimit="100000">
    
  </schema>
  <dataNode name="dn1" dataHost="host1" database="testdb"/>
  
  <dataHost name="host1" maxCon="500" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <writeHost host="hostM1" url="192.168.140.128:3306" user="rdrsuser" password="************">
        <readHost host="hostS1" url="192.168.140.127:3306" user="rdrsuser" password="************">
    </writeHost>
    <writeHost host="hostM2" url="192.168.140.126:3306" user="rdrsuser" password="************">
        <readHost host="hostS2" url="192.168.140.125:3306" user="rdrsuser" password="************">
    </writeHost>
  </dataHost>
  
</mycat:schema>

 

posted on 2021-01-26 15:25  MaXianZhe  阅读(509)  评论(0编辑  收藏  举报

导航