mycat詳細

MyCAT的優點
基於阿里開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能以及衆多成熟的使用案例使得MYCAT一開始就擁有一個很好的起點,站在巨人的肩膀上,咱們能看到更遠。業界優秀的開源項目和創新思路被普遍融入到MYCAT的基因中,使得MYCAT在不少方面都領先於目前其餘一些同類的開源項目,甚至超越某些商業產品。
MYCAT背後有一支強大的技術團隊,其參與者都是5年以上資深軟件工程師、架構師、DBA等,優秀的技術團隊保證了MYCAT的產品質量。
MYCAT並不依託於任何一個商業公司,所以不像某些開源項目,將一些重要的特性封閉在其商業產品中,使得開源項目成了一個擺設。


高可用方案和架構圖以下:




css

 

 Mycat部署與使用 前端

MyCAT 能夠視爲「MySQL」集羣的企業級數據庫,用來替代昂貴的Oracle集羣,其背後是阿里曾經開源的知名產品Cobar。MyCAT的目標是:低成本的將現有的單機數據庫和應用平滑遷移到「雲」端,解決數據存儲和業務規模迅速增加狀況下的數據瓶頸問題。java

下面就適合訂單的業務場景作介紹node

1 應用場景mysql

Mycat 有不少數據分庫規則,接下來幾篇就相關以爲經常使用的規則進行試用與總結。linux

通常來講,按天然月份或按日期來進行數據分片的規則比較適用於商城訂單查詢,相似最近1周、2周、3個月內的數據。或是報表類應用。程序員

這樣的數據放在一個片區內省去了數據合併的時間。sql

固然按月數據量不要過大就OK。mongodb

1、部署步驟詳解
(1) 用命令行工具或圖形化客戶端,鏈接MYSQL,建立DEMO所用三個分片數據庫;數據庫

CREATE SCHEMA `range_db_01` DEFAULT CHARACTER SET utf8 ;
CREATE SCHEMA `range_db_02` DEFAULT CHARACTER SET utf8 ;
CREATE SCHEMA `range_db_03` DEFAULT CHARACTER SET utf8 ;
CREATE SCHEMA `range_db_04` DEFAULT CHARACTER SET utf8 ; 

(2) 修改配置my.cnf新增如下語句, 通常會放在/etc/my.cnf 或 /etc/mysql/my.cnf,設置爲Mysql表名大小寫不敏感,不然可能會發生表找不到的問題。

lower_case_table_names = 1 

(3) 解壓Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz 到安裝目錄下,會生成mycat目錄

(4) 安裝jdk-7u79-linux-x64

(5) 修改mycat/conf/wrap.conf 修改wrapper.Java.command=java爲上一步存放路徑

wrapper.java.command=/usr/java/jdk1.7.0_79/ 

(6) 建立mycat 用戶,改變目錄權限爲mycat

useradd mycat
chown -R mycat.mycat mycat 

(7) 修改用戶密碼

passwd mycat
輸入: 

(8) 修改mycat/conf/schema.xml,URL、用戶名、密碼修改,其他不變

<writeHost host="hostM1" url="192.168.184.56:3306" user="root"
                       password="root"> 

2、運行步驟詳解
(1) 進入 mycat/bin (默認數據端口爲8066,管理端口爲9066)
執行./mycat start
(2) 進入logs目錄,查看日誌,若是wrapper.log 報錯 java.NET.BindException: Address already in use 殺掉正在執行的相關java進程

ps -ef|grep java
kill -9 xxx 

3、使用步驟詳解
(1) 進入mysql bin目錄mysql/bin/
(2) 登陸mysql 執行如下命令
./mysql -utest -ptest -h192.168.184.56 -P8066 -DTESTDB

(mycat的用戶帳號和受權信息是在conf/server.xml文件中配置)
(3) 表建立測試:

mysql> create table employee (id int not null primary key,name varchar(100),sharding_id int not null);
Query OK, 0 rows affected (0.30 sec)
mysql> explain create table employee (id int not null primary key,name varchar(100),sharding_id int not null);
+-----------+------------------------------------------------------------------------------------------------+
| DATA_NODE | SQL                                                                                            |
+-----------+------------------------------------------------------------------------------------------------+
| dn1       | create table employee (id int not null primary key,name varchar(100),sharding_id int not null) | 
| dn2       | create table employee (id int not null primary key,name varchar(100),sharding_id int not null) | 
+-----------+------------------------------------------------------------------------------------------------+
2 rows in set (0.04 sec) 

(4) 客戶端軟件使用:navicat
建立mycat新鏈接:ip:192.168.184.56,用戶名:test,密碼:test,端口:8066
可看到TESTDB數據庫下已建立表:employee
打開db1,db2 數據庫也可看到已建立表employee

(5) 插入數據測試

mysql> insert into employee(id,name,sharding_id) values(1,'leader us',10000);
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    6
Current database: TESTDB
Query OK, 1 row affected (0.03 sec)
mysql> explain insert into employee(id,name,sharding_id) values(1,'leader us',10000);
+-----------+-----------------------------------------------------------------------+
| DATA_NODE | SQL                                                                   |
+-----------+-----------------------------------------------------------------------+
| dn1       | insert into employee(id,name,sharding_id) values(1,'leader us',10000) | 
+-----------+-----------------------------------------------------------------------+
1 row in set (0.00 sec) 

