阿里開源Mysql分散式中介軟體:Cobar

hai0808發表於2017-11-14

  這幾天研究了下Cobar, Cobar是阿里巴巴研發的關係型資料的分散式處理系統(Amoeba的升級版,該產品成功替代了原先基於Oracle的資料儲存方案,目前已經接管了3000+個MySQL資料庫的schema,平均每天處理近50億次的SQL執行請求。)(github上面的是原始碼,大家下來需要自己用maven2編譯後執行、者放Eclipse裡面執行,一開始我用maven3沒有執行成功。)

首先,使用Cobar的核心功能如下:

分散式:

Cobar的分散式主要是通過將表放入不同的庫來實現:
1. Cobar支援將一張表水平拆分成多份分別放入不同的庫來實現表的水平拆分
2. Cobar也支援將不同的表放入不同的庫
3. 多數情況下,使用者會將以上兩種方式混合使用
這裡需要強調的是,Cobar不支援將一張表,例如test表拆分成test_1, test_2, test_3.....放在同一個庫中,必須將拆分後的表分別放入不同的庫來實現分散式。

HA:
在使用者配置了MySQL心跳的情況下,Cobar可以自動向後端連線的MySQL傳送心跳,判斷MySQL執行狀況,一旦執行出現異常,Cobar可以自動切換到備機工作。但需要強調的是:
1. Cobar的主備切換有兩種觸發方式,一種是使用者手動觸發,一種是Cobar的心跳語句檢測到異常後自動觸發。那麼,當心跳檢測到主機異常,切換到備機,如果主機恢復了,需要使用者手動切回主機工作,Cobar不會在主機恢復時自動切換回主機,除非備機的心跳也返回異常。
2. Cobar只檢查MySQL主備異常,不關心主備之間的資料同步,因此使用者需要在使用Cobar之前在MySQL主備上配置雙向同步,詳情可以參閱MySQL參考手冊。

其次,我們也需要注意Cobar的功能約束:

1) 不支援跨庫情況下的join、分頁、排序、子查詢操作。
2) SET語句執行會被忽略,事務和字符集設定除外。
3) 分庫情況下,insert語句必須包含拆分欄位列名。
4) 分庫情況下,update語句不能更新拆分欄位的值。
5) 不支援SAVEPOINT操作。
6) 暫時只支援MySQL資料節點。
7) 使用JDBC時,不支援rewriteBatchedStatements=true引數設定(預設為false)。
8) 使用JDBC時,不支援useServerPrepStmts=true引數設定(預設為false)。
9) 使用JDBC時,BLOB, BINARY, VARBINARY欄位不能使用setBlob()或setBinaryStream()方法設定引數。

然後,我們來分析一下Cobar邏輯層次圖:


 
* dataSource:資料來源,表示一個具體的資料庫連線,與物理存在的資料庫schema一一對應。
* dataNode:資料節點,由主、備資料來源,資料來源的HA以及連線池共同組成,可以將一個dataNode理解為一個分庫。
* table:表,包括拆分表(如tb1,tb2)和非拆分表。
* tableRule:路由規則,用於判斷SQL語句被路由到具體哪些datanode執行。
* schema:cobar可以定義包含拆分表的schema(如schema1),也可以定義無拆分表的schema(如schema2)。

Cobar支援的資料庫結構(schema)的層次關係具有較強的靈活性,使用者可以將表自由放置不同的datanode,也可將不同的datasource放置在同一MySQL例項上。在實際應用中,我們需要通過配置檔案(schema.xml)來定義我們需要的資料庫伺服器和表的分佈策略,這點我們將在後面的安裝和配置部分中介紹到。

接著,我們來介紹Cobar的安裝和配置步驟:

下面我們將使用一個最簡單的分庫分表的例子來說明Cobar的基本用法,資料庫schema如下圖(該例項也可參考:Cobar產品首頁)。


 
1) 系統對外提供的資料庫名是dbtest,並且其中有兩張表tb1和tb2。
2) tb1表的資料被對映到物理資料庫dbtest1的tb1上。
3) tb2表的一部分資料被對映到物理資料庫dbtest2的tb2上,另外一部分資料被對映到物理資料庫dbtest3的tb2上。

1、環境準備

作業系統:Linux或者Windows (推薦在Linux環境下執行Cobar)
MySQL:http://www.mysql.com/downloads/ (推薦使用5.1以上版本)
JDK:http://www.oracle.com/technetwork/java/javase/downloads/ (推薦使用1.6以上版本)
Cobar:https://github.com/alibaba/cobar (下載tar.gz或者zip檔案,特意說明下,阿里的開源全部移到github上去了,裡面有很多阿里人的作品,當然包含著名的dubbo,地址是:https://github.com/alibaba/)

