【Mycat】Mycat核心開發者帶你輕鬆掌握Mycat路由轉發!!

冰河團隊發表於2020-11-14

寫在前面

熟悉Mycat的小夥伴都知道,Mycat一個很重要的功能就是路由轉發,那麼,這篇文章就帶著大家一起來看看Mycat是如何進行路由轉發的,好了,不多說了,我們直接進入主題。

環境準備

軟體版本

作業系統:CentOS-6.8

JDK版本:jdk1.8

Mycat版本:Mycat-server-1.6

MySQL:5.7

注意:這裡,我將Mycat和MySQL安裝在同一臺虛擬機器(IP:192.168.209.140 主機名為:binghe140),大家也可以將Mycat和MySQL安裝到不同的主機上,測試效果是一樣的。

建立物理庫

mysql -uroot -proot -h192.168.209.140 -P3306

drop database if exists db1;
create database db1;
drop database if exists db2;
create database db2;
drop database if exists db3;
create database db3;

配置Mycat

schema.xml配置

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/" >
 
	<schema name="binghe" checkSQLschema="false" sqlMaxLimit="100">
		<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"></table>
	</schema>
	<!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743" 
		/> -->
	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost1" database="db2" />
	<dataNode name="dn3" dataHost="localhost1" database="db3" />
	<!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
	 <dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" /> 
	<dataNode	name="jdbc_dn2" dataHost="jdbchost" database="db2" /> 
	<dataNode name="jdbc_dn3" 	dataHost="jdbchost" database="db3" /> -->
	<dataHost name="localhost1" 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="127.0.0.1:3306" user="root" password="root"></writeHost>
		
		<writeHost host="hostM2" url="127.0.0.1:3306" user="root" password="root"></writeHost>
		<!--<writeHost host="hostS1" url="localhost:3316" user="root"-->
			<!--password="123456" />-->
		<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
	</dataHost>
</mycat:schema>

server.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
	<system>
	<property name="defaultSqlParser">druidparser</property>
	</system>
	<user name="binghe">
		<property name="password">binghe.123</property>
		<property name="schemas">binghe</property>
	</user>
	<user name="test">
		<property name="password">test</property>
		<property name="schemas">binghe</property>
		<property name="readOnly">true</property>
	</user>
</mycat:server>

rule.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://org.opencloudb/">
	<tableRule name="rule1">
		<rule>
			<columns>id</columns>
			<algorithm>func1</algorithm>
		</rule>
	</tableRule>
 
	<tableRule name="rule2">
		<rule>
			<columns>user_id</columns>
			<algorithm>func1</algorithm>
		</rule>
	</tableRule>
 
	<tableRule name="sharding-by-intfile">
		<rule>
			<columns>sharding_id</columns>
			<algorithm>hash-int</algorithm>
		</rule>
	</tableRule>
	<tableRule name="auto-sharding-long">
		<rule>
			<columns>id</columns>
			<algorithm>rang-long</algorithm>
		</rule>
	</tableRule>
	<tableRule name="mod-long">
		<rule>
			<columns>id</columns>
			<algorithm>mod-long</algorithm>
		</rule>
	</tableRule>
	<tableRule name="sharding-by-murmur">
		<rule>
			<columns>id</columns>
			<algorithm>murmur</algorithm>
		</rule>
	</tableRule>
	<tableRule name="sharding-by-month">
		<rule>
			<columns>create_date</columns>
			<algorithm>partbymonth</algorithm>
		</rule>
	</tableRule>
	<tableRule name="latest-month-calldate">
		<rule>
			<columns>calldate</columns>
			<algorithm>latestMonth</algorithm>
		</rule>
	</tableRule>
	
	<tableRule name="auto-sharding-rang-mod">
		<rule>
			<columns>id</columns>
			<algorithm>rang-mod</algorithm>
		</rule>
	</tableRule>
	
	<tableRule name="jch">
		<rule>
			<columns>id</columns>
			<algorithm>jump-consistent-hash</algorithm>
		</rule>
	</tableRule>
 
	<function name="murmur"
		class="org.opencloudb.route.function.PartitionByMurmurHash">
		<property name="seed">0</property>
		<property name="count">2</property>
		<property name="virtualBucketTimes">160</property>
	</function>
	<function name="hash-int"
		class="org.opencloudb.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-int.txt</property>
	</function>
	<function name="rang-long"
		class="org.opencloudb.route.function.AutoPartitionByLong">
		<property name="mapFile">autopartition-long.txt</property>
	</function>
	<function name="mod-long" class="org.opencloudb.route.function.PartitionByMod">
		<!-- how many data nodes -->
		<property name="count">3</property>
	</function>
 
	<function name="func1" class="org.opencloudb.route.function.PartitionByLong">
		<property name="partitionCount">8</property>
		<property name="partitionLength">128</property>
	</function>
	<function name="latestMonth"
		class="org.opencloudb.route.function.LatestMonthPartion">
		<property name="splitOneDay">24</property>
	</function>
	<function name="partbymonth"
		class="org.opencloudb.route.function.PartitionByMonth">
		<property name="dateFormat">yyyy-MM-dd</property>
		<property name="sBeginDate">2020-01-01</property>
	</function>
	
	<function name="rang-mod" class="org.opencloudb.route.function.PartitionByRangeMod">
        	<property name="mapFile">partition-range-mod.txt</property>
	</function>
	
	<function name="jump-consistent-hash" class="org.opencloudb.route.function.PartitionByJumpConsistentHash">
		<property name="totalBuckets">3</property>
	</function>
