zoukankan      html  css  js  c++  java
  • MyCat 离线扩缩容

    当我们规划了数据分片,而数据已经超过了单个节点的存储上线,或者需要下线节 点的时候,就需要对数据重新分片。

    Mycat 自带的工具

    准备工作:

    1、mycat 所在环境安装 mysql 客户端程序。

    2、mycat 的 lib 目录下添加 mysql 的 jdbc 驱动包。

    3、对扩容缩容的表所有节点数据进行备份,以便迁移失败后的数据恢复。

    步骤:

    以取模分片表 sharding-by-mod 缩容为例:

    1、复制 schema.xml、rule.xml 并重命名为 newSchema.xml、newRule.xml 放 于 conf 目录下。

    2、修改 newSchema.xml 和 newRule.xml 配置文件为扩容缩容后的 mycat 配置参数(表的节点数、数据源、路由规则)。

    注意:

    只有节点变化的表才会进行迁移。仅分片配置变化不会迁移。

    newSchema.xml

    <table name="sharding_by_mod" dataNode="dn1,dn2,dn3" rule="qs-sharding-by-mod" />
    

    改成(减少了一个节点):

    <table name="sharding_by_mod" dataNode="dn1,dn2" rule="qs-sharding-by-mod" />
    

    newRule.xml 修改 count 个数

    <function name="qs-sharding-by-mod-long" class="io.mycat.route.function.PartitionByMod">
        <property name="count">2</property>
    </function>
    

    3、修改 conf 目录下的 migrateTables.properties 配置文件,告诉工具哪些表 需要进行扩容或缩容,没有出现在此配置文件的 schema 表不会进行数据迁移,

    格 式:

    注意:

    • 1)不迁移的表,不要修改 dn 个数,否则会报错。
    • 2)ER 表,因为只有主表有分片规则,子表不会迁移。

    4、dataMigrate.sh 中这个必须要配置 通 过 命 令 "find / -name mysqldump" 查 找 mysqldump 路 径 为 "/usr/bin/mysqldump",指定#mysql bin 路径为"/usr/bin/"

    #mysql bin 路径
    RUN_CMD="$RUN_CMD -mysqlBin= /usr/bin/"
    

    5、停止 mycat 服务

    6、执行执行 bin/ dataMigrate.sh 脚本 注意:必须要配置 Java 环境变量,不能用 openjdk

    7 、 脚 本 执 行 完 成 , 如 果 最 后 的 数 据 迁 移 验 证 通 过 , 就 可 以 将 之 前 的 newSchema.xml 和 newRule.xml 替换之前的 schema.xml 和 rule.xml 文 件,并重启 mycat 即可。

    注意事项:

    • 1)保证分片表迁移数据前后路由规则一致(取模——取模)。
    • 2)保证分片表迁移数据前后分片字段一致。
    • 3)全局表将被忽略。
    • 4)不要将非分片表配置到 migrateTables.properties 文件中。
    • 5)暂时只支持分片表使用 MySQL 作为数据源的扩容缩容。

    migrate 限制比较多,还可以使用 mysqldump。

    mysqldump 方式:

    系统第一次上线,把单张表迁移到 Mycat,也可以用 mysqldump。

    MySQL 导出

    mysqldump -uroot -p123456 -h127.0.0.1 -P3306 -c -t --skip-extended-insert gpcat > mysql-1017.sql
    

    -c 代表带列名

    -t 代表只要数据,不要建表语句

    --skip-extended-insert 代表生成多行 insert(mycat childtable 不支持多行插入ChildTable multi insert not provided)

    Mycat 导入:

    mysql -uroot -p123456 -h127.0.0.1 -P8066 catmall < mysql-1017.sql
    

    Mycat 导出:

    mysqldump -h192.168.8.151 -uroot -p123456 -P8066 -c -t --skip-extended-insert catmall customer > mycat-cust.sql
    

    其他导入方式: load data local infile '/mycat/customer.txt' into table customer; source sql '/mycat/customer.sql';

    核心流程总结

    官网的架构图:

    启动:

    • 1、MycatServer 启动,解析配置文件,包括服务器、分片规则等
    • 2、创建工作线程,建立前端连接和后端连接

    执行 SQL

    1、前端连接接收 MySQL 命令

    2、解析 MySQL,Mycat 用的是 Druid 的 DruidParser

    3、获取路由

    4、改写 MySQL

    例如两个条件在两个节点上,则变成两条单独的 SQL 例如 select * from customer where id in(5000001, 10000001);

    改写成:

    select * from customer where id = 5000001;(dn2 执行)

    select * from customer where id = 10000001;(dn3 执行)

    又比如多表关联查询,先到各个分片上去获取结果,然后在内存中计算

    5、与后端数据库建立连接

    6、发送 SQL 语句到 MySQL 执行

    7、获取返回结果

    8、处理返回结果,例如排序、计算等等

    9、返回给客户端

    源码下载与调试环境搭建:

    下载源代码,导入工程:

    git clone https://github.com/MyCATApache/Mycat-Server

    配置:

    schema.xml

    <?xml version="1.0"?>
    <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
            <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
            <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
            <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="mod-long" />
        </schema>
        <dataNode name="dn1" dataHost="localhost1" database="db1" />
        <dataNode name="dn2" dataHost="localhost1" database="db2" />
        <dataNode name="dn3" dataHost="localhost1" database="db3" />
        <dataHost name="localhost1" maxCon="20" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
            <heartbeat>select user()</heartbeat>
            <writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="123456">
            </writeHost>
        </dataHost>
    </mycat:schema>
    

    表结构:

    本地数据库创建 db1、db2、db3 数据库,全部执行建表脚本

    CREATE TABLE `company` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `name` varchar(64) DEFAULT '', 
    `market_value` bigint(20) DEFAULT '0', PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
    
    CREATE TABLE `hotnews` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `title` varchar(64) DEFAULT '', 
    `content` varchar(512) DEFAULT '0', 
    `time` varchar(8) DEFAULT '', 
    `cat_name` varchar(10) DEFAULT '', PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    CREATE TABLE `travelrecord` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `city` varchar(32) DEFAULT '', 
    `time` varchar(8) DEFAULT '', PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

    逻辑表配置:

    travelrecord 表配置:

    <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
    <tableRule name="auto-sharding-long">
    <rule>
        <columns>id</columns>
        <algorithm>rang-long</algorithm>
    </rule>
    </tableRule>
    <function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
    <property name="mapFile">autopartition-long.txt</property>
    </function>
    

    hotnews 表配置:

    <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="mod-long" />
    <tableRule name="mod-long">
    <rule>
        <columns>id</columns>
        <algorithm>mod-long</algorithm>
    </rule>
    </tableRule>
    <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
      <!-- how many data nodes -->
      <property name="count">3</property>
    </function>
    

    company 表配置:

    <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
    

    debug 方式启动:

    main 方法

    Mycat-Server-1.6.5-RELEASEsrcmainjavaiomycatMycatStartup.java

    连接本机 Mycat 服务

    测试语句:

    insert into travelrecord(`id`, `city`, `time`) values(1, '长沙', '20191020');
    insert into hotnews(`title`, `content`) values('哈哈', '盆鱼宴');
    insert into company(`name`, `market_value`) values('spring', 100);
    

    调试入口:

    连接入口: io.mycat.net.NIOAcceptor#accept SQL

    入口: io.mycat.server.ServerQueryHandler#query

    Step Over 可以看到上一层的调用

  • 相关阅读:
    唯品会面经
    动态代理两种实现方式
    腾讯运营开发面经
    MySQL一些中重要命令
    金山wps面经
    三七互娱面经
    排序算法之快速排序(Quicksort)解析
    全排列算法分析(原创方法/一般方法/字典序法)
    WinForm如何去掉右边和下边的白边
    Java异常处理机制的秘密
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13691503.html
Copyright © 2011-2022 走看看