2、資料準備

假設本文MySQL所在伺服器IP為192.168.0.1,埠為3306,使用者名稱為test,密碼為空,我們需要建立schema:dbtest1、dbtest2、dbtest3,table:tb1、tb2,SQL如下:

[sql] view plaincopy

1.  #建立dbtest1  

2.  drop database if exists dbtest1;  

3.  create database dbtest1;  

4.  use dbtest1;  

5.  #在dbtest1上建立tb1  

6.  create table tb1(  

7.  id    int not null,  

8.  gmt   datetime);  

9.     

10.#建立dbtest2  

11.drop database if exists dbtest2;  

12.create database dbtest2;  

13.use dbtest2;  

14.#在dbtest2上建立tb2  

15.create table tb2(  

16.id    int not null,  

17.val   varchar(256));  

18.   

19.#建立dbtest3  

20.drop database if exists dbtest3;  

21.create database dbtest3;  

22.use dbtest3;  

23.#在dbtest3上建立tb2  

24.create table tb2(  

25.id    int not null,  

26.val   varchar(256));  


3、配置Cobar

Cobar解壓之後有四個目錄:
bin/:可執行檔案目錄,包含啟動(start)、關閉(shutdown)和重啟(restart)指令碼
lib/:邏輯類庫目錄,包含了Cobar所需的jar包
conf/:配置檔案目錄,下面會詳細介紹
logs/:執行日誌目錄,最主要的log有兩個:程式日誌(stdout.log)和控制檯輸出(console.log)

配置檔案的用法如下:
log4j.xml:日誌配置,一般來說保持預設即可
schema.xml:定義了schema邏輯層次圖中的所有元素,並利用這些元素以及rule.xml中定義的規則組建分散式資料庫系統
rule.xml:定義了分庫分表的規則
server.xml:系統配置檔案

我們在schema.xml中配置資料庫結構(schema)、資料節點(dataNode)、以及資料來源(dataSource)。

[html] view plaincopy

1.  <?xml version="1.0" encoding="UTF-8"?>  

2.  <!DOCTYPE cobar:schema SYSTEM "schema.dtd">  

3.  <cobar:schema xmlns:cobar="http://cobar.alibaba.com/">  

4.     

5.    <!-- schema定義 -->  

6.    <schema name="dbtest" dataNode="dnTest1">  

7.      <table name="tb2" dataNode="dnTest2,dnTest3" rule="rule1" />  

8.    </schema>  

9.     

10.  <!-- 資料節點定義,資料節點由資料來源和其他一些引數組織而成。-->  

11.  <dataNode name="dnTest1">  

12.    <property name="dataSource">  

13.      <dataSourceRef>dsTest[0]</dataSourceRef>  

14.    </property>  

15.  </dataNode>  

16.  <dataNode name="dnTest2">  

17.    <property name="dataSource">  

18.      <dataSourceRef>dsTest[1]</dataSourceRef>  

19.    </property>  

20.  </dataNode>  

21.  <dataNode name="dnTest3">  

22.    <property name="dataSource">  

23.      <dataSourceRef>dsTest[2]</dataSourceRef>  

24.    </property>  

25.  </dataNode>  

26.   

27.  <!-- 資料來源定義,資料來源是一個具體的後端資料連線的表示。-->  

28.  <dataSource name="dsTest" type="mysql">  

29.    <property name="location">  

30.      <location>192.168.0.1:3306/dbtest1</location> <!--注意:替換為您的MySQL IPPort-->  

31.      <location>192.168.0.1:3306/dbtest2</location> <!--注意:替換為您的MySQL IPPort-->  

32.      <location>192.168.0.1:3306/dbtest3</location> <!--注意:替換為您的MySQL IPPort-->  

33.    </property>  

34.    <property name="user">test</property> <!--注意:替換為您的MySQL使用者名稱-->  

35.    <property name="password">test</property> <!--注意:替換為您的MySQL密碼-->  

36.    <property name="sqlMode">STRICT_TRANS_TABLES</property>  

37.  </dataSource>  

38.</cobar:schema>  

我們注意到,上述配置實際上已經把圖2中的資料庫結構配置好了。dbtest主要對映的是dnTest1庫(即192.168.0.1:3306/dbtest1庫),而其中的tb2表則是按照規則rule1,被分配到dnTest2庫(即192.168.0.1:3306/dbtest2庫)和dnTest3庫(即192.168.0.1:3306/dbtest3庫)中。此外,規則rule1的定義可以在rule.xml中找到,程式碼如下:

