您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)MyCat中怎么實(shí)現(xiàn)讀寫分離,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
這里沒有用到mysql03主機(jī),讀寫分離的實(shí)現(xiàn)比較簡(jiǎn)單,只需要修改mycat的下面兩個(gè)配置文件即可。如下:
[root@mycat mycat]# pwd /usr/local/mycat <!--此處為mycat的家目錄--> [root@mycat mycat]# vim conf/server.xml <!--指定client連接mycat的用戶名及密碼,此處的賬號(hào)密碼與MySQL數(shù)據(jù)庫無關(guān)--> [root@mycat mycat]# vim conf/server.xml <!--定位到80行左右,修改如下--> <user name="mycat" defaultAccount="true"> <!--mycat為用戶名--> <property name="password">pwd@123</property> <!--此處為用戶mycat的登錄密碼--> <property name="schemas">test_mycat</property> <!--此處為邏輯庫名-- <!-- 表級(jí) DML 權(quán)限設(shè)置 --> <!-- <privileges check="false"> <schema name="TESTDB" dml="0110" > <table name="tb01" dml="0000"></table> <table name="tb02" dml="1111"></table> </schema> </privileges> --> </user>
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <!--下面的schema必須和第一個(gè)文件中的schema name(邏輯庫名)一致。--> <schema name="test_mycat" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> </schema> <dataNode name="dn1" dataHost="host1" database="test" /> <!--這里的database是指定要連接后端的哪個(gè)數(shù)據(jù)庫,這里連接的是test庫--> <!--下面是指定后端真實(shí)的MySQL主機(jī),關(guān)于下面的balance值,有三個(gè)可選值,將在下面寫下來--> <dataHost name="host1" 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 --> <!--指定后端哪臺(tái)主機(jī)用來寫數(shù)據(jù)--> <writeHost host="hostM1" url="192.168.20.2:3306" user="root" password="123.com"> <!-- can have multi read hosts --> <!--指定后端哪臺(tái)主機(jī)用來讀數(shù)據(jù)--> <readHost host="hostS2" url="192.168.20.3:3306" user="root" password="123.com" /> </writeHost> </dataHost> </mycat:schema>
注:上面提到的dataHost字段balance負(fù)載均衡類型,目前的取值有以下4 種:
balance="0", 不開啟讀寫分離機(jī)制,所有讀操作都發(fā)送到當(dāng)前可用的 writeHost 上(默認(rèn)值)。
balance="1",全部的 readHost 與 stand by writeHost 參與 select 語句的負(fù)載均衡,簡(jiǎn)單的說,當(dāng)雙主雙從模式(M1->S1,M2->S2,并且 M1 與 M2 互為主備),正常情況下,M2,S1,S2 都參與 select 語句的負(fù)載均衡。
balance="2",所有讀操作都隨機(jī)的在 writeHost、readhost 上分發(fā)。
balance="3",所有讀請(qǐng)求隨機(jī)的分發(fā)到 wiriterHost 對(duì)應(yīng)的 readhost 執(zhí)行,writerHost 不負(fù)擔(dān)讀壓力,注意 balance=3 只在 1.4 及其以后版本有,1.3 沒有。
writeTyep字段有以下3中取值:
1、writeType="0", 所有寫操作發(fā)送到配置的第一個(gè) writeHost,第一個(gè)掛了切到還生存的第二個(gè) writeHost,重新啟動(dòng)后已切換后的為準(zhǔn),切換記錄在配置文件中:dnindex.properties 。
2、writeType="1",所有寫操作都隨機(jī)的發(fā)送到配置的 writeHost,1.5 以后廢棄不推薦。switchType 屬性
-1 表示不自動(dòng)切換。
1 默認(rèn)值,自動(dòng)切換。
2 基于 MySQL 主從同步的狀態(tài)決定是否切換。
[root@mycat mycat]# vim conf/server.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mycat:server SYSTEM "server.dtd"> <mycat:server xmlns:mycat="http://io.mycat/"> <system> <property name="useSqlStat">0</property> <!-- 1為開啟實(shí)時(shí)統(tǒng)計(jì)、0為關(guān)閉 --> <property name="useGlobleTableCheck">0</property> <!-- 1為開啟全加班一致性檢測(cè)、0為關(guān)閉 --> <property name="sequnceHandlerType">2</property> <property name="processorBufferPoolType">0</property> <property name="handleDistributedTransactions">0</property> <property name="useOffHeapForMerge">1</property> <property name="memoryPageSize">1m</property> <property name="spillsFileBufferSize">1k</property> <property name="useStreamOutput">0</property> <property name="systemReserveMemorySize">384m</property> <property name="useZKSwitch">true</property> </system> <user name="mycat" > <property name="password">pwd@123</property> <property name="schemas">test_mycat</property> </user> </mycat:server>
[root@mycat mycat]# vim conf/schema.xml <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="test_mycat" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> </schema> <dataNode name="dn1" dataHost="host1" database="test" /> <dataHost name="host1" 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.20.2:3306" user="root" password="123.com"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.20.3:3306" user="root" password="123.com" /> </writeHost> </dataHost> </mycat:schema>
注:至此,后端數(shù)據(jù)庫上自行創(chuàng)建有相關(guān)權(quán)限的用戶,比如我在上面的datahost字段中指定的writehost和readhost字段的user值為root,則數(shù)據(jù)庫的root賬號(hào)要有對(duì)應(yīng)的登錄權(quán)限(默認(rèn)root用戶只允許在localhost登錄,所以要自行修改root權(quán)限或換成其他有權(quán)限的用戶)。
總結(jié):
1.指定的后端數(shù)據(jù)庫登錄用戶,必須可以有相應(yīng)的權(quán)限;
2.在上面指定的后端真實(shí)數(shù)據(jù)庫為test,所以后端必須要有這個(gè)test庫;
[root@mycat mycat]# mycat start #啟動(dòng)mycat [root@mycat mycat]# mysql -umycat -ppwd@123 -h 192.168.20.4 -P 8066 #登錄到mycat #192.168.20.4為mycat主機(jī)IP,mycat監(jiān)聽端口為8066,使用的登錄用戶為server.xml文件中創(chuàng)建的用戶 #創(chuàng)建表并插入一些測(cè)試數(shù)據(jù) mysql> use test_mycat; mysql> create table t1 (id int,name varchar(4)); mysql> insert into t1 values(1,'張三'),(2,'李四'),(3,'王五'); #此時(shí),去后端數(shù)據(jù)庫上查看,應(yīng)該是有上面這些數(shù)據(jù)的。 #現(xiàn)在可以暫時(shí)關(guān)閉后端數(shù)據(jù)庫的主從復(fù)制,然后再mycat主機(jī)上繼續(xù)插入數(shù)據(jù),測(cè)試是否可以讀到 #關(guān)閉主從復(fù)制命令:stop slave; #以下操作還是在mycat主機(jī)進(jìn)行 mysql> insert into t1 values(4,'趙六'); #插入一條數(shù)據(jù) Query OK, 1 row affected (0.01 sec) mysql> select * from t1; #查詢不到剛插入的數(shù)據(jù),說明讀寫操作沒有在同一臺(tái)主機(jī)上進(jìn)行 +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | +------+--------+ #可以去后端兩個(gè)數(shù)據(jù)庫分別進(jìn)行查看數(shù)據(jù) #mysql01主機(jī)的數(shù)據(jù)如下(說明寫操作是在mysql01): mysql> select * from t1; +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | | 4 | 趙六 | +------+--------+ 4 rows in set (0.00 sec) #mysql02主機(jī)的數(shù)據(jù)如下: mysql> select * from t1(說明讀操作是在mysql02); +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | +------+--------+ 3 rows in set (0.00 sec)
讀寫分離效果至此結(jié)束。(為不影響后面的測(cè)試進(jìn)行,最好恢復(fù)mysql01和mysql02主機(jī)的主從復(fù)制)。
一個(gè)數(shù)據(jù)庫由很多表組成,每個(gè)表對(duì)應(yīng)著不同的業(yè)務(wù),所謂分庫,就是按照業(yè)務(wù)將表進(jìn)行分類,分不到不同的數(shù)據(jù)庫上面,這樣也就將數(shù)據(jù)或者說壓力分擔(dān)到不同的庫上面,分庫的原則:有緊密關(guān)聯(lián)關(guān)系的表應(yīng)該在一個(gè)庫里,相互沒有或者關(guān)聯(lián)關(guān)系不大的表可以分到不同的庫里。
分庫舉例:
假設(shè)現(xiàn)在有四張表: customer, orders, orders_detail, dict_order_type,每張表都有數(shù)百萬條數(shù)據(jù),那么這四張表如若要實(shí)現(xiàn)分庫,則可以將customer表單獨(dú)分離到一個(gè)數(shù)據(jù)庫,另外三張表單獨(dú)在另一個(gè)數(shù)據(jù)庫。
[root@mycat mycat]# cat conf/server.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mycat:server SYSTEM "server.dtd"> <mycat:server xmlns:mycat="http://io.mycat/"> <system> <property name="useSqlStat">0</property> <!-- 1為開啟實(shí)時(shí)統(tǒng)計(jì)、0為關(guān)閉 --> <property name="useGlobleTableCheck">0</property> <!-- 1為開啟全加班一致性檢測(cè)、0為關(guān)閉 --> <property name="sequnceHandlerType">2</property> <property name="processorBufferPoolType">0</property> <property name="handleDistributedTransactions">0</property> <property name="useOffHeapForMerge">1</property> <property name="memoryPageSize">1m</property> <property name="spillsFileBufferSize">1k</property> <property name="useStreamOutput">0</property> <property name="systemReserveMemorySize">384m</property> <property name="useZKSwitch">true</property> </system> <user name="mycat" > <property name="password">pwd@123</property> <property name="schemas">test_db</property> </user> </mycat:server>
[root@mycat mycat]# cat conf/schema.xml <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="test_db" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> <table name="customer" dataNode="dn2"/> <!--這里指定customer在dn2節(jié)點(diǎn)上--> </schema> <dataNode name="dn1" dataHost="host1" database="test" /> <dataNode name="dn2" dataHost="host2" database="test" /> <dataHost name="host1" 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.20.2:3306" user="root" password="123.com"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.20.3:3306" user="root" password="123.com" /> </writeHost> </dataHost> <!--下面添加host2主機(jī)字段,指定的主機(jī)就是mysql03--> <dataHost name="host2" 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="hostM2" url="192.168.20.21:3306" user="root" password="123.com"> </writeHost> </dataHost> </mycat:schema>
[root@mycat mycat]# mycat restart
注:后端指定的真實(shí)數(shù)據(jù)庫必須要有test數(shù)據(jù)庫,因?yàn)樵谏厦鎠chema.xml文件中的dataNode字段指定的是連接后端的test數(shù)據(jù)庫。
#登錄到mycat [root@mycat mycat]# mysql -umycat -ppwd@123 -h 192.168.20.4 -P 8066 #創(chuàng)建相應(yīng)的表 mysql> use test_db; mysql> CREATE TABLE customer( -> id_a INT AUTO_INCREMENT, -> NAME VARCHAR(200), -> PRIMARY KEY(id_a) -> ); Query OK, 0 rows affected (0.02 sec) mysql> CREATE TABLE orders( -> id_b INT AUTO_INCREMENT, -> order_type INT, -> customer_id INT, -> amount DECIMAL(10,2), -> PRIMARY KEY(id_b) -> ); Query OK, 0 rows affected (0.01 sec) mysql> CREATE TABLE orders_detail( -> id_c INT AUTO_INCREMENT, -> detail VARCHAR(2000), -> order_id INT, -> PRIMARY KEY(id_c) -> ); Query OK, 0 rows affected (0.02 sec) mysql> CREATE TABLE dict_order_type( -> id_d INT AUTO_INCREMENT, -> order_type VARCHAR(200), -> PRIMARY KEY(id_d) -> ); Query OK, 0 rows affected (0.01 sec) #登錄到后端數(shù)據(jù)庫上,查看表是否按照預(yù)計(jì)的效果拆分 [root@mycat mycat]# mysql -uroot -p123.com -h 192.168.20.2 mysql> use test; mysql> show tables; #可以看到主機(jī)mysql01這里有三個(gè)表 +-----------------+ | Tables_in_test | +-----------------+ | dict_order_type | | orders | | orders_detail | +-----------------+ 3 rows in set (0.00 sec) #登錄到mysql03上查看 [root@mycat mycat]# mysql -uroot -p123.com -h 192.168.20.21 mysql> use test; mysql> show tables; #可以看到這里只有customer表 +----------------+ | Tables_in_test | +----------------+ | customer | +----------------+ 1 row in set (0.00 sec)
至此,已經(jīng)實(shí)現(xiàn)了分庫,多個(gè)表放在了不同的庫中(在上面的栗子中,實(shí)現(xiàn)的是多個(gè)表放在了不同的主機(jī)上),但對(duì)于通過mycat登錄的客戶來說,還是一個(gè)庫,庫中有四張表。
這里對(duì)一個(gè)新表emp進(jìn)行拆分。
[root@mycat mycat]# cat conf/schema.xml <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="test_db" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> <table name="customer" dataNode="dn2"/> <!--只需要在原來的配置文件中增加下面一行即可,表示將emp表分在了dn1和dn2這兩個(gè)節(jié)點(diǎn)上--> <table name="emp" dataNode="dn1,dn2" rule="mod_rule"/> </schema> <dataNode name="dn1" dataHost="host1" database="test" /> <dataNode name="dn2" dataHost="host2" database="test" /> <dataHost name="host1" 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.20.2:3306" user="root" password="123.com"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.20.3:3306" user="root" password="123.com" /> </writeHost> </dataHost> <dataHost name="host2" 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="hostM2" url="192.168.20.21:3306" user="root" password="123.com"> </writeHost> </dataHost> </mycat:schema>
[root@mycat mycat]# vim conf/rule.xml #修改rule.xml文件 <tableRule name="mod_rule"> <!--這里指定的name必須和schema.xml中指定的name一致--> <rule> <columns>id</columns> <!--這里指定的是以哪里列進(jìn)行分表的--> <algorithm>mod_long</algorithm> <!--這里指定的是分片方法--> </rule> </tableRule> ................... <!--下面的name必須和上面的分片方法一致--> <function name="mod_long" class="io.mycat.route.function.PartitionByMod"> <!-- how many data nodes --> <property name="count">2</property> <!--這里指定的是node節(jié)點(diǎn)數(shù)量--> </function>
[root@mycat mycat]# mycat restart
[root@mycat mycat]# mysql -umycat -ppwd@123 -h 192.168.20.4 -P 8066 mysql> use test_db; #創(chuàng)建emp表(后端兩個(gè)數(shù)據(jù)庫節(jié)點(diǎn)上都會(huì)有這張表) mysql> create table emp ( -> id int, -> name varchar(10) -> ); Query OK, 0 rows affected (0.41 sec) #插入多條數(shù)據(jù)(對(duì)于這種分表,插入數(shù)據(jù)需要指定列名,否則會(huì)報(bào)錯(cuò)) mysql> insert into emp(id,name) values(1,'張三'),(2,'李四'),(3,'王五'),(4,'趙六'); #查詢新插入的數(shù)據(jù) mysql> select * from emp; +------+--------+ | id | name | +------+--------+ | 2 | 李四 | | 4 | 趙六 | | 1 | 張三 | | 3 | 王五 | +------+--------+ 4 rows in set (0.04 sec) mysql> select * from emp order by id; #對(duì)結(jié)果進(jìn)行排序 +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | | 4 | 趙六 | +------+--------+ 4 rows in set (0.01 sec) #后端mysql01主機(jī)查詢到該表的數(shù)據(jù)如下: mysql> select * from emp; +------+--------+ | id | name | +------+--------+ | 2 | 李四 | | 4 | 趙六 | +------+--------+ 2 rows in set (0.00 sec) #mysql03主機(jī)查詢到的數(shù)據(jù)如下: mysql> select * from emp; +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 3 | 王五 | +------+--------+ 2 rows in set (0.00 sec)
可以看到數(shù)據(jù)是平均分散在不同節(jié)點(diǎn)上保存的。
但是經(jīng)過分片的普通表,是無法直接和其他表進(jìn)行join的。
要想解決多表join的問題,還需要修改schema.xml配置文件,在分表的table字段下添加childTable字段,具體怎么實(shí)現(xiàn),還在研究中。但是可以將分表的類型設(shè)置為全局表,這是一種比較簡(jiǎn)單的實(shí)現(xiàn)方式。
分表后,與其他表如何join就成了比較棘手的問題,我們可以選擇將分表設(shè)置為全局表,這是一個(gè)解決join的方法(但不是唯一的方法),但全局表有一定的局限性,如下:
全局表變動(dòng)不頻繁;
數(shù)據(jù)量總體變化不大;
數(shù)據(jù)規(guī)模不大,很少有超數(shù)十萬的記錄。
全局表有以下特性:
全局表的插入、更新操作會(huì)實(shí)時(shí)在所有節(jié)點(diǎn)上執(zhí)行,保持各個(gè)分片的數(shù)據(jù)一致性;
全局表的查詢操作,只從一個(gè)節(jié)點(diǎn)獲取;
全局表可以跟任何一個(gè)表進(jìn)行 JOIN 操作。
若想創(chuàng)建全局表,只需在table字段增加type="global"即可。如下:
[root@mycat conf]# cat schema.xml <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="test_db" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> <table name="customer" dataNode="dn2"/> <!--在下面的table字段增加global屬性即可--> <table name="emp" dataNode="dn1,dn2" type="global"> </table> </schema> <dataNode name="dn1" dataHost="host1" database="test" /> <dataNode name="dn2" dataHost="host2" database="test" /> <dataHost name="host1" 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.20.2:3306" user="root" password="123.com"> <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.20.3:3306" user="root" password="123.com" /> </writeHost> </dataHost> <dataHost name="host2" 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="hostM2" url="192.168.20.21:3306" user="root" password="123.com"> </writeHost> </dataHost> </mycat:schema>
mysql> drop table emp; #需要?jiǎng)h除之前創(chuàng)建的emp表 Query OK, 0 rows affected (0.03 sec) #重新創(chuàng)建emp表 mysql> create table emp( -> id int, -> name varchar(10) -> ); Query OK, 0 rows affected (0.38 sec) #插入數(shù)據(jù)測(cè)試 mysql> insert into emp(id,name) values(1,'張三'),(2,'李四'),(3,'王五'),(4,'趙六'); #在mycat上查詢插入的數(shù)據(jù)如下: mysql> select * from emp; +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | | 4 | 趙六 | +------+--------+ 4 rows in set (0.02 sec) #在后端主機(jī)上分別查看emp表中的數(shù)據(jù): #mysql01主機(jī)上數(shù)據(jù)如下: mysql> select * from emp; +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | | 4 | 趙六 | +------+--------+ 4 rows in set (0.00 sec) #mysql03主機(jī)上數(shù)據(jù)如下: mysql> select * from emp; +------+--------+ | id | name | +------+--------+ | 1 | 張三 | | 2 | 李四 | | 3 | 王五 | | 4 | 趙六 | +------+--------+ 4 rows in set (0.00 sec)
上述就是小編為大家分享的MyCat中怎么實(shí)現(xiàn)讀寫分離了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。