</mycat:rule>

登入Mycat

登入Mycat

命令列輸入以下命令登入Mycat

D:\>mysql -ubinghe -pbinghe.123 -h192.168.209.140 -P8066
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.8-mycat-1.6.1-RELEASE-20170807215126 MyCat Server (OpenCloundDB)
 
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
 
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
mysql>

建立表測試

輸入以下命令檢視建立表的路由

create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int); 

結果如下:

mysql> explain create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int);
+-----------+-----------------------------------------------------------------------------------------------------------------------+
| DATA_NODE | SQL                                                                                                                   |
+-----------+-----------------------------------------------------------------------------------------------------------------------+
| dn1       | create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int) |
| dn2       | create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int) |
| dn3       | create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int) |
+-----------+-----------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)
 
mysql>

說明建立表的SQL語句被Mycat路由到dn1,dn2,dn3三個節點上,也就是說在3個節點上都執行了建立表的SQL。

我們輸入建表語句:

mysql> create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int);
Query OK, 0 rows affected (0.18 sec)

此時,將會在dn1,dn2,dn3三個節點上建立travelrecord表。

錄入資料測試

錄入到dn1節點

我們在命令列輸入如下SQL語句

explain insert into travelrecord (id,user_id,traveldate,fee,days) values(100001,'binghe','2020-11-10',510.5,3);

結果如下:

mysql> explain insert into travelrecord (id,user_id,traveldate,fee,days) values(100001,'binghe','2020-11-10',510.5,3);
+-----------+-------------------------------------------------------------------------------------------------------------+
| DATA_NODE | SQL                                                                                                         |
+-----------+-------------------------------------------------------------------------------------------------------------+
| dn1       | insert into travelrecord (id,user_id,traveldate,fee,days) values(100001,'binghe','2020-11-10',510.5,3) |
+-----------+-------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

說明Mycat將SQL路由到了dn1節點。

我們執行插入語句:

mysql> insert into travelrecord (id,user_id,traveldate,fee,days) values(100001,'binghe','2020-11-10',510.5,3);
Query OK, 1 row affected, 1 warning (0.01 sec)
 
mysql>

錄入到dn2節點

我們在命令列輸入如下語句:

explain insert into travelrecord (id,user_id,traveldate,fee,days) values(8000004,'binghe','2020-11-10',510.5,3);

結果如下:

mysql> explain insert into travelrecord (id,user_id,traveldate,fee,days) values(8000004,'binghe','2020-11-10',510.5,3);
+-----------+--------------------------------------------------------------------------------------------------------------+
| DATA_NODE | SQL                                                                                                          |
+-----------+--------------------------------------------------------------------------------------------------------------+
| dn2       | insert into travelrecord (id,user_id,traveldate,fee,days) values(8000004,'binghe','2020-11-10',510.5,3) |
+-----------+--------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

說明Mycat將SQL路由到了dn2節點,我們執行插入語句:

mysql> insert into travelrecord (id,user_id,traveldate,fee,days) values(8000004,'binghe','2020-11-10',510.5,3);
Query OK, 1 row affected, 1 warning (0.06 sec)

路由到dn3節點

我們在命令列輸入如下語句

explain insert into travelrecord (id,user_id,traveldate,fee,days) values(10000004,'binghe','2020-11-10',510.5,3);