[html] view plaincopy

1.  <?xml version="1.0" encoding="UTF-8"?>  

2.  <!DOCTYPE cobar:rule SYSTEM "rule.dtd">  

3.  <cobar:rule xmlns:cobar="http://cobar.alibaba.com/">  

4.    

5.    <!-- 路由規則定義,定義什麼表,什麼欄位,採用什麼路由演算法。-->  

6.    <tableRule name="rule1">  

7.      <rule>  

8.        <columns>id</columns>  

9.        <algorithm><![CDATA[ func1(${id})]]></algorithm>  

10.    </rule>  

11.  </tableRule>  

12.  

13.  <!-- 路由函式定義,應用在路由規則的演算法定義中,路由函式可以自定義擴充套件。-->  

14.  <function name="func1" class="com.alibaba.cobar.route.function.PartitionByLong">  

15.    <property name="partitionCount">2</property>  

16.    <property name="partitionLength">512</property>  

17.  </function>  

18.</cobar:rule>  

結合schema.xml中的內容,我們可以看出分表的規則是,按照id欄位把tb2表中的資料分配到dnTest2和dnTest3兩個分割槽中,其中id小於512的資料會被放到dnTest2庫的分割槽中,而其餘的會被放到dnTest3庫的分割槽中,更多路由演算法可以參考《路由文件》。最後,我們來看一下server.xml的配置,程式碼如下。

[html] view plaincopy

1.  <?xml version="1.0" encoding="UTF-8"?>  

2.  <!DOCTYPE cobar:server SYSTEM "server.dtd">  

3.  <cobar:server xmlns:cobar="http://cobar.alibaba.com/">  

4.     

5.    <!--定義Cobar使用者名稱,密碼-->  

6.    <user name="root">  

7.      <property name="password">passwd</property>  

8.      <property name="schemas">dbtest</property>  

9.    </user>  

10.</cobar:server>  

這裡的server.xml配置比較簡單,只配置了本地Cobar服務的資料庫結構、使用者名稱和密碼。在啟動Cobar服務之後,使用使用者名稱root和密碼passwd就可以登入Cobar服務。

4、執行Cobar

啟動Cobar服務很簡單,運用bin目錄下的start.sh即可(停止使用shutdown.sh)。啟動成功之後,可以在logs目錄下的stdout.log中看到如下日誌:

[html] view plaincopy

1.  10:54:19,264 INFO  ===============================================  

2.  10:54:19,265 INFO  Cobar is ready to startup ...  

3.  10:54:19,265 INFO  Startup processors ...  

4.  10:54:19,443 INFO  Startup connector ...  

5.  10:54:19,446 INFO  Initialize dataNodes ...  

6.  10:54:19,470 INFO  dnTest1:0 init success  

7.  10:54:19,472 INFO  dnTest3:0 init success  

8.  10:54:19,473 INFO  dnTest2:0 init success  

9.  10:54:19,481 INFO  CobarManager is started and listening on 9066  

10.10:54:19,483 INFO  CobarServer is started and listening on 8066  

11.10:54:19,484 INFO  ===============================================  


接著,我們就可以使用“mysql -h127.0.0.1 -uroot -ppasswd -P8066 -Ddbtest”命令來登入Cobar服務了,再接下來的操作就和在其他MySQL Client中一樣了。比如,我們可以使用“show databases”命令檢視資料庫,使用“show tables”命令檢視資料表,如下圖:


 接著,我們按照下圖中的SQL指定向資料表插入測試記錄。


 可以看到,這裡的tb2中包含了id為1、2、513的3條記錄。而實際上,這3條記錄儲存在不同的物理資料庫上的,大家可以到物理庫上驗證一下。

至於Cobar的連線和使用方法和MySQL一樣,Java程式中可以使用JDBC(建議5.1以上的版本),PHP中可以使用PDO。當然,Cobar還提供HA、叢集等高階的功能,更多資訊請參考其《產品文件》。此外,產品文件中還為我們提供了詳細的PPT文件《Cobar原理及應用.ppt》來介紹Cobar在實際生產環境中的使用方法。

此外,特別解釋一下大家可能比較關心的心跳檢測問題,Cobar的心跳檢測主要用在以下兩個地方。

1、在配置資料節點的時候,我們需要使用心跳檢測來探測資料節點的執行狀況。Cobar中使用執行SQL的方式來進行探測,簡單且實用。例如,我們可以把前面例項中的schema.xml中的dataNode配置成下面的樣子。

