1、业务场景:用户购物下单。
要求:把订单分片,商家要查询购买在订单,用户要查询自己的订单。
表设计:用户,商家订单,订单明细,买方订单
分片规则:
“用户表”---user_id 取模,“商家订单”----seller_user_id 取模
“订单明细”----“商家订单”ER 分片,“买家订单”----buyer_user_id 取模
2、表
CREATE TABLE tb_user (
login_name VARCHAR (32) comment '登录名',
user_id BIGINT comment '用户标识',
TYPE INT comment '用户类型 1 商家,2买家',
passwd VARCHAR (128) comment '密码',
primary key (user_id)
) ;
alter table tb_user comment '用户表';
CREATE TABLE tb_seller_order (
seller_user_id BIGINT comment '商家标识',
buyer_user_id BIGINT comment '用户标识',
order_id BIGINT comment '订单标识',
price BIGINT comment '价格',
STATUS INT comment '状态',
primary key (order_id)
);
alter table tb_seller_order comment '商家订单表';
CREATE TABLE tb_order_detail(
seller_user_id BIGINT comment '商家标识',
order_detail_id BIGINT comment '订单明细标识',
order_id BIGINT comment '订单标识',
goods_id BIGINT comment '标识',
goods_name VARCHAR(32) comment '商品名称',
cnt INT comment '数量',
unit_price INT comment '单价',
primary key (order_detail_id)
);
alter table tb_order_detail comment '订单明细';
CREATE TABLE tb_buyer_order (
buyer_user_id BIGINT comment '用户标识',
seller_user_id BIGINT comment '商家标识',
order_id BIGINT comment '订单标识',
price BIGINT comment '价格',
STATUS INT comment '状态',
primary key (order_id)
);
alter table tb_buyer_order comment '买家订单';
3、服务器分配:
mysql:
主 192.168.109.128 备192.168.109.130
主 192.168.109.131
主 192.168.109.132
mycat:
192.168.109.129
4、表主键生成策略使用mycat全局序列生成(mycat 全局序列号:http://blog.csdn.net/convict_eva/article/details/51917499)
添加mycat全局序列号:
USER_ID_SQUE=dn_master
ORDER_ID_SQUE=dn_master
DETAIL_ID_SQUE=dn_master
在dn_master结点执行:
insert into MYCAT_SEQUENCE(NAME,current_value,increment)
values('USER_ID_SQUE',1,100),('ORDER_ID_SQUE',1,100),('DETAIL_ID_SQUE',1,100);
重启mycat测试:
SELECT NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE;
SELECT NEXT VALUE FOR MYCATSEQ_ORDER_ID_SQUE;
SELECT NEXT VALUE FOR MYCATSEQ_DETAIL_ID_SQUE;
5、配置分片规则
在mycat conf 目录下的rule.xml 是分片规则的配置文件。
5.1 配置function 标签,找到function 标签name="mod-long" 的function 配置,修改总结点数为3(和使用的mysql 结点数一致)。
<function name="mod-long" class="org.opencloudb.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">3</property>
</function>
5.2 配置表分片(name 要全局唯一),rule.xml 配置添加如下配置
<!-- user分片规则 -->
<tableRule name="tb_user_mod-long">
<rule>
<!-- 分片使用的字段 -->
<columns>user_id</columns>
<!-- 分片使用的方法,对应function 名称 -->
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<!-- 卖家订单分片规则 -->
<tableRule name="seller_order_mod-long">
<rule>
<columns>seller_user_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<!-- 买家订单分片规则 -->
<tableRule name="buyer_order_mod-long">
<rule>
<columns>buyer_user_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
6 schema.xml 配置
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/" >
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- auto sharding by id (long) -->
<table name="tb_a" dataNode="dn_master"/>
<!-- 全局表,使用type属性指定,多个结点要都执行建表语句。所有结点的数据一致。 -->
<table name="tb_global_test" dataNode="dn_master,dn_master2,dn_master3" type="global" />
<!-- 配置表所在的分片结点,指定主键和分片规则。指定主键是为了使用主键查询时mycat什么缓存主键对应的dn,提高查询效率。-->
<table name="tb_user" rule="tb_user_mod-long" primaryKey="user_id" dataNode="dn_master,dn_master2,dn_master3" />
<table name="tb_seller_order" rule="seller_order_mod-long" primaryKey="order_id" dataNode="dn_master,dn_master2,dn_master3" >
<!-- 配置ER 分片,子表的存储依赖于主表,并且物理上紧邻存放。 -->
<childTable name="tb_order_detail" primaryKey="order_detail_id" joinKey="order_id" parentKey="order_id" />
</table>
<table name="tb_buyer_order" rule="buyer_order_mod-long" primaryKey="order_id" dataNode="dn_master,dn_master2,dn_master3" />
</schema>
<!-- 配置数据结点 -->
<dataNode name="dn_master" dataHost="master" database="test_db" />
<dataNode name="dn_master2" dataHost="master2" database="test_db" />
<dataNode name="dn_master3" dataHost="master3" database="test_db" />
<!-- ddata node host 配置 -->
<dataHost name="master" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!-- 主从心跳语句配置 -->
<heartbeat>show slave status</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="192.168.109.128:3306" user="root" password="Abc123!@#">
<!-- 从库 -->
<readHost host="hostS2" url="192.168.109.130:3306" user="root" password="Abc123!@#" />
</writeHost>
</dataHost>
<dataHost name="master2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="192.168.109.131:3306" user="root" password="Abc123!@#"></writeHost>
</dataHost>
<dataHost name="master3" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM3" url="192.168.109.132:3306" user="root" password="Abc123!@#"></writeHost>
</dataHost>
</mycat:schema>
重启mycat,使用SQLyog连接到mycat,并执行建表语句。
7、测试
7.1、插入user
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-1',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-2',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-3',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-4',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-5',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-6',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-7',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-8',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-9',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-10',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-11',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-12',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-13',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-14',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-15',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-16',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-17',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-18',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-19',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-20',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-21',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-22',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('name-23',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,1,'passwd-A');
109.128数据为:
mysql> select * from tb_user;
+------------+---------+------+----------------------+
| login_name | user_id | TYPE | passwd |
+------------+---------+------+----------------------+
| name-1 | 225 | 1 | passwd-A |
| name-4 | 228 | 1 | passwd-A |
| name-7 | 231 | 1 | passwd-A |
| name-10 | 234 | 1 | passwd-A |
| name-13 | 237 | 1 | passwd-A |
| name-16 | 240 | 1 | passwd-A |
| name-19 | 243 | 1 | passwd-A |
| name-22 | 246 | 1 | passwd-A |
+------------+---------+------+----------+
8 rows in set (0.00 sec)
109.131数据为:
mysql> select * from tb_user;
+------------+---------+------+----------+
| login_name | user_id | TYPE | passwd |
+------------+---------+------+----------+
| name-2 | 226 | 1 | passwd-A |
| name-5 | 229 | 1 | passwd-A |
| name-8 | 232 | 1 | passwd-A |
| name-11 | 235 | 1 | passwd-A |
| name-14 | 238 | 1 | passwd-A |
| name-17 | 241 | 1 | passwd-A |
| name-20 | 244 | 1 | passwd-A |
| name-23 | 247 | 1 | passwd-A |
+------------+---------+------+----------+
8 rows in set (0.00 sec)
109.132 数据为:
mysql> select * from tb_user;
+------------+---------+------+----------+
| login_name | user_id | TYPE | passwd |
+------------+---------+------+----------+
| name-3 | 227 | 1 | passwd-A |
| name-6 | 230 | 1 | passwd-A |
| name-9 | 233 | 1 | passwd-A |
| name-12 | 236 | 1 | passwd-A |
| name-15 | 239 | 1 | passwd-A |
| name-18 | 242 | 1 | passwd-A |
| name-21 | 245 | 1 | passwd-A |
+------------+---------+------+----------+
7 rows in set (0.00 sec)
通过数据的id取模,取模为0的在109.128 机器,取模为1的在109.131机器,取模为2的在109.132机器。
7.2 下单测试
上面创建的是商家用户,下面创建买家用户。
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('buyer-1',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,2,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('buyer-2',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,2,'passwd-A');
INSERT INTO `tb_user`(`login_name`,`user_id`,`TYPE`,`passwd`)
VALUES ('buyer-3',NEXT VALUE FOR MYCATSEQ_USER_ID_SQUE,2,'passwd-A');
所有的用户如下:
mysql> select * from tb_user order by login_name;
+------------+---------+------+----------+
| login_name | user_id | TYPE | passwd |
+------------+---------+------+----------+
| buyer-1 | 248 | 2 | passwd-A |
| buyer-2 | 249 | 2 | passwd-A |
| buyer-3 | 250 | 2 | passwd-A |
| name-1 | 225 | 1 | passwd-A |
| name-10 | 234 | 1 | passwd-A |
| name-11 | 235 | 1 | passwd-A |
| name-12 | 236 | 1 | passwd-A |
| name-13 | 237 | 1 | passwd-A |
| name-14 | 238 | 1 | passwd-A |
| name-15 | 239 | 1 | passwd-A |
| name-16 | 240 | 1 | passwd-A |
| name-17 | 241 | 1 | passwd-A |
| name-18 | 242 | 1 | passwd-A |
| name-19 | 243 | 1 | passwd-A |
| name-2 | 226 | 1 | passwd-A |
| name-20 | 244 | 1 | passwd-A |
| name-21 | 245 | 1 | passwd-A |
| name-22 | 246 | 1 | passwd-A |
| name-23 | 247 | 1 | passwd-A |
| name-3 | 227 | 1 | passwd-A |
| name-4 | 228 | 1 | passwd-A |
| name-5 | 229 | 1 | passwd-A |
| name-6 | 230 | 1 | passwd-A |
| name-7 | 231 | 1 | passwd-A |
| name-8 | 232 | 1 | passwd-A |
| name-9 | 233 | 1 | passwd-A |
+------------+---------+------+----------+
下单:
SELECT NEXT VALUE FOR MYCATSEQ_ORDER_ID_SQUE;
INSERT INTO `tb_seller_order`(`seller_user_id`,`buyer_user_id`,`order_id`,`price`)
VALUES (225,248,201,1222);
INSERT INTO `tb_order_detail`
(`seller_user_id`,`order_detail_id`,`order_id`,`goods_id`,`goods_name`,`cnt`,`unit_price`)
VALUES (225, NEXT VALUE FOR MYCATSEQ_DETAIL_ID_SQUE,201,11,'goods_name',1,1220);
INSERT INTO `tb_order_detail`
(`seller_user_id`,`order_detail_id`,`order_id`,`goods_id`,`goods_name`,`cnt`,`unit_price`)
VALUES (225, NEXT VALUE FOR MYCATSEQ_DETAIL_ID_SQUE,201,11,'goods_name2',1,2);
说明:商家225 在109.128 上,tb_seller_order表根据seller_user_id 取模分片,所有此订单数据存储在与user id为225 的商家同一分片
tb_order_detail 表使用的是与tb_seller_order ER 分片,使用order_id 关联,所以tb_order_detail 存储的分片与相同的order_id 的tb_seller_order 的数据在同一分片。
再测试一条数据:user_id为238 的用户存储在109.131 分片上。
INSERT INTO `tb_seller_order`(`seller_user_id`,`buyer_user_id`,`order_id`,`price`)
VALUES (238,248,203,1222);
INSERT INTO `tb_order_detail`
(`seller_user_id`,`order_detail_id`,`order_id`,`goods_id`,`goods_name`,`cnt`,`unit_price`)
VALUES (238, NEXT VALUE FOR MYCATSEQ_DETAIL_ID_SQUE,203,11,'goods_name',1,1220);
INSERT INTO `tb_order_detail`
(`seller_user_id`,`order_detail_id`,`order_id`,`goods_id`,`goods_name`,`cnt`,`unit_price`)
VALUES (238, NEXT VALUE FOR MYCATSEQ_DETAIL_ID_SQUE,203,11,'goods_name2',1,2);
测试结果:
109.128数据为:
mysql> select * from tb_user;
+------------+---------+------+----------+
| login_name | user_id | TYPE | passwd |
+------------+---------+------+----------+
| name-1 | 225 | 1 | passwd-A |
| name-4 | 228 | 1 | passwd-A |
| name-7 | 231 | 1 | passwd-A |
| name-10 | 234 | 1 | passwd-A |
| name-13 | 237 | 1 | passwd-A |
| name-16 | 240 | 1 | passwd-A |
| name-19 | 243 | 1 | passwd-A |
| name-22 | 246 | 1 | passwd-A |
| buyer-2 | 249 | 2 | passwd-A |
+------------+---------+------+----------+
9 rows in set (0.00 sec)
mysql> select * from tb_seller_order;
+----------------+---------------+----------+-------+--------+
| seller_user_id | buyer_user_id | order_id | price | STATUS |
+----------------+---------------+----------+-------+--------+
| 225 | 248 | 201 | 1222 | NULL |
+----------------+---------------+----------+-------+--------+
1 row in set (0.00 sec)
mysql> select * from tb_order_detail;
+----------------+-----------------+----------+----------+-------------+------+------------+
| seller_user_id | order_detail_id | order_id | goods_id | goods_name | cnt | unit_price |
+----------------+-----------------+----------+----------+-------------+------+------------+
| 225 | 201 | 201 | 11 | goods_name | 1 | 1220 |
| 225 | 202 | 201 | 11 | goods_name2 | 1 | 2 |
+----------------+-----------------+----------+----------+-------------+------+------------+
2 rows in set (0.00 sec)
109.131数据为:
mysql> select * from tb_user;
+------------+---------+------+----------+
| login_name | user_id | TYPE | passwd |
+------------+---------+------+----------+
| name-2 | 226 | 1 | passwd-A |
| name-5 | 229 | 1 | passwd-A |
| name-8 | 232 | 1 | passwd-A |
| name-11 | 235 | 1 | passwd-A |
| name-14 | 238 | 1 | passwd-A |
| name-17 | 241 | 1 | passwd-A |
| name-20 | 244 | 1 | passwd-A |
| name-23 | 247 | 1 | passwd-A |
| buyer-3 | 250 | 2 | passwd-A |
+------------+---------+------+----------+
9 rows in set (0.00 sec)
mysql> select * from tb_seller_order;
+----------------+---------------+----------+-------+--------+
| seller_user_id | buyer_user_id | order_id | price | STATUS |
+----------------+---------------+----------+-------+--------+
| 238 | 248 | 203 | 1222 | NULL |
+----------------+---------------+----------+-------+--------+
1 row in set (0.00 sec)
mysql> select * from tb_order_detail;
+----------------+-----------------+----------+----------+-------------+------+------------+
| seller_user_id | order_detail_id | order_id | goods_id | goods_name | cnt | unit_price |
+----------------+-----------------+----------+----------+-------------+------+------------+
| 238 | 203 | 203 | 11 | goods_name | 1 | 1220 |
| 238 | 204 | 203 | 11 | goods_name2 | 1 | 2 |
+----------------+-----------------+----------+----------+-------------+------+------------+
2 rows in set (0.00 sec)
本想写存储过程测试,发现存储过程只能写的某一个结点,然后通过mycat指定结点调用,这样就不能使用mycat的全局序列,所以就手动写了sql。
转载:https://blog.csdn.net/convict_eva/article/details/52022696