(6) 根據規則auto-sharding-long(主鍵範圍)進行分片測試

mysql> explain create table company(id int not null primary key,name varchar(100));
+-----------+---------------------------------------------------------------------+
| DATA_NODE | SQL                                                                 |
+-----------+---------------------------------------------------------------------+
| dn1       | create table company(id int not null primary key,name varchar(100)) | 
| dn2       | create table company(id int not null primary key,name varchar(100)) | 
| dn3       | create table company(id int not null primary key,name varchar(100)) | 
+-----------+---------------------------------------------------------------------+
3 rows in set (0.01 sec) 

(7) 三個分片上都插入了3條數據

mysql> explain insert into company(id,name) values(1,'hp');
+-----------+---------------------------------------------+
| DATA_NODE | SQL                                         |
+-----------+---------------------------------------------+
| dn1       | insert into company(id,name) values(1,'hp') | 
| dn2       | insert into company(id,name) values(1,'hp') | 
| dn3       | insert into company(id,name) values(1,'hp') | 
+-----------+---------------------------------------------+
3 rows in set (0.00 sec) 

(8) 確認是分片存儲

mysql> select * from employee;
+----+-----------+-------------+
| id | name      | sharding_id |
+----+-----------+-------------+
|  2 | me        |       10010 | 
|  4 | mydog     |       10010 | 
|  1 | leader us |       10000 | 
|  3 | mycat     |       10000 | 
+----+-----------+-------------+
4 rows in set (0.01 sec)
mysql> explain select * from employee;
+-----------+----------------------------------+
| DATA_NODE | SQL                              |
+-----------+----------------------------------+
| dn1       | SELECT * FROM employee LIMIT 100 | 
| dn2       | SELECT * FROM employee LIMIT 100 | 
+-----------+----------------------------------+
2 rows in set (0.00 sec)


mycat更詳細閱讀
 MySQL分佈式集羣之MyCAT
-----------------------------------------------------------------重要的TIPs-----------------------------------------------------------------------
MyCAT的團隊已經發布了1.4Alpha版本,這其中修復了很多的bug,也添加了新功能,
博主這邊測試用的是1.3的版本,因此和最新版本的測試結果可能出現不一致!

-------------------------------------------------------------------背景介紹------------------------------------------------------------------

MyCAT的背景介紹直接略過,沒啥用,固然,這是一個由JAVA開發的東東,這一點須要瞭解~。

-----------------------------------------------------------------MyCAT的前身----------------------------------------------------------------
MyCAT的前身,是阿里巴巴於2012年6月19日,正式對外開源的數據庫中間件Cobar,Cobar的前身是早已經開源的Amoeba,不過其做者陳思儒離職去盛大以後,阿里巴巴內部考慮到Amoeba的穩定性、性能和功能支持,以及其餘因素,從新設立了一個項目組而且更換名稱爲Cobar。Cobar是由 Alibaba 開源的 MySQL 分佈式處理中間件,它能夠在分佈式的環境下看上去像傳統數據庫同樣提供海量數據服務。

Cobar自誕生之日起, 就受到廣大程序員的追捧,可是自2013年後,幾乎沒有後續更新。在此狀況下,MyCAT應運而生,它基於阿里開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能,以及衆多成熟的使用案例使得MyCAT一開始就擁有一個很好的起點,站在巨人的肩膀上,MyCAT能看到更遠。

---------------------------------------------------------MyCAT的下載方式--------------------------------------------------------------------
MyCAT的SVN地址爲:http://code.taobao.org/svn/openclouddb/

---------------------------------------------------------MyCAT的重要特性--------------------------------------------------------------------
支持 SQL 92標準;
支持MySQL集羣,能夠做爲Proxy使用;
支持JDBC鏈接ORACLE、DB二、SQL Server,將其模擬爲MySQL Server使用;
支持galera for mysql集羣,percona-cluster或者mariadb cluster,提供高可用性數據分片集羣;
自動故障切換,高可用性;
支持讀寫分離,支持MySQL雙主多從,以及一主多從的模式;
支持全局表,數據自動分片到多個節點,用於高效表關聯查詢;
支持獨有的基於E-R 關係的分片策略,實現了高效的表關聯查詢;
多平臺支持,部署和實施簡單。

------------------------------------------------------------MyCAT的體系結構----------------------------------------------------------------

整體上分紅三個部分,最前端的是鏈接器,線程管理使用了資源池,而且默認採用了AIO的方式(這些基本信息能夠再啓動日誌裏面看到);
中間層在圖中已經描述的很清楚了,SQL解析器+SQL路由,SQL Executor須要具體看源碼才能瞭解,由於經過這段時間對MyCAT的測試,沒有感受到SQL Executor的存在,更多的感受是一個SQL process的東西,DataNode和心跳檢測算是中間層實現的兩個組件,一個是和MySQL的庫(注意,不是實例)相關,一個是常見的監測機制的功能模塊;
最下層的存儲就是是MySQL的集羣了~怎麼玩MySQL的集羣,由咱們本身決定╰(?? ▽ ??)╯。

 
--------------------------------------------------------------怎麼使用MyCAT---------------------------------------------------------- 
MyCAT目前經過配置文件的方式來定義邏輯庫和相關配置,主要是包括三個文件:
MYCAT_HOME/conf/schema.xml中定義邏輯庫,表、分片節點等內容;
 MYCAT_HOME/conf/rule.xml中定義分片規則;
