您好,登錄后才能下訂單哦!
mycat實驗之主從配置讀寫分離和分表
1.實驗環境:
vmware虛機3個 (虛機太少了,電腦有點吃力,3個虛機只能達到基本的測試)
系統centos7 (實驗是關閉防火墻和selinux做的)
mysql版本5.7
mycat版本1.6
虛機名字和ip:
mysql1 192.168.211.138
mysql2 192.168.211.139
mysql3 192.168.211.142
mycat安裝在mysql1(192.168.211.138)
這臺主機須能夠解析mysql2,mysql3的地址。
可通過/etc/hosts 手動添加解析
2.實驗目的
實現mycat讀寫分離和分表的功能。
3.實驗思路
在mycat創建一個邏輯庫:hello。
創建四個表格:
t1 這個表格用來分片,用枚舉的規則分片。
t2 這個表格做全局表。
t3 這個表格做普通表,定義它放到其中一個datanode,放到mysql1
t4 這個表格做普通表,定義它放到其中一個datanode,放到mysql3
虛機的分配:
mysql1 和mysql2做主從配置,其中mysql1為主,mysql2為從,其中mysql1用來寫,mysql2用來讀。
mysql3 就是個單獨的datanode
實際我們只有兩個datanode,mysql1,mysql3。
4.實驗步驟
分別在虛機安裝mysql5.7,步驟略。
設置mysql用戶,步驟略。請注意,必須設置一個用戶允許內網地址連接或者干脆是允許任何地方連接。比如設置'root'@'%'。
安裝mycat。步驟略。
配置mysql1和mysql2主從,步驟略。
以上都是些常用配置,懶得特意記錄了。
以上的環境都配置好了,就可以開始我們實驗核心步驟mycat的配置了
現在開始整個過程的配置。
1.在mysql1(192.168.211.138)里創建一個db1.
mysql> create database db1; Query OK, 1 row affected (0.01 sec)
檢查mysql2(192.168.211.139)里是不是同步了?
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | logs | | mysql | | performance_schema | | sys | | wordpress | +--------------------+ 7 rows in set (0.00 sec)
同步了。
2.在mysql3(192.168.211.142)里創建db2。
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db2 | | logs | | mysql | | performance_schema | | sys | | wordpress | +--------------------+ 7 rows in set (0.01 sec)
3.在mysql1里配置mycat,我的mycat安裝在mysql1。
我的配置文件路徑:
[root@mysql1 conf]# pwd /usr/local/mycat/conf
主要配置文件有:
[root@mysql1 conf]# ls autopartition-long.txt log4j2.xml schema.xml.bk server.xml.bk auto-sharding-long.txt migrateTables.properties schema.xml.bk2 sharding-by-enum.txt auto-sharding-rang-mod.txt myid.properties sequence_conf.properties wrapper.conf cacheservice.properties partition-hash-int.txt sequence_db_conf.properties zkconf dnindex.properties partition-range-mod.txt sequence_distributed_conf.properties zkdownload ehcache.xml rule.xml sequence_time_conf.properties index_to_charset.properties schema.xml server.xml [root@mysql1 conf]#
需要用到的是:schema.xml ##這個文件配置分表讀寫分離策略
rule.xml ##這是分表規則的定義
server.xml ##登錄mycat的賬戶密碼和防火墻的設置
4.首先配置:schema.xml
備份下原配置文件:
[root@mysql1 conf]# cp schema.xml schema.xml.bk3
清空配置文件:
[root@mysql1 conf]# echo " " >schema.xml
重新配置schema.xml,如下是我的配置文件整個內容:
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="hello" checkSQLschema="false" sqlMaxLimit="100"> <!-- auto sharding by id (long) --> <table name="t1" dataNode="dn1,dn2" rule="sharding-by-intfile" /> <!-- global table is auto cloned to all defined data nodes ,so can join with any table whose sharding node is in the same data node --> <table name="t2" primaryKey="ID" type="global" dataNode="dn1,dn2" /> <table name="t3" dataNode="dn1" /> <table name="t4" dataNode="dn2" /> </schema> <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743" /> --> <dataNode name="dn1" dataHost="mysql1" database="db1" /> <dataNode name="dn2" dataHost="mysql3" database="db2" /> <dataHost name="mysql1" 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.211.138:3306" user="root" password="Alex2010@"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.211.139:3306" user="root" password="Alex2010@"/> </writeHost> </dataHost> <dataHost name="mysql3" 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="192.168.211.142:3306" user="root" password="Alex2010@"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.211.142:3306" user="root" password="Alex2010@"/> </writeHost> </dataHost> </mycat:schema>
這些字段的解釋,可以查看我前面分片規則里面的解析。
說明下datahost balance字段的意義
balance屬性
負載均衡類型,目前的取值有3種:
1. balance="0", 不開啟讀寫分離機制,所有讀操作都發送到當前可用的writeHost上。
2. balance="1",全部的readHost與stand by writeHost參與select語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1,M2->S2,并且M1與
M2互為主備),正常情況下,M2,S1,S2都參與select語句的負載均衡。
3. balance="2",所有讀操作都隨機的在writeHost、readhost上分發。
4. balance="3",所有讀請求隨機的分發到wiriterHost對應的readhost執行,writerHost不負擔讀壓
writeType屬性
負載均衡類型,目前的取值有3種:
1. writeType="0", 所有寫操作發送到配置的第一個writeHost,第一個掛了切到還生存的第二個writeHost,重新啟動后已切換后的為準,
切換記錄在配置文件中:dnindex.properties .
2. writeType="1",所有寫操作都隨機的發送到配置的writeHost,1.5以后廢棄不推薦。
需要說明的是:
<dataHost name="mysql1" 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.211.138:3306" user="root" password="Alex2010@"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.211.139:3306" user="root" password="Alex2010@"/> </writeHost> </dataHost>
讀寫分離這里有兩種寫法:
除了上面的還可以寫下面這樣:
<dataHost name="mysql1" 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.211.138:3306" user="root" password="Alex2010@"> </writeHost> <writeHost host="hostM1" url="192.168.211.139:3306" user="root" password="Alex2010@"> </writeHost> </dataHost>
區別是上面的那種寫法,如果主服務器掛了,從服務器不能讀了。
下面的這種寫法,主服務器掛了,從服務器依然可以正常讀取。
這里說一下,后面會做測試。
5.看看rule.xml里的配置
看分表t1的設置:
<table name="t1" dataNode="dn1,dn2" rule="sharding-by-intfile" />
分表規則是 sharding-by-intfile
看看這個的規則設置
<tableRule name="sharding-by-intfile"> <rule> <columns>city</columns> <algorithm>hash-int</algorithm> </rule> </tableRule>
為什么columns是city呢?
這個city是我設定的,計劃創建表格t1(id,name,bu,city)有這四個列。我準備用city來做分片的列。
繼續往下看
</function> <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> <property name="type">1</property> <property name="defaultNode">0</property> </function>
這是用的hash-int函數的設置了。其中mpfile是指要讀取的配置文件。這是什么意思呢?
看看partition-hash-int.txt的內容
[root@mysql1 conf]# cat partition-hash-int.txt #10000=0 #10010=1 bj=0 gz=0 sz=1 [root@mysql1 conf]#
我計劃的表格t1 city列有三個值,bj gz sz ,這個設置的意思是:bj gz 的數據存儲到datanode1也就是mysql1,sz的數據存儲
到datanode2也就是mysql3。
<property name="type">1</property> <property name="defaultNode">0</property>
這兩條參數也必須要有,type默認的值是0,而0的格式是interger,注意我們分片的列是city是字符。
6.配置server.xml,參考下官方教程,很簡單。
7.到這里可以來啟動mycat,登錄進去創建表格,插入數據測試,是不是能夠達到我們的預期目標?
[root@mysql1 conf]# mysql -uroot -p123456 -P8066 -h 127.0.0.1 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB) Copyright (c) 2000, 2017, 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>
登錄進來了
mysql> show databases; +----------+ | DATABASE | +----------+ | hello | +----------+ 1 row in set (0.02 sec) mysql>
我們設置的邏輯庫hello
mysql> use hello; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-----------------+ | Tables in hello | +-----------------+ | t1 | | t2 | | t3 | | t4 | +-----------------+ 4 rows in set (0.01 sec) mysql> mysql> desc t1; ERROR 1146 (42S02): Table 'db1.t1' doesn't exist mysql>
注意這里有個問題,這些t1-t4的表格,看似是有,其實是假的。感覺像是BUG。表格需要我們手動創建。
創建表格:
mysql> create table t1 (id int not null,name varchar(15) not null,bu varchar(10) not null,city varchar(5) not null); Query OK, 0 rows affected (0.36 sec) mysql> create table t2 (id int not null,name varchar(15) not null); Query OK, 0 rows affected (0.10 sec) mysql> create table t3 (id int not null,gongzi int not null); Query OK, 0 rows affected (0.07 sec) mysql> create table t4 (id int not null,shui int not null); Query OK, 0 rows affected (0.07 sec)
看看創建的表格都放在哪?
mysql> explain create table t1 (id int not null,name varchar(15) not null,bu varchar(10) not null,city varchar(5) not null); +-----------+--------------------------------------------------------------------------------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------------------------------------------------------------------------------+ | dn1 | create table t1 (id int not null,name varchar(15) not null,bu varchar(10) not null,city varchar(5) not null) | | dn2 | create table t1 (id int not null,name varchar(15) not null,bu varchar(10) not null,city varchar(5) not null) | +-----------+--------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) mysql>
這是分片表,dn1,dn2都有
mysql> explain create table t2 (id int not null,name varchar(15) not null); +-----------+-------------------------------------------------------------+ | DATA_NODE | SQL | +-----------+-------------------------------------------------------------+ | dn1 | create table t2 (id int not null,name varchar(15) not null) | | dn2 | create table t2 (id int not null,name varchar(15) not null) | +-----------+-------------------------------------------------------------+ 2 rows in set (0.00 sec) mysql>
這是全局表,dn1,dn2都有,全局表的意思是,每個dn節點都有的表而且數據保持一致。
mysql> explain create table t3 (id int not null,gongzi int not null); +-----------+-------------------------------------------------------+ | DATA_NODE | SQL | +-----------+-------------------------------------------------------+ | dn1 | create table t3 (id int not null,gongzi int not null) | +-----------+-------------------------------------------------------+ 1 row in set (0.00 sec) mysql>
普通表,預設就是放在dn1,正常
mysql> explain create table t4 (id int not null,shui int not null); +-----------+------------------------------------------------------+ | DATA_NODE | SQL | +-----------+------------------------------------------------------+ | dn2 | create table t4 (id int not null,shui int not null) | +-----------+------------------------------------------------------+ 1 row in set (0.00 sec) mysql>
普通表,預設就是放在dn2,正常
看看從庫的情況:
mysql> show tables; +---------------+ | Tables_in_db1 | +---------------+ | t1 | | t2 | | t3 | +---------------+ 3 rows in set (0.00 sec) mysql>
除了t4沒有,其他都有,正常。
插入數據:
插入t1
mysql> insert into t1(id,name,bu,city)values(1,'am1','sy','bj'); Query OK, 1 row affected (0.38 sec) mysql> insert into t1(id,name,bu,city)values(2,'am2','cs','gz'); Query OK, 1 row affected (0.03 sec) mysql> insert into t1(id,name,bu,city)values(3,'am3','net','sz'); Query OK, 1 row affected (0.08 sec) mysql>
插入t2
mysql> insert into t2(id,name)value(4,'am4'),(5,'am5'); Query OK, 2 rows affected (0.11 sec) Records: 2 Duplicates: 0 Warnings: 0
插入t3
mysql> insert into t3(id,gongzi)values(6,1000),(7,1200); Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0
插入t4
mysql> insert into t4(id,shui)values(8,10),(9,8); Query OK, 2 rows affected (0.04 sec) Records: 2 Duplicates: 0 Warnings: 0
基礎架構和環境以及達成,現在來測試:
首先,t1根據預設的目的,bj和gz的數據存放在dn1(mysql1),sz的數據存放在dn2(mysql3)
mysql> select * from t1 where city='bj' or city='gz'; +----+------+----+------+ | id | name | bu | city | +----+------+----+------+ | 1 | am1 | sy | bj | | 2 | am2 | cs | gz | +----+------+----+------+ 2 rows in set (0.10 sec) mysql> explain select * from t1 where city='bj' or city='gz'; +-----------+--------------------------------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------------------------------+ | dn1 | SELECT * FROM t1 WHERE city = 'bj' OR city = 'gz' LIMIT 100 | +-----------+--------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> mysql> explain select * from t1 where city='sz'; +-----------+----------------------------------------------+ | DATA_NODE | SQL | +-----------+----------------------------------------------+ | dn2 | SELECT * FROM t1 WHERE city = 'sz' LIMIT 100 | +-----------+----------------------------------------------+ 1 row in set (0.02 sec) mysql>
分表正常
測試讀寫分離
開啟debug日志
<asyncRoot level="debug" includeLocation="true"> ##默認level是info 改成debug后,重啟mycat服務。 <AppenderRef ref="Console" /> <AppenderRef ref="RollingFile"/> </asyncRoot>
檢索數據:
檢索t3的數據,t3只有mysql1有。
mysql> select * from t3; +----+--------+ | id | gongzi | +----+--------+ | 6 | 1000 | | 7 | 1200 | +----+--------+ 2 rows in set (0.02 sec)
以下是mycat.log日志,可以看到是從mysql2(192.168.211.139)讀取的數據
2017-12-15 01:47:23.280 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=22, lastTime=1513320443251, user=root, schema=db1, old shema=db1, borrowed=true, fromSlaveDB=true, threadId=33, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROM t3 LIMIT 100}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROM t3 LIMIT 100}, packetId=6], host=192.168.211.139, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false] 2017-12-15 01:54:37.777 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=26, lastTime=1513320877751, user=root, schema=db1, old shema=db1, borrowed=true, fromSlaveDB=true, threadId=31, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROM t3 LIMIT 100}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROM t3 LIMIT 100}, packetId=6], host=192.168.211.139, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
mysql> select * from t1; +----+------+-----+------+ | id | name | bu | city | +----+------+-----+------+ | 3 | am3 | net | sz | | 1 | am1 | sy | bj | | 2 | am2 | cs | gz | +----+------+-----+------+ 3 rows in set (0.04 sec)
日志
2017-12-15 02:02:35.818 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) - con need syn ,total syn cmd 1 commands SET names utf8;schema change:false con:MySQLConnection [id=29, lastTime=1513321355817, user=root, schema=db1, old shema=db1, borrowed=true, fromSlaveDB=true, threadId=35, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROM t1 LIMIT 100}, respHandler=io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler@11eaaf37, host=192.168.211.139, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false] 2017-12-15 02:02:35.819 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) - con need syn ,total syn cmd 1 commands SET names utf8;schema change:false con:MySQLConnection [id=20, lastTime=1513321355819, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=65, charset=utf8, txIsolation=3, autocommit=true, attachment=dn2{SELECT * FROM t1 LIMIT 100}, respHandler=io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler@11eaaf37, host=192.168.211.142, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
多執行幾次檢索存在dn1的數據,查看日志,可以確認,數據都是從mysql2(192.168.211.139)讀取。實現了讀寫分離。
8.讀寫兩種不同寫法的測試
前面有提到讀寫分離有兩種寫法,
<dataHost name="mysql1" 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.211.138:3306" user="root" password="Alex2010@"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.211.139:3306" user="root" password="Alex2010@"/> </writeHost> </dataHost>
讀寫分離這里有兩種寫法:
除了上面的還可以寫下面這樣:
<dataHost name="mysql1" 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.211.138:3306" user="root" password="Alex2010@"> </writeHost> <writeHost host="hostM1" url="192.168.211.139:3306" user="root" password="Alex2010@"> </writeHost> </dataHost>
區別是上面的那種寫法,如果主服務器掛了,從服務器不能讀了。
下面的這種寫法,主服務器掛了,從服務器依然可以正常讀取。
現在服務器的寫法是第一種,主服務器掛了,從服務器不能讀了。執行看看
[root@mysql1 ~]# systemctl stop mysqld.service [root@mysql1 ~]# systemctl status mysqld.service ● mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: inactive (dead) since Fri 2017-12-15 02:16:43 EST; 35s ago Docs: man:mysqld(8)
[root@mysql1 ~]# mysql -uroot -p123456 -P8066 -h227.0.0.1 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB) Copyright (c) 2000, 2017, 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> select * from t1; ERROR 3000 (HY000): No MyCAT Database selected mysql> select * from t1; ERROR 3000 (HY000): No MyCAT Database selected
確實無法讀取
測試第二種
修改schema.xml配置文件
重新啟動mysql和mycat 保證環境正常
正常使用環境,我們現在關閉mysql1就是主節點
[root@mysql1 conf]# systemctl stop mysqld.service [root@mysql1 conf]# systemctl status mysqld.service ● mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: inactive (dead) since Fri 2017-12-15 02:23:55 EST; 23s ago Docs: man:mysqld(8)
檢索數據看看
[root@mysql1 ~]# mysql -uroot -p123456 -P8066 -h227.0.0.1 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB) Copyright (c) 2000, 2017, 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> use hello; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from t1; +----+------+-----+------+ | id | name | bu | city | +----+------+-----+------+ | 3 | am3 | net | sz | | 1 | am1 | sy | bj | | 2 | am2 | cs | gz | +----+------+-----+------+ 3 rows in set (0.46 sec)
果然如此,孰優孰劣無須說明了吧。
后記:通過環境的搭建和簡單的測試,達到了設計的預期目標。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。