• MyCat学习记录


    一、准备工作

    1、安装Java(>=1.7)

    1)下载

    下载地址:http://www.oracle.com/technetwork/java/javase/archive-139210.html

    解压: tar zxvf xxx.tar.gz -C /usr/local/

    2)配置环境变量

    vi /etc/profile:添加内容:

    export JAVA_HOME=/usr/java/jdk1.7
    export PATH=$JAVA_HOME/bin:$PATH 
    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

    source /etc/profile:使/etc/profile文件生效

    3)验证

    java -version

    2、安装MyCat

    1)下载

    下载地址:https://github.com/MyCATApache/Mycat-download

    解压: tar zxvf xxx.tar.gz -C /usr/local/

    2)配置环境变量

    vi /etc/profile:添加内容:

    export MYCAT_HOME=/usr/local/mycat

    source /etc/profile:使/etc/profile文件生效

    3)结构

    conf/service.xml:定义系统参数和授权
    conf/schema.xml:定义逻辑库、表、分片节点
    conf/rule.xml:定义分片规则等
    bin/mycat [start/stop/restart]:主程序
    默认端口:8066

    3、修改MySql

    修改my.cnf:vi /etc/mysql/my.cnf:在 [mysqld] 下添加内容:

    lower_case_table_names = 1

    重启服务:service mysql restart

    二、简单配置schema.xml

    1、Schema节点

    逻辑库(好比数据库),在里面需要定义对各个表的“规则”

    2、dataNode节点

    数据节点,上面的逻辑库和这个dataNode要进行绑定

    3、dataHost节点

    数据库配置,dataNode节点和其进行绑定

    属性writeType:

    • 0(默认从第一个writeHost写数据)
    • 1(随机发送写操作)

    属性balance:

    • 0(不开启读写分离,所有读操作都加在writeHost 上)
    • 1(全部writeHost和readHost都参与select)
    • 2(所有读操作都随机在writeHost、readhost 上处理)
    • 3(所有读请求都在readhost执行,writerHost只负责写,读写分离)
    <?xml version="1.0"?>
    <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://org.opencloudb/">
    
        <schema name="txl" checkSQLschema="false" sqlMaxLimit="100">
            <!-- auto sharding by id (long) -->
            <table name="news_main" primaryKey="news_id" type="global" dataNode="dn1,dn2"/>
        </schema> 
    
        <dataNode name="dn1" dataHost="localhost1" database="jtthink" />
        <dataNode name="dn2" dataHost="localhost2" database="jtthink" />
    
        <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.32.128:3306" user="root"
            password="txl">
                <readHost host="hostS1" url="192.168.1.101:3306" user="root"
                password="123"/>
            </writeHost>
        </dataHost>
    
        <dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
            writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
            <heartbeat>select user()</heartbeat>
            <!-- can have multi write hosts -->
            <writeHost host="hostM1" url="xxx:3306" user="xxx"
                password="xxx">
            </writeHost> 
        </dataHost>
    </mycat:schema>

    三、全局表

    一般不经常产生修改的表,如配置表、类别表以及数据量不是很大的表会设置成全局表

    1、设置全局表:type=global

    <table name="news_class" primaryKey="class_id" autoIncrement="true" type="global" dataNode="dn1" />

    2、作用

    • 和具体物理表一一对应
    • 多节点配置时出现新增、修改操作时,则mycat会对所有节点(dataNode)发送该操作,保证所有的节点里面的全局表保持同步

    四、全局序列号(sequnce)

    在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一。为此,MyCat 提供了全局sequence,并且提供了包含本地配置和数据库配置等多种实现方式。

    1、本地文件方式

    原理:此方式 MyCAT 将 sequence 配置到文件中,当使用到 sequence 中的配置后,MyCAT 会更新 classpath 中的 sequence_conf.properties 文件中 sequence 当前的值。

    配置方式:
    在 server.xml 文件的 system 节点下做如下配置:

    <property name="sequnceHandlerType">0</property>

    在 sequence_conf.properties 文件中做如下配置:

    GLOBAL.HISIDS=        //示使用过的历史分段(一般无需设置)
    GLOBAL.MINID=1        //最小值
    GLOBAL.MAXID=100000   //最大值
    GLOBAL.CURID=0        //当前值
    // 自定义序列
    xxx.HISIDS=
    xxx.MINID=1
    ......

    使用示例:

    insert into table1(id,name) values(next value for MYCATSEQ_GLOBAL,'test');

    这里的 GLOBAL 和上面的配置对应

    缺点:当 MyCAT 重新发布后,配置文件中的 sequence 会恢复到初始值。
    优点:本地加载,读取速度较快。

    2、数据库方式

    原理:在数据库中建立一张表,存放 sequence 名称(name),sequence 当前值(current_value),步长(increment int 类型每次读取多少个 sequence,假设为 K)等信息。

    Sequence 获取步骤:

    • 当初次使用该 sequence 时,根据传入的 sequence 名称,从数据库这张表中读取 current_value,和 increment 到 MyCat 中,并将数据库中的 current_value 设置为原 current_value 值+increment 值;
    • MyCat 将读取到 current_value+increment 作为本次要使用的 sequence 值,下次使用时,自动加 1,当使用 increment 次后,执行步骤 1)相同的操作;
    • MyCat 负责维护这张表,用到哪些 sequence,只需要在这张表中插入一条记录即可。若某次读取的sequence 没有用完,系统就停掉了,则这次读取的 sequence 剩余值不会再使用。

    配置方式:
    在 server.xml 文件的 system 节点下做如下配置:

    <property name="sequnceHandlerType">1</property>

    创建 MYCAT_SEQUENCE 表和相关 function:

    #建表
    CREATE TABLE MYCAT_SEQUENCE (name VARCHAR(50) NOT NULL,current_value INT NOT 
    NULL,increment INT NOT NULL DEFAULT 100, PRIMARY KEY(name)) ENGINE=InnoDB;
    
    INSERT INTO MYCAT_SEQUENCE(name,current_value,increment) VALUES ('GLOBAL', 100000, 
    100); 
    
    #获取当前 ID
    DROP FUNCTION IF EXISTS mycat_seq_currval; 
    DELIMITER //
    CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS varchar(64)  
    DETERMINISTIC 
    BEGIN 
    DECLARE retval VARCHAR(64); 
    SET retval='-999999999,null'; 
    SELECT concat(CAST(current_value AS CHAR),',',CAST(increment AS CHAR)) INTO retval FROM 
    MYCAT_SEQUENCE WHERE name = seq_name; 
    RETURN retval;
    END;//
    
    #设置
    DROP FUNCTION IF EXISTS mycat_seq_setval; 
    DELIMITER//
    CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),value INTEGER) RETURNS varchar(64) 
    DETERMINISTIC 
    BEGIN 
    UPDATE MYCAT_SEQUENCE 
    SET current_value = value 
    WHERE name = seq_name; 
    RETURN mycat_seq_currval(seq_name); 
    END;//
    
    #获取下一个(新的ID)
    DROP FUNCTION IF EXISTS mycat_seq_nextval; 
    DELIMITER //
    CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS varchar(64)
    DETERMINISTIC 
    BEGIN 
    UPDATE MYCAT_SEQUENCE 
    SET current_value = current_value + increment WHERE name = seq_name; 
    RETURN mycat_seq_currval(seq_name); 
    END;//

    sequence_db_conf.properties 相关配置,指定 sequence 相关配置在哪个节点上:

    GLOBAL=dn1

    使用示例:

    insert into table1(id,name) values(next value for MYCATSEQ_GLOBAL,'test');

    这里的 GLOBAL 和上面的数据库字段名对应

    五、数据分片

    1、枚举分片

    通过在配置文件中配置可能的枚举 id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县固定的,这类业务使用本条规则。
    在 schema.xml 文件中配置:

    <table name="news_main" primaryKey="news_id" autoIncrement="true" dataNode="dn1,dn2" rule="news_rule" />

    在 rule.xml 文件中配置:

    <tableRule name="news_rule">
        <rule>
            <columns>news_area</columns> <!-- 将要分片的表字段 -->   
            <algorithm>func1</algorithm> <!-- 分片函数 --> 
        </rule>
    </tableRule>
    
    <function name="func1" class="org.opencloudb.route.function.PartitionByFileMap">
        <property name="mapFile">news_area_rule</property> <!-- 配置文件名称 -->
        <property name="type">1</property> <!-- 0表示Integer,非零表示String -->
        <property name="defaultNode">0</property> <!-- 默认节点 -->
    </function>

    新建 news_area_rule 文件并配置:

    beijing=0
    shangahi=1
    hanzhong=1

    2、范围分片

    此分片适用于,提前规划好分片字段某个范围属于哪个分片。
    在 schema.xml 文件中配置:

    <table name="news_main" primaryKey="news_id" autoIncrement="true" dataNode="dn1,dn2" rule="news_rule2" />

    在 rule.xml 文件中配置:

    <tableRule name="news_rule2">
        <rule>
            <columns>news_id</columns>    <!-- 将要分片的表字段 -->
            <algorithm>func2</algorithm>  <!-- 分片函数 -->
        </rule>
    </tableRule>
    
    <function name="func2" class="org.opencloudb.route.function.AutoPartitionByLong">
        <property name="mapFile">news_id_rule</property>  <!-- 配置文件名称 -->
        <property name="defaultNode">0</property>  <!-- 默认节点 -->
    </function>

    新建 news_id_rule 文件并配置:

    0-100000=0
    100001-200000=1

    3、按日期(天)分片

    在 schema.xml 文件中配置:

    <table name="news_main" primaryKey="news_id" autoIncrement="true" dataNode="dn1,dn2" rule="news_rule3" />

    在 rule.xml 文件中配置:

    <tableRule name="news_rule3">
        <rule>
            <columns>news_date</columns>  <!-- 将要分片的表字段 -->
            <algorithm>func3</algorithm>  <!-- 分片函数 -->
        </rule>
    </tableRule>
    
    <function name="func3" class="org.opencloudb.route.function.PartitionByDate">
        <property name="dateFormat">yyyy-MM-dd</property> <!-- 日期格式 -->
        <property name="sBeginDate">2018-01-01</property> <!-- 开始日期 -->
        <property name="sEndDate">2018-02-01</property> <!-- 结束日期 -->
        <property name="sPartionDay">10</property> <!-- 分区天数,即默认从开始日期算起,分隔 10 天一个分区 -->
    </function>

    4、取模分片

    此规则为对分片字段求摸运算。
    在 schema.xml 文件中配置:

    <table name="news_main" primaryKey="news_id" autoIncrement="true" dataNode="dn1,dn2" rule="news_rule4" />

    在 rule.xml 文件中配置:

    <tableRule name="news_rule4">
        <rule>
            <columns>news_id</columns>   <!-- 将要分片的表字段 -->
            <algorithm>func4</algorithm> <!-- 分片函数 -->
        </rule>
    </tableRule>
    
    <function name="func4" class="org.opencloudb.route.function.PartitionByMod">
        <property name="count">2</property> <!-- 节点数量 -->
    </function>

    5、取模范围分片

    此种规则是取模运算与范围约束的结合,主要为了后续数据迁移做准备,即可以自主决定取模后数据的节点分布。
    在 schema.xml 文件中配置:

    <table name="news_main" primaryKey="news_id" autoIncrement="true" dataNode="dn1,dn2" rule="news_rule5" />

    在 rule.xml 文件中配置:

    <tableRule name="news_rule5">
        <rule>
            <columns>news_id</columns>   <!-- 将要分片的表字段 -->
            <algorithm>func5</algorithm> <!-- 分片函数 -->
        </rule>
    </tableRule>
    
    <function name="func5" class="org.opencloudb.route.function.PartitionByPattern">
        <property name="patternValue">64</property> <!-- 求模基数 -->
        <property name="defaultNode">0</property> <!-- 默认节点 -->
        <property name="mapFile">news_modandrange_rule</property> <!-- 配置文件名称 -->
    </function>

    新建 news_modandrange_rule 文件并配置:

    0-32=0
    33-64=1

    6、关联表分片

    保证主表和字表进入同一节点。
    在 schema.xml 文件中配置:

    <table name="order_main" primaryKey="order_id" autoIncrement="true" rule="order_mod" dataNode="dn1,dn2" >
        <childTable name="order_detail" primaryKey="order_detail_id"  
        joinKey="order_id" parentKey="order_id" /> 
    </table>

    joinKey:插入子表时候会使用这个列的值查找父表存储在哪个节点
    parentKey:根据JoinKey进行查询,从而确定子表存储位置

  • 相关阅读:
    【SPOJ】6779 Can you answer these queries VII
    【SPOJ】1557 Can you answer these queries II
    【SPOJ】2916 Can you answer these queries V
    【CodeForces】86D Powerful array
    【SPOJ】1043 Can you answer these queries I
    【HDU】3727 Jewel
    【HDU】3915 Game
    【SPOJ】1043 Can you answer these queries III
    【SPOJ】2713 Can you answer these queries IV
    成为一名更好的软件工程师的简单方法
  • 原文地址:https://www.cnblogs.com/tangxuliang/p/9078951.html
Copyright © 2020-2023  润新知