[html] view plaincopy

1.  ... ...  

2.    <!-- 資料節點定義,資料節點由資料來源和其他一些引數組織而成。-->  

3.    <dataNode name="dnTest1">  

4.      <property name="dataSource">  

5.        <dataSourceRef>dsTest[0]</dataSourceRef>  

6.      </property>  

7.      <!--Cobar與後端資料來源連線池大小設定-->  

8.      <property name="poolSize">256</property>  

9.      <!--Cobar通過心跳來實現後端資料來源HA,一旦主資料來源心跳失敗,便切換到備資料來源上工作-->  

10.    <!--Cobar心跳是通過向後端資料來源執行一條SQL語句,根據該語句的返回結果判斷資料來源的執行情況-->  

11.    <property name="heartbeat">select user()<property>  

12.  </dataNode>  

13.... ...  

2、當我們需要對Cobar作叢集(cluster),進行負載均衡的時候,我們也需要用到心跳機制。不過此處的配置則是在server.xml中,程式碼如下:

[html] view plaincopy

1.  ... ...  

2.    <!--組建一個Cobar叢集,只需在cluster配置中把所有Cobar節點(注意:包括當前Cobar自身)都配置上便可-->  

3.    <cluster>  

4.      <!--node名稱,一個node表示一個Cobar節點,一旦配置了node,當前Cobar便會向此節點定期發起心跳,探測節點的執行情況-->  

5.      <node name="cobar1">  

6.        <!--Cobar節點IP, 表示當前Cobar將會向192.168.0.1上部署的Cobar傳送心跳-->  

7.        <property name="host">192.168.0.1</property>  

8.        <!--節點的權重,用於客戶端的負載均衡,使用者可以通過命令查詢某個節點的執行情況以及權重-->  

9.        <property name="weight">1</property>  

10.    </node>  

11.    <!--當前Cobar將會向192.168.0.2上部署的Cobar傳送心跳-->  

12.    <node name="cobar2">  

13.      <property name="host">192.168.0.2</property>  

14.      <property name="weight">2</property>  

15.    </node>  

16.    <!--當前Cobar將會向192.168.0.3上部署的Cobar傳送心跳-->  

17.    <node name="cobar3">  

18.      <property name="host">192.168.0.3</property>  

19.      <property name="weight">3</property>  

20.    </node>  

21.    <!--使用者還可以將Cobar節點分組,以便實現schema級別的細粒度負載均衡-->  

22.    <group name="group12">  

23.      <property name="nodeList">cobar1,cobar2</property>  

24.    </group>  

25.     <group name="group23">  

26.      <property name="nodeList">cobar2,cobar3</property>  

27.    </group>  

28.  </cluster>  

29.... ...  


最後,簡單看一下Cobar的實現原理。

首先是系統模組架構。


 從上圖中可以看到,Cobar的前、後端模組都實現了MySQL協議;當接受到SQL請求時,會依次進行解釋(SQL Parser)和路由(SQL Router)工作,然後使用SQL Executor去後端模組獲取資料集(後端模組還負責心跳檢測功能);如果資料集來自多個資料來源,Cobar則需要把資料集進行組合(Result Merge),最後返回響應。整個過程應該比較容易理解,

下面是Cobar的網路通訊模組架構。


 從上圖中可以看出,Cobar採用了主流的Reactor設計模式來處理請求,並使用NIO進行底層的資料交換,這大大提升系統的負載能力。其中,NIOAcceptor用於處理前端請求,NIOConnector則用於管理後端的連線,NIOProcessor用於管理多執行緒事件處理,NIOReactor則用於完成底層的事件驅動機制,就是看起來和Mina和Netty的網路模型比較相似。如果有興趣,大家還可以到Cobar站點的下載頁面(https://github.com/alibaba/cobar)獲取該專案的原始碼,感謝阿里人的付出!

 

最後說點題外話,目前國內關於mysql分散式中間有

360公司的Atlas:http://www.guokr.com/blog/475765/

淘寶的tddl:http://www.guokr.com/blog/475765/

京東的藍海豚:http://cio.zdnet.com.cn/cio/2014/0731/3028990.shtml?fromrss=rss

網易的DDB:http://wenku.baidu.com/link?url=TiILF6KxWQBUu1bj2n8mA1E-_-RUESzjI7ALpo-mDWXW9uQv-0PCjmJrl9QH6ijP1ycFTXyz3plcrWgXOV80snuIVcMkLYNNKJA3EujCPTG

但是還是阿里的cobar好些,因為他開源了,除了中介軟體本身,還開源提供驅動、管理器。

相關文章