MYCAT_HOME/conf/server.xml中定義用戶以及系統相關變量,如端口等。

 不着急,這一篇簡單介紹這幾個配置文件的做用和一些參數的意義。
一個一個來,先看schema.xml,這是從網上摘抄的一個示例模板                

點擊(此處)摺疊或打開

  1. <?xml version="1.0"?>
  2. <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
  3. <mycat:schema xmlns:mycat="http://org.opencloudb/">
  4.     <schema name="weixin" checkSQLschema="false" sqlMaxLimit="100" dataNode="weixin" >
  5.         
  6.     
  7.     <schema name="yixin" checkSQLschema="false" sqlMaxLimit="100" dataNode="yixin" />
  8.         
  9.     
  10.     <dataNode name="dn1" dataHost="localhost0" database="weixin" />
  11.     <dataNode name="dn2" dataHost="localhost0" database="yixin" />
  12.     <dataHost name="localhost0" maxCon="450" minCon="10" balance="1"
  13.        writeType="0" dbType="mysql" dbDriver="native">
  14.        <heartbeat>select user()</heartbeat>
  15.        <!-- can have multi write hosts -->
  16.        <writeHost host="hostM1" url="localhost:3306" user="root" password="123456" />
  17.            <readHost host="hostS1" url="localhost:3307" user="test" password="123456" />
  18.     </dataHost>
  19. </mycat:schema>
首先是schema name = "weixin",這一項配置之後的效果就是,當MySQL客戶端鏈接MyCAT時,經過Show DATABASE命令,能看到的數據庫的,名字,
好比在這個配置文件裏面,就配置了兩個數據庫,weixin和yixin,這兩個庫各自包含一張user表。
注意:MyCAT對外端顯示出來的數據庫,和數據庫裏面的表,所有在schema裏面配置,沒有寫在這個裏面的表或者庫,即便後端的MySQL裏面存在,也沒法經過MyCAT去訪問,不過MyCAT不會去定義具體表的結構。
而後是datanode,這個屬性指定了schema的表,具體存放在哪一個數據庫,好比這個配置裏面,指定了dn1的數據節點位於localhost0,這個數據庫實例的名爲weixin的數據庫,dn2同理。
datahost列出了實際的後端MySQL集羣的具體信息,writehost是負責寫入數據的MySQL實例,writehost是負責讀的MySQL實例,若是兩個實例的具體信息寫成同樣,那就意味着後端使用單實例,若是配置成不一樣的實例,那麼就在兩個實例之間配置主從同步,而後經過MyCAT實現讀寫分離
對數據庫進行垂直切分,主要由schema.xml來完成,這個之後再詳細介紹。

rule.xml如示例

點擊(此處)摺疊或打開

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mycat:rule SYSTEM "rule.dtd">
  3. <mycat:rule xmlns:mycat="http://org.opencloudb/"> 
  4.  <tableRule name="rule">
  5.     <rule>
  6.       <columns>user_id</columns>
  7.       <algorithm>func1</algorithm>
  8.     </rule>
  9.  </tableRule>
  10.  <function name="func1" class="org.opencloudb.route.function.PartitionByLong">
  11.     <property name="partitionCount">2</property>
  12.     <property name="partitionLength">512</property>
  13.  </function>
  14. </mycat:rule>
                
rule.xml裏面的配置主要用於對錶的水平切分,MyCAt自己提供了不少種水平切分的策略,這個示例顯示的是取模分片,總共分紅四片,user_id對1024取模,而後分紅兩片,每一片512個。
其餘的切分策略之後再詳細介紹

server.xml如示例

點擊(此處)摺疊或打開

  1. <!DOCTYPE mycat:server SYSTEM "server.dtd">
  2. <mycat:server xmlns:mycat="http://org.opencloudb/">
  3.     <system>
  4.         <property name="sequnceHandlerType">0</property> 
  5.     </system>
  6.     <user name="test">
  7.        <property name="password">test</property>
  8.        <property name="schemas">weixin,yixin</property>
  9.     </user>
  10. </mycat:server>

server.xml裏面配置MyCAT的邏輯庫參數,如示例,配置的就是邏輯庫weixin和yixin的登陸用戶名和密碼
這個XML裏面其實還有一些有關於MyCAT性能調整的參數,不過略去了,東西太多,之後再詳細介紹

----------------------------------------------------------------------華麗的分割線-------------------------------------------------------------

