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进行查询,从而确定子表存储位置

原文地址:https://www.cnblogs.com/tangxuliang/p/9078951.html