一、准备工作
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进行查询,从而确定子表存储位置