簡單的MyCAT搭建大體上就包括這些內容,如今講講使用一段時間之後,對MyCAT的一些總結;
1.MyCAT的性能表現仍是不錯的,這幾天一直對MyCAT的各方面進行測試,發現MyCAT做爲一個代理,雖然是在JAVA虛擬機上面運行,可是面對接近9K的QPS的峯值的時候,自己並無出現無響應或者丟失鏈接的問題;
2.MyCAT對前端顯示的全部的庫,表,所有由schema來配置,可是自己不定義表結構,這使得後端的表結構若是出現不一致,MyCAT前端是察覺不到的,不太方便吧;
3.第二點的不方便,也反映了一點,沒有配置到schema的表,徹底沒法經過MyCAT去操做,這也算是安全性良好的一個表現吧;
4.以前說SQL Executor沒感受到,也是由於在一些測試中,發現MyCAT更像一個提供轉發和結果合併功能的代理,只是對SQL和結果進行了process,不過這個須要去看源代碼才知曉細節了。

此次只打算寫這麼多,關於MyCAT的一些細節介紹,留給下一章~
 
 在第一部分,有簡單的介紹MyCAT的搭建和配置文件的基本狀況,這一篇詳細介紹schema的一些具體參數,以及實際做用
        首先貼上本身測試用的schema文件,雙引號以前的反斜槓不會消除,姑且當成不存在吧...