結果為:

mysql> explain insert into travelrecord (id,user_id,traveldate,fee,days) values(10000004,'binghe','2020-11-10',510.5,3);
+-----------+---------------------------------------------------------------------------------------------------------------+
| DATA_NODE | SQL                                                                                                           |
+-----------+---------------------------------------------------------------------------------------------------------------+
| dn3       | insert into travelrecord (id,user_id,traveldate,fee,days) values(10000004,'binghe','2020-11-10',510.5,3) |
+-----------+---------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

說明Mycat將SQL路由到了dn3節點,我們同樣執行插入語句的操作

mysql>  insert into travelrecord (id,user_id,traveldate,fee,days) values(10000004,'binghe','2020-11-10',510.5,3);
Query OK, 1 row affected, 1 warning (0.01 sec)

查詢測試

查詢所有資料

在命令列執行如下語句:

explain select * from travelrecord;

結果為:

mysql> explain select * from travelrecord;
+-----------+--------------------------------------+
| DATA_NODE | SQL                                  |
+-----------+--------------------------------------+
| dn1       | SELECT * FROM travelrecord LIMIT 100 |
| dn2       | SELECT * FROM travelrecord LIMIT 100 |
| dn3       | SELECT * FROM travelrecord LIMIT 100 |
+-----------+--------------------------------------+
3 rows in set (0.01 sec)

說明查詢所有的資料,Mycat是將SQL語句路由到了所有的資料分片,即dn1,dn2,dn3節點上。

根據id查詢指定資料

我們分別在命令列中執行如下SQL:

explain select * from travelrecord where id = 1000004;
explain select * from travelrecord where id = 8000004;
explain select * from travelrecord where id = 10000004;

得到的結果依次如下:

mysql> explain select * from travelrecord where id = 1000004;
+-----------+---------------------------------------------------------+
| DATA_NODE | SQL                                                     |
+-----------+---------------------------------------------------------+
| dn1       | SELECT * FROM travelrecord WHERE id = 1000004 LIMIT 100 |
+-----------+---------------------------------------------------------+
1 row in set (0.06 sec)
 
mysql> explain select * from travelrecord where id = 8000004;
+-----------+---------------------------------------------------------+
| DATA_NODE | SQL                                                     |
+-----------+---------------------------------------------------------+
| dn2       | SELECT * FROM travelrecord WHERE id = 8000004 LIMIT 100 |
+-----------+---------------------------------------------------------+
1 row in set (0.00 sec)
 
mysql> explain select * from travelrecord where id = 10000004;
+-----------+----------------------------------------------------------+
| DATA_NODE | SQL                                                      |
+-----------+----------------------------------------------------------+
| dn3       | SELECT * FROM travelrecord WHERE id = 10000004 LIMIT 100 |
+-----------+----------------------------------------------------------+
1 row in set (0.00 sec)

說明:按照分片欄位查詢,Mycat只會將SQL路由到指定的資料分片。

刪表測試

在命令列輸入如下SQL:

explain drop table travelrecord;

結果如下

mysql> explain drop table travelrecord;
+-----------+-------------------------+
| DATA_NODE | SQL                     |
+-----------+-------------------------+
| dn1       | drop table travelrecord |
| dn2       | drop table travelrecord |
| dn3       | drop table travelrecord |
+-----------+-------------------------+
3 rows in set (0.00 sec)

有結果可知,刪表操作和建立表操作一樣,Mycat在本例項中都會將SQL路由到所有的資料分片。

注意:本文的Mycat路由結果針對本文的配置例項,其他配置下,Mycat的路由結果可能會有不同。

好了,我們今天就到這兒吧,我是冰河,我們下期見~~

重磅福利

微信搜一搜【冰河技術】微信公眾號,關注這個有深度的程式設計師,每天閱讀超硬核技術乾貨,公眾號內回覆【PDF】有我準備的一線大廠面試資料和我原創的超硬核PDF技術文件,以及我為大家精心準備的多套簡歷模板(不斷更新中),希望大家都能找到心儀的工作,學習是一條時而鬱鬱寡歡,時而開懷大笑的路,加油。如果你通過努力成功進入到了心儀的公司,一定不要懈怠放鬆,職場成長和新技術學習一樣,不進則退。如果有幸我們江湖再見!

另外,我開源的各個PDF,後續我都會持續更新和維護,感謝大家長期以來對冰河的支援!!

相關文章