現在隨着互聯網的發展,數據的量級也是成指數的增加,從GB到TB到PB。對數據的各類操做也是越發的困難,傳統的關係型數據庫已經沒法知足快速查詢與插入數據的需求。這個時候NoSQL的出現暫時解決了這一危機。它經過下降數據的安全性,減小對事務的支持,減小對複雜查詢的支持,來獲取性能上的提高。node
可是,在有些場合NoSQL一些折衷是沒法知足使用場景的,就好比有些使用場景是絕對要有事務與安全指標的。這個時候NoSQL確定是沒法知足的,因此仍是須要使用關係型數據庫。如何使用關係型數據庫解決海量存儲的問題呢?此時就須要作數據庫集羣,爲了提升查詢性能將一個數據庫的數據分散到不一樣的數據庫中存儲。mysql
Mycat 背後是阿里曾經開源的知名產品——Cobar。Cobar 的核心功能和優點是 MySQL 數據庫分片,此產品曾經廣爲流傳,聽說最先的發起者對 Mysql 很精通,後來從阿里跳槽了,阿里隨後開源的 Cobar,並維持到 2013 年年初,而後,就沒有而後了。linux
Cobar 的思路和實現路徑的確不錯。基於 Java 開發的,實現了 MySQL 公開的二進制傳輸協議,巧妙地將本身假裝成一個 MySQL Server,目前市面上絕大多數 MySQL 客戶端工具和應用都能兼容。比本身實現一個新的數據庫協議要明智的多,由於生態環境在哪裏擺着。git
Mycat 是基於 cobar 演變而來,對 cobar 的代碼進行了完全的重構,使用 NIO 重構了網絡模塊,而且優化了 Buffer 內核,加強了聚合,Join 等基本特性,同時兼容絕大多數數據庫成爲通用的數據庫中間件。github
簡單的說,MyCAT就是:一個新穎的數據庫中間件產品,支持mysql集羣,或者mariadb cluster,提供高可用性數據分片集羣。你能夠像使用mysql同樣使用mycat。對於開發人員來講根本感受不到mycat的存在。算法
MyCat支持的數據庫:sql
使用mycat以前確定要使用mysql(具體哪一個數據庫無所謂,只要是mycat支持的就行)簡單的說一下Linux下mysql的安裝:數據庫
安裝要求:安全
JDK:要求jdk必須是1.7及以上版本服務器
MySQL:推薦mysql是5.5以上版本
安裝與啓動步驟以下:
(1)將MySQL的服務端和客戶端安裝包(RPM)上傳到服務器
(2)查詢以前是否安裝過MySQL
rpm -qa|grep -i mysql
(3)卸載舊版本MySQL
rpm -e --nodeps 軟件名稱
(4)安裝服務端
rpm -ivh MySQL-server-5.5.49-1.linux2.6.i386.rpm
(5)安裝客戶端
rpm -ivh MySQL-client-5.5.49-1.linux2.6.i386.rpm
(6)啓動MySQL服務
service mysql start
(7)登陸MySQL (記得設置mysql登陸密碼,此處不做詳細介紹!)
mysql -u root -proot
(8)設置遠程登陸權限
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY 'root' WITH GRANT OPTION;
在本地SQLyog 鏈接遠程MySQL進行測試
接下來的工做就是咱們的重頭戲mycat了,首先固然仍是從mycat的安裝提及了。
mycat的官方網站:http://www.mycat.org.cn/
下載地址①:https://github.com/MyCATApache/Mycat-download
下載地址②:http://dl.mycat.io/
下載好了以後開始正式安裝:
第一步:將Mycat-server-1.4-release-20151019230038-linux.tar.gz上傳至服務器
第二步:將壓縮包解壓縮。建議將mycat放到/usr/local/mycat目錄下。
tar -xzvf Mycat-server-1.4-release-20151019230038-linux.tar.gz mv mycat /usr/local
第三步:進入mycat目錄的bin目錄,啓動mycat
./mycat start
中止mycat:
./mycat stop
mycat 支持的命令{ console | start | stop | restart | status | dump }
Mycat的默認端口號爲:8066
此時咱們已經成功的安裝好了mycat了,這以前先不用着急怎麼去用mycat,咱們須要知道怎麼用mycat分片解決海量數據存儲方案的。
首先來講說什麼是分片?
簡單來講,就是指經過某種特定的條件,將咱們存放在同一個數據庫中的數據分散存放到多個數據庫(主機)上面,以達到分散單臺設備負載的效果。數據的切分(Sharding)根據其切分規則的類型,能夠分爲兩種切分模式。
(1)一種是按照不一樣的表(或者Schema)來切分到不一樣的數據庫(主機)之上,這種切分能夠稱之爲數據的垂直(縱向)切分
(2)另一種則是根據表中的數據的邏輯關係,將同一個表中的數據按照某種條件拆分到多臺數據庫(主機)上面,這種切分稱之爲數據的水平(橫向)切分。
MyCat分片策略:
分片相關的概念:
邏輯庫(schema) :前面講了數據庫中間件,一般對實際應用來講,並不須要知道中間件的存在,業務開發人員只須要知道數據庫的概念,因此數據庫中間件能夠被看作是一個或多個數據庫集羣構成的邏輯庫。
邏輯表(table):既然有邏輯庫,那麼就會有邏輯表,分佈式數據庫中,對應用來講,讀寫數據的表就是邏輯表。邏輯表,能夠是數據切分後,分佈在一個或多個分片庫中,也能夠不作數據切分,不分片,只有一個表構成。
分片表:是指那些原有的很大數據的表,須要切分到多個數據庫的表,這樣,每一個分片都有一部分數據,全部分片構成了完整的數據。 總而言之就是須要進行分片的表。
非分片表:一個數據庫中並非全部的表都很大,某些表是能夠不用進行切分的,非分片是相對分片表來講的,就是那些不須要進行數據切分的表。
分片節點(dataNode):數據切分後,一個大表被分到不一樣的分片數據庫上面,每一個表分片所在的數據庫就是分片節點(dataNode)。
節點主機(dataHost) :數據切分後,每一個分片節點(dataNode)不必定都會獨佔一臺機器,同一機器上面能夠有多個分片數據庫,這樣一個或多個分片節點(dataNode)所在的機器就是節點主機(dataHost),爲了規避單節點主機併發數限制,儘可能將讀寫壓力高的分片節點(dataNode)均衡的放在不一樣的節點主機(dataHost)。
分片規則(rule) :前面講了數據切分,一個大表被分紅若干個分片表,就須要必定的規則,這樣按照某種業務規則把數據分到某個分片的規則就是分片規則,數據切分選擇合適的分片規則很是重要,將極大的避免後續數據處理的難度。
(1)配置schema.xml
schema.xml做爲MyCat中重要的配置文件之一,管理着MyCat的邏輯庫、邏輯表以及對應的分片規則、DataNode以及DataSource。弄懂這些配置,是正確使用MyCat的前提。這裏就一層層對該文件進行解析。
schema 標籤用於定義MyCat實例中的邏輯庫
Table 標籤訂義了MyCat中的邏輯表 rule用於指定分片規則,auto-sharding-long的分片規則是按ID值的範圍進行分片 1-5000000 爲第1片 5000001-10000000 爲第2片....
dataNode 標籤訂義了MyCat中的數據節點,也就是咱們一般說所的數據分片。
dataHost標籤在mycat邏輯庫中也是做爲最底層的標籤存在,直接定義了具體的數據庫實例、讀寫分離配置和心跳語句。
在服務器上建立3個數據庫,分別是db1 db2 db3
修改schema.xml以下:
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://org.opencloudb/"> <schema name="PINYOUGOUDB" checkSQLschema="false" sqlMaxLimit="100"> <table name="tb_test" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> </schema> <dataNode name="dn1" dataHost="localhost1" database="db1" /> <dataNode name="dn2" dataHost="localhost1" database="db2" /> <dataNode name="dn3" dataHost="localhost1" 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> <writeHost host="hostM1" url="192.168.25.142:3306" user="root" password="root"> </writeHost> </dataHost> </mycat:schema>
(2)配置 server.xml
server.xml幾乎保存了全部mycat須要的系統配置信息。最經常使用的是在此配置用戶名、密碼及權限。在system中添加UTF-8字符集設置,不然存儲中文會出現問號
<property name="charset">utf8</property>
修改user的設置 , 咱們這裏爲 PINYOUGOUDB設置了兩個用戶
<user name="test"> <property name="password">test</property> <property name="schemas">PINYOUGOUDB</property> </user> <user name="root"> <property name="password">123456</property> <property name="schemas">PINYOUGOUDB</property> </user>
MyCat分片測試:
進入mycat ,執行下列語句建立一個表:
CREATE TABLE tb_test ( id BIGINT(20) NOT NULL, title VARCHAR(100) NOT NULL , PRIMARY KEY (id) ) ENGINE=INNODB DEFAULT CHARSET=utf8
建立後你會發現,MyCat會自動將你的錶轉換爲大寫,這一點與Oracle有些相似。
咱們再查看MySQL的3個庫,發現表都自動建立好啦。好神奇。
接下來是插入表數據,注意,在寫INSERT語句時必定要寫把字段列表寫出來,不然會出現下列錯誤提示:
錯誤代碼: 1064
partition table, insert must provide ColumnList
咱們試着插入一些數據:
INSERT INTO TB_TEST(ID,TITLE) VALUES(1,'goods1'); INSERT INTO TB_TEST(ID,TITLE) VALUES(2,'goods2'); INSERT INTO TB_TEST(ID,TITLE) VALUES(3,'goods3');
咱們會發現這些數據被寫入到第一個節點中了,那何時數據會寫到第二個節點中呢?
咱們插入下面的數據就能夠插入第二個節點了
INSERT INTO TB_TEST(ID,TITLE) VALUES(5000001,'goods5000001');
由於咱們採用的分片規則是每節點存儲500萬條數據,因此當ID大於5000000則會存儲到第二個節點上。
目前只設置了兩個節點,若是數據大於1000萬條,會怎麼樣呢?執行下列語句測試一下
INSERT INTO TB_TEST(ID,TITLE) VALUES(10000001,'goods10000001');
rule.xml用於定義分片規則 ,咱們這裏講解兩種最多見的分片規則
(1)按主鍵範圍分片rang-long
在配置文件中咱們找到
<tableRule name="auto-sharding-long"> <rule> <columns>id</columns> <algorithm>rang-long</algorithm> </rule> </tableRule>
tableRule 是定義具體某個表或某一類表的分片規則名稱 columns用於定義分片的列 algorithm表明算法名稱 咱們接着找rang-long的定義
<function name="rang-long" class="org.opencloudb.route.function.AutoPartitionByLong"> <property name="mapFile">autopartition-long.txt</property> </function>
Function用於定義算法 mapFile 用於定義算法須要的數據,咱們打開autopartition-long.txt
# range start-end ,data node index # K=1000,M=10000. 0-500M=0 500M-1000M=1 1000M-1500M=2
(2)一致性哈希murmur
當咱們須要將數據平均分在幾個分區中,須要使用一致性hash規則
咱們找到function的name爲murmur 的定義,將count屬性改成3,由於我要將數據分紅3片
<function name="murmur" class="org.opencloudb.route.function.PartitionByMurmurHash"> <property name="seed">0</property><!-- 默認是0 --> <property name="count">3</property><!-- 要分片的數據庫節點數量,必須指定,不然無法分片 --> <property name="virtualBucketTimes">160</property><!-- 一個實際的數據庫節點被映射爲這麼多虛擬節點,默認是160倍,也就是虛擬節點數是物理節點數的160倍 --> <!-- <property name="weightMapFile">weightMapFile</property> 節點的權重,沒有指定權重的節點默認是1。以properties文件的格式填寫,
以從0開始到count-1的整數值也就是節點索引爲key,以節點權重值爲值。全部權重值必須是正整數,不然以1代替 --> <!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property> 用於測試時觀察各物理節點與虛擬節點的分佈狀況,若是指定了這個屬性,會把虛擬節點的murmur hash值與物理節點的映射按行輸出到這個文件,沒有默認值,若是不指定,就不會輸出任何東西 --> </function>
咱們再配置文件中能夠找到表規則定義
<tableRule name="sharding-by-murmur"> <rule> <columns>id</columns> <algorithm>murmur</algorithm> </rule> </tableRule>
可是這個規則指定的列是id ,若是咱們的表主鍵不是id ,而是order_id ,那麼咱們應該從新定義一個tableRule:
<tableRule name="sharding-by-murmur-order"> <rule> <columns>order_id</columns> <algorithm>murmur</algorithm> </rule> </tableRule>
在schema.xml中配置邏輯表時,指定規則爲sharding-by-murmur-order
<table name="tb_order" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur-order" />
咱們測試一下,建立訂單表 ,並插入數據,測試分片效果。