點擊(此處)摺疊或打開

  1. <?xml version=\"1.0\"?>
  2. <!DOCTYPE mycat:schema SYSTEM \"schema.dtd\">
  3. <mycat:schema xmlns:mycat=\"http://org.opencloudb/\">
  4.     <schema name=\"mycat\" checkSQLschema=\"false\" sqlMaxLimit=\"100\">
  5.         <!-- auto sharding by id (long) -->
  6.         <table name=\"students\" dataNode=\"dn1,dn2,dn3,dn4\" rule=\"rule1\" />
  7.         <table name=\"log_test\" dataNode=\"dn1,dn2,dn3,dn4\" rule=\"rule2\" />
  8.         <!-- global table is auto cloned to all defined data nodes ,so can join 
  9.             with any table whose sharding node is in the same data node -->
  10.         <!--<table name=\"company\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2,dn3\" />
  11.         <table name=\"goods\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2\" />
  12.             -->
  13.         <table name=\"item_test\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2,dn3,dn4\" />
  14.         <!-- random sharding using mod sharind rule -->
  15.         <!-- <table name=\"hotnews\" primaryKey=\"ID\" dataNode=\"dn1,dn2,dn3\"
  16.             rule=\"mod-long\" /> -->
  17.             <!-- 
  18.         <table name=\"worker\" primaryKey=\"ID\" dataNode=\"jdbc_dn1,jdbc_dn2,jdbc_dn3\" rule=\"mod-long\" />
  19.  -->
  20.         <!-- <table name=\"employee\" primaryKey=\"ID\" dataNode=\"dn1,dn2\"
  21.             rule=\"sharding-by-intfile\" />
  22.         <table name=\"customer\" primaryKey=\"ID\" dataNode=\"dn1,dn2\"
  23.             rule=\"sharding-by-intfile\">
  24.             <childTable name=\"orders\" primaryKey=\"ID\" joinKey=\"customer_id\"
  25.                 parentKey=\"id\">
  26.                 <childTable name=\"order_items\" joinKey=\"order_id\"
  27.                     parentKey=\"id\" />
  28.             <ildTable>
  29.             <childTable name=\"customer_addr\" primaryKey=\"ID\" joinKey=\"customer_id\"
  30.                 parentKey=\"id\" /> -->
  31.     </schema>
  32.     <!-- <dataNode name=\"dn\" dataHost=\"localhost\" database=\"test\" /> -->
  33.     <dataNode name=\"dn1\" dataHost=\"localhost\" database=\"test1\" />
  34.     <dataNode name=\"dn2\" dataHost=\"localhost\" database=\"test2\" />
  35.     <dataNode name=\"dn3\" dataHost=\"localhost\" database=\"test3\" />
  36.     <dataNode name=\"dn4\" dataHost=\"localhost\" database=\"test4\" />
  37.     <!-- 
  38.     <dataNode name=\"jdbc_dn1\" dataHost=\"jdbchost\" database=\"db1\" />
  39.     <dataNode name=\"jdbc_dn2\" dataHost=\"jdbchost\" database=\"db2\" />
  40.     <dataNode name=\"jdbc_dn3\" dataHost=\"jdbchost\" database=\"db3\" />
  41.  -->
  42.     <dataHost name=\"localhost\" maxCon=\"100\" minCon=\"10\" balance=\"1\"
  43.         writeType=\"1\" dbType=\"mysql\" dbDriver=\"native\">
  44.         <heartbeat>select user()<beat>
  45.         <!-- can have multi write hosts -->
  46.         <writeHost host=\"localhost\" url=\"localhost:3306\" user=\"root\" password=\"wangwenan\">
  47.             <!-- can have multi read hosts -->
  48.             <readHost host=\"hostS1\" url=\"localhost:3307\" user=\"root\" password=\"wangwenan\"/>
  49.         </writeHost>
  50.         <writeHost host=\"localhost1\" url=\"localhost:3308\" user=\"root\" password=\"wangwenan\">
  51.             <!-- can have multi read hosts -->
  52.             <readHost host=\"hostS11\" url=\"localhost:3309\" user=\"root\" password=\"wangwenan\"/>
  53.         </writeHost>
  54.     </dataHost>
  55.         <!-- <writeHost host=\"hostM2\" url=\"localhost:3316\" user=\"root\" password=\"123456\"/> -->
  56.     <!-- 
  57.         <dataHost name=\"jdbchost\" maxCon=\"1000\" minCon=\"1\" balance=\"0\" writeType=\"0\" dbType=\"mongodb\" dbDriver=\"jdbc\">
  58.         <heartbeat>select user()<beat>
  59.         <writeHost host=\"hostM\" url=\"mongodb://192.168.0.99/test\" user=\"admin\" password=\"123456\" ></writeHost>
  60.     </dataHost>    
  61.     -->
  62.      <!-- 
  63.     <dataHost name=\"jdbchost\" maxCon=\"1000\" minCon=\"10\" balance=\"0\"
  64.         dbType=\"mysql\" dbDriver=\"jdbc\">
  65.         <heartbeat>select user()<beat>
  66.         <writeHost host=\"hostM1\" url=\"jdbc:mysql://localhost:3306\"
  67.             user=\"root\" password=\"123456\">
  68.         </writeHost>
  69.     </dataHost>
  70.      -->
  71. </mycat:schema>
        第一行參數<schema name="mycat" checkSQLschema="false" sqlMaxLimit="100"/>
                在這一行參數裏面,schema name定義了能夠在MyCAT前端顯示的邏輯數據庫的名字,
                checkSQLschema這個參數爲False的時候,代表MyCAT會自動忽略掉表名前的數據庫名,好比說mydatabase1.test1,會被當作test1;
                sqlMaxLimit指定了SQL語句返回的行數限制;
                     
                       
                如截圖,這個limit會讓MyCAT在分發SQL語句的時候,自動加上一個limit,限制從分庫得到的結果的行數,另外,截圖右上角能夠看到,MyCAT自己也是有緩存的;
                那麼,若是咱們執行的語句要返回較多的數據行,在不修改這個limit的狀況下,MyCAT會怎麼作?
                      
                 能夠從截圖看到,MyCAT徹底就沒搭理前端的實際需求, 老老實實返回100條數據 ,因此若是實際應用裏面須要返回大量數據,可能就得手動改邏輯了
                MyCAT的1.4版本里面,用戶的Limit參數會覆蓋掉默認的MyCAT設置 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                <table name="students" dataNode="dn1,dn2,dn3,dn4" rule="rule1" />
                這一行表明在MyCAT前端會顯示哪些表名,相似幾行都表明同樣的意思,這裏強調的是表,而MyCAT並不會在配置文件裏面定義表結構
                    若是在前端使用show create table ,MyCAT會顯示正常的表結構信息,觀察Debug日誌,
                      
                能夠看到,MyCAT把命令分發給了dn1表明的數據庫,而後把dn1的查詢結果返回給了前端
                能夠判斷,相似的數據庫級別的一些查詢指令,有多是單獨分發給某個節點,而後再把某個節點的信息返回給前端;
               
                dataNode的意義很簡單,這個邏輯表的數據存儲在後端的哪幾個數據庫裏面                
                rule表明的是這個邏輯表students的具體切分策略,目前MyCAT只支持按照某一個特殊列,遵循一些特殊的規則來切分,如取模,枚舉等,具體的留給以後細說 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                
                <table name="item_test" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3,dn4" />
                這一行表明的是全局表,這意味着,item_test這張表會在四個dataNode裏面都保存有完整的數據副本,那麼查詢的時候還會分發到全部的數據庫麼?
                      
                結果如截圖,MyCAT依然是規規矩矩的返回了100條數據(╮(╯_╰)╭),而針對全局表的查詢,只會分發到某一個節點上
                配置的primaryKey沒發現做用在哪裏,姑且忽略吧,之後發現了再補上

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                childtable我在測試中並無實際用起來不過在MyCAT的設計文檔裏面有提到,childtable是一種依賴於父表的結構,
                這意味着,childtable的joinkey會按照父表的parentKey的策略一塊兒切分,當父表與子表進行鏈接,且鏈接條件是childtable.joinKey=parenttable.parentKey時,不會進行跨庫的鏈接.
                PS:具體測試之後再補

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                dataNode的參數在以前的篇章介紹過,這裏直接跳過~

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                dataHost配置的是實際的後端數據庫集羣,大部分參數簡單易懂,這裏就不一個個介紹了,只介紹比較重要的兩個參數,writeType和balance.
                writeType和balance是用來控制後端集羣的讀寫分離的關鍵參數,這裏我用了雙主雙從的集羣配置
                這裏的測試過程比較麻煩,因此直接貼結論:
                        1.balance=0時,讀操做都在localhost上(localhost失敗時,後端直接失敗)
                        2.balance=1時,讀操做會隨機分散在localhost1和兩個readhost上面(localhost失敗時,寫操做會在localhost1,若是localhost1再失敗,則沒法進行寫操做)
                        3.balance=2時,寫操做會在localhost上,讀操做會隨機分散在localhost1,localhost1和兩個readhost上面(同上)
                        4.writeType=0時,寫操做會在localhost上,若是localhost失敗,會自動切換到localhost1,localhost恢復之後並不會切換回localhost進行寫操做
                        5.writeType=1時,寫操做會隨機分佈在localhost和localhost1上,單點失敗並不會影響集羣的寫操做,可是後端的從庫會沒法從掛掉的主庫獲取更新,會在讀數據的時候出現數據不一致
                                舉例:localhost失敗了,寫操做會在localhost1上面進行,localhost1的主從正常運行,可是localhost的從庫沒法從localhost獲取更新,localhost的從庫於其餘庫出現數據不一致

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                實際上,MyCAT自己的讀寫分離是基於後端集羣的同步來實現的,而MyCAT自己則提供語句的分發功能,固然,那個sqlLimit的限制也使得MyCAT會對前端應用層的邏輯形成一些影響
                由schema到table的配置,則顯示出MyCAT自己的邏輯結構裏面,就包含了分庫分表的這種特性(能夠指定不一樣的表存在於不一樣的數據庫中,而沒必要分到所有數據庫)
                下一章將會介紹server和rule的一些細節
 
首先寫在最前面,MyCAT1.4的alpha版本已經發布了,這裏面修復了很多的bug,也完善了一細節,以前兩篇博客已經作了一些修改

---------------------------------------------------------------------------------這纔是本體~----------------------------------------------------------------------------------
            以前已經介紹過了schema的做用了,這一篇會把rule和server一塊兒介紹~
            首先是rule,在這個文件裏面會詳細的制定多種分片的規則,此次只抽出一些使用率比較高的方法,先上配置文件的內容
         
            能夠簡單看一下,在截圖的上半部分描述的是rule的定義,在下半部分,是rule對應的實際切分規則,這裏總工介紹下面四種切分方式~murmur已坑~
-------------------------------------------------------------------------------------------Hash-int---------------------------------------------------------------------------------
            先看hash-int,在這一條切分規則的下面,有一個mapfile,這表明着,這個切分規則是根據partition-hash-int的內容來決定的,那麼看一下這個文本文件
         
            很簡單的內容,這表明着切分使用的基準列裏面,值爲10000的時候,放在第一個DN裏面(dn1),值爲10010的時候,放在第二個DN裏面(dn2)
            能夠看一下實際效果
         
         
            看一下MyCAT的Debug日誌,這兩條語句被分配到了dn1和dn2上面,數據庫裏面也插入了相對應的數據
         
            那麼~問題來了(挖掘機滾粗~),若是插入的數據中,基準列的取值不是這個文件裏面寫明的值,會是什麼效果?
         
            直截了當的報錯了~

            好了,hash-int的這種切分規則,大致上能夠理解爲枚舉分區,會比較適合於取值固定的場合,好比說性別(0,1),省份(固定值,短期不會收復日本省吧~),渠道商 or 各類平臺的ID
            並且,用逗號分隔能夠把多個值放在一個分區裏面,因此能夠根據實際的數據量/流量/訪問量來綜合制定切分策略;
            缺點:畢竟不是全能戰士╮(╯_╰)╭

-------------------------------------------------------------------------------------------range-long---------------------------------------------------------------------------------
            第二種切分方式,range-long,仔細一看的話,和hash-int是比較像的,也是由特定的文件來決定切分策略,因此仍是去看一下文件的內容
         
            從文件內容能夠看出,這是一種範圍切分的方式,制定基準列的取值範圍,而後把這一範圍的全部數據都放到一個DN上面,這種方式和hash-int基本一致,就不截圖了(懶癌晚期,時間不夠了!)
            這種切分策略,我的感受在業務數據庫裏面的使用場景會少一些,由於這種切分方式須要預約好總體的數量,這就決定了那種無限增加的數據不能用這個,畢竟要改動這個切分策略會很麻煩
            真要用起來,感受也就對自增主鍵用,而後按照必定的數量來均勻切分,好比那種一天固定X條數據的業務(溫度採集?數據採集?之類的狀況),而後提早建好多個DN(庫)。
            固然,也存在一種潛在的問題,若是在短期發生海量的順序插入操做,而每個DN(分庫)設定的數量比較高(好比說一個DN設定的放1000W條數據),那麼在這個時候,會出現某一個DN(分庫)IO壓力很是高,而其餘幾個DN(分庫)徹底沒有IO操做,就會出現相似於DB中常見的熱塊/熱盤的現象,而MySQL常常用自增主鍵,因此使得MySQL的表出現大量「順序」插入的機會會多不少。
--------------------------------------------------------------------------------------------mod-long-----------------------------------------------------------------------------------
            mod-long,從mod來看這應該是一種取餘數的方法,來看一下具體配置的信息
         
            count=4,這是表明着總共把數據切分紅四份,通常是和具體的DN數量對應,從而達到把數據均勻的分佈在四個DN上(固然,count<dn數量也沒什麼問題)
             看一下實際的效果
         
            看一下MyCAT的Debug日誌,看看MyCAT是如何處理的
         
            採用這種取餘數的方式時,這四條數據分別插入了四個DN(庫),並且能夠看到,順序插入時,數據是被均勻的分散在多個DN(庫)上面
            相比較於上面的range的方法,這種切分策略會更好的分散數據庫寫的壓力,可是問題也很明顯,一旦出現了範圍查詢,就須要MyCAT去合併結果,當數據量偏高的時候,這種跨庫查詢+合併結果消耗的時間有可能會增長不少,尤爲是還出現了order by的時候。
            因此這種切分策略會比較適合於單點查詢的情景,好比說.....我也不知道......真的不知道,也許在銀行,查詢我的帳戶信息的時候,一些和用戶信息的表能夠作好冗餘,而後利用這種方式來提供更爲高效的查詢(畢竟銀行的用戶數量多,恩恩~)

--------------------------------------------------------------------------------partition-by-long----------------------------------------------------------------------------------
            partition-by-long,處於range-long和mod-long之間的一個略微折中的劃分策略,具體切分形勢依照以下描述:
            以1024爲一個單位,每一個DN存放partitionLength數量的數據,且,partitionCount x partitionLength=1024
            看起來有點難以理解,形象點描述的話,以partitionCount(4) x partitionLength(256)爲例,sid%1024=0-255的放在DN1,256-511的放在DN2,以此類推
            試着以128爲偏移值插入了八條數據,直接看MyCAT的日誌
         
            能夠看到,八條數據均勻的分佈在這四個DN裏面~
            值得一提的是,這種切分策略也支持非均勻分佈~實在是測不動了,盜圖兩張~
          
          
            這兩張圖基本上也說明白了這種非均勻分佈的劃分策略,重點仍是在2x256+1x512=1024上面~
            這種劃分策略在range-long和mod-long之間取了一個折中點,同時,也還算是比較靈活,能夠根據不一樣的狀況進行非均勻劃分,實際上能應用的場景會稍微多一點吧,或者說,很多場景都能用一用,相對減小了跨DN的情形,又把數據比較均勻的切分開來了,單點查詢也不會太慢。

-----------------------------------------------------------------------------------寫在最後-------------------------------------------------------------------------------------
            其實MyCAT支持的切分方式還有很多,好比說按照時間的切分策略,能夠按月,按天切分等,在這裏也沒辦法把全部的策略都放上來,見諒了o( ̄ヘ ̄o#)
            實際上從我的的觀點來看,時間的切分依照數據庫自己的分區策略來分也沒什麼問題,半年度,季度的數據也仍是會須要查詢的....PS:   _(:з」∠)_真不是懶...
            能夠說,MyCAT的分庫分表的重點,基本所有在這個rule裏面體現了,表要不要分,表的數據怎麼切分,都是須要根據實際業務來決定,充分根據業務的特色去決定最合適的劃分策略~
 
背景:接本應接在基準測試以後就整理,不過有別的事情耽擱了

環境:與基準測試時保持一致,4核32G,MyCAT-1.4-RC,6月17號發佈的版本,目前最新發布的版本應該是在7.29,七月底的樣子。

相關配置文件:server.xml與cacheservice.properties

文件簡介:
server.xml:保存了有關MyCAT的配置信息,包括MyCAT對外暴露的schema(包含這個schema對應的帳戶名和密碼),MyCAT server的鏈接池等參數配置
cacheservice.properties:緩存區的配置

server.xml示例:

點擊(此處)摺疊或打開

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 
  3.         - you may not use this file except in compliance with the License. - You 
  4.         may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 
  5.         - - Unless required by applicable law or agreed to in writing, software - 
  6.         distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 
  7.         WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 
  8.         License for the specific language governing permissions and - limitations 
  9.         under the License. -->
  10. <!DOCTYPE mycat:server SYSTEM "server.dtd">
  11. <mycat:server xmlns:mycat="http://org.opencloudb/">
  12.         <system> 
  13.         <property name="processors">32</property> 
  14.         <property name="processorExecutor">256</property> 
  15.         <property name="processorBufferPool">204800000</property>
  16.         <property name="processorBufferChunk">40960</property>
  17.                 <!--默認是65535 64K 用於sql解析時最大文本長度 -->
  18.         <property name="maxStringLiteralLength">65535</property>
  19.                 <!--<property name="sequnceHandlerType">0</property>-->
  20.                 <!--<property name="backSocketNoDelay">1</property>-->
  21.                 <!--<property name="frontSocketNoDelay">1</property>-->
  22.                 <!--<property name="processorExecutor">16</property>-->
  23.                 <!-- 
  24.                         <property name="mutiNodeLimitType">1</property> 0:開啓小數量級(默認) ;1:開啓億級數據排序
  25.                         <property name="mutiNodePatchSize">100</property> 億級數量排序批量
  26.                         <property name="processors">32</property> <property name="processorExecutor">32</property> 
  27.                         <property name="serverPort">8066</property> <property name="managerPort">9066</property> 
  28.                         <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> 
  29.                         <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
  30.         <property name="defaultSqlParser">druidparser</property>
  31.         </system>
  32.         <!--
  33.         <user name="root">
  34.                 <property name="password">root</property>
  35.                 <property name="schemas">test</property>
  36.         </user>
  37.         <user name="root_read">
  38.                 <property name="password">root_read</property>
  39.                 <property name="schemas">test</property>
  40.                 <property name="readOnly">true</property>
  41.         </user>
  42.         -->
  43.         <user name="test">
  44.                 <property name="password">test</property>
  45.                 <property name="schemas">test</property>
  46.         </user>
  47.         <!-- <cluster> <node name="cobar1"> <property name="host">127.0.0.1</property> 
  48.                 <property name="weight">1</property> </node> </cluster> -->
  49.         <!-- <quarantine> <host name="1.2.3.4"> <property name="user">test</property> 
  50.                 </host> </quarantine> -->
  51. </mycat:server>
PS:MyCAT對外暴露的schema,是可使用readonly模式的,如上面配置文件中的加紅部分;

processors:用於指定可用線程數,實際上因爲如今的多核CPU和超線程技術,這個值能夠酌情調高,這裏調到了虛擬機核數的 八倍,感受稍稍有點高了,實際上 四倍or 五倍就差很少了

processorExecutor:相似於線程池大小的參數,酌情修改便可,在1.4以後,這個線程池是用來作異步處理邏輯的時候用的,對併發能力的影響相對較小了

processorBufferPool:BufferPool的大小,原則上來講,調高一些會比較好

processorBufferChunk:每個Buffer塊的大小,processorBufferPool/processorBufferChun能夠獲得buffer塊的數量

server調整總結:
processors+processorExecutor會影響到MyCAT可用的線程數,雖然調高點會比較好,可是調的過高會致使頻繁的上下文切換和軟中斷,在實際調整中,用top觀察sys和si的百分比,若是服務器/虛擬機並無什麼不乾淨的後臺程序和其餘的服務在運行, sys在10%-15%以內,si在5%以內是比較理想的狀態

processorBufferPool+processorBufferChunk影響的server緩存,保持processorBufferChunk大小合理的狀況下, 增長buffer塊的數量纔是關鍵


cacheservice.properties示例:

點擊(此處)摺疊或打開

  1. #used for mycat cache service conf
  2. factory.encache=org.opencloudb.cache.impl.EnchachePooFactory
  3. #key is pool name ,value is type,max size, expire seconds
  4. pool.SQLRouteCache=encache,1500000,60
  5. pool.ER_SQL2PARENTID=encache,2000,180
  6. layedpool.TableID2DataNodeCache=encache,3000,18000
  7. layedpool.TableID2DataNodeCache.TESTDB_ORDERS=10000,18000
cacheservice是SQL的緩存服務,

SQLRouteCache:sql路由緩存,經過緩存SQL語句的路由信息,下次查詢,不用再路由了,直接從緩存中獲取路由信息,而後發到各個節點執行;
TableID2DataNodeCache :表主鍵ID的路由緩存,爲每個表建一個緩存池,命名爲TableID2DataNodeCache.TESTDB_表名,緩存的key是id的值,value是節點名;
ER_SQL2PARENTID : ER關係的緩存目前只是在Insert語句中才會使用緩存,子表插入數據的時候,根據joinKey的值,判斷父表所在分片,從而定位子表分片,分片信息put緩存,以便下次直接獲取

因爲在測試的時候並無對測試表是簡單的區域劃分,因此在測試中對後兩個緩存是沒有利用到的,具體對緩存大小的調整能夠參考SQLRouteCache;

首先貼出結論:SQLRouteCache的大小對具體的QPS有比較大的影響(廢話......._(:з」∠)_),在實際的測試過程當中,保持線程併發不變的狀況下,從100W-300W都有調整過,大概每增長50W,有約15%的增長,直觀來看的話,從100W-300W的增長過程當中,128線程,5張表x5000W行/表的狀況下,QPS範圍從1W5-2W5, 然而有一個問題很重要,當這個值增長到比較高後,會頻繁出現極高的sys佔用率,同時vmstat命令下,proc列會有很是高的r和b,直接後果就是 MyCAT server自己會出現劇烈的性能波動 ,在基準測試中,QPS的低谷會降到3000-4000;可是free查看內存使用的時候,並無出現內存不足的狀況,推斷爲MyCAT自己的緩存設計中存在不完善的地方;

具體的設置值,在不斷的測試中, 以以前的虛擬機的配置(4核,32G )爲參考 ,當 SQLRouteCache 的值設置到180W以上的時候,就會不定時的出現性能波動,爲了保證穩定運行,在基準測試時採用了較低的150W

PS:因爲基準測試的時候,SQL語句模板裏面的參數都是 採用隨機值,因此緩存的命中率是偏低的(150W的設置下,大約只有 25%的命中率),生產環境下, 這個命中率會高不少,同時QPS也會有必定程度的上升
PPS:這個routeCache和MySQL的queryCache比較像,緩存的都是具體的SQL語句,而不是框架裏面的帶?佔位符的語句,queryCache的信息能夠參考http://blog.itpub.net/29510932/viewspace-1694922/
 
 
來源:http://blog.itpub.net/29510932/
相關文章
相關標籤/搜索