Cobar使用文檔(可用作MySQL大型集群解決方案)

w327 9年前發布 | 27K 次閱讀 Cobar MySQL 數據庫服務器

最近好不容易抽空研究了下Cobar,感覺這個產品確實很不錯(在文檔方面比Amoeba強多了),特此推薦給大家。Cobar是阿里巴巴研發的關系型數據的分布式處理系統,該產品成功替代了原先基于Oracle的數據存儲方案,目前已經接管了3000+個MySQL數據庫的schema,平均每天處理近50億次的SQL執行請求。


首先,使用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邏輯層次圖:
Cobar使用文檔(可用作MySQL大型集群解決方案)
* 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產品首頁)。
Cobar使用文檔(可用作MySQL大型集群解決方案)
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:http://code.alibabatech.com/wiki/display/cobar/release/ (下載tar.gz或者zip文件)

2、數據準備

假設本文MySQL所在服務器IP為192.168.0.1,端口為3306,用戶名為test,密碼為空,我們需要創建schema:dbtest1、dbtest2、dbtest3,table:tb1、tb2,SQL如下:

#創建dbtest1  
drop database if exists dbtest1;  
create database dbtest1;  
use dbtest1;  
#在dbtest1上創建tb1  
create table tb1(  
id    int not null,  
gmt   datetime);  
   
#創建dbtest2  
drop database if exists dbtest2;  
create database dbtest2;  
use dbtest2;  
#在dbtest2上創建tb2  
create table tb2(  
id    int not null,  
val   varchar(256));  
   
#創建dbtest3  
drop database if exists dbtest3;  
create database dbtest3;  
use dbtest3;  
#在dbtest3上創建tb2  
create table tb2(  
id    int not null,  
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)。

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE cobar:schema SYSTEM "schema.dtd">  
<cobar:schema xmlns:cobar="http://cobar.alibaba.com/">  
   
  <!-- schema定義 -->  
  <schema name="dbtest" dataNode="dnTest1">  
    <table name="tb2" dataNode="dnTest2,dnTest3" rule="rule1" />  
  </schema>  
   
  <!-- 數據節點定義,數據節點由數據源和其他一些參數組織而成。-->  
  <dataNode name="dnTest1">  
    <property name="dataSource">  
      <dataSourceRef>dsTest[0]</dataSourceRef>  
    </property>  
  </dataNode>  
  <dataNode name="dnTest2">  
    <property name="dataSource">  
      <dataSourceRef>dsTest[1]</dataSourceRef>  
    </property>  
  </dataNode>  
  <dataNode name="dnTest3">  
    <property name="dataSource">  
      <dataSourceRef>dsTest[2]</dataSourceRef>  
    </property>  
  </dataNode>  
   
  <!-- 數據源定義,數據源是一個具體的后端數據連接的表示。-->  
  <dataSource name="dsTest" type="mysql">  
    <property name="location">  
      <location>192.168.0.1:3306/dbtest1</location> <!--注意:替換為您的MySQL IP和Port-->  
      <location>192.168.0.1:3306/dbtest2</location> <!--注意:替換為您的MySQL IP和Port-->  
      <location>192.168.0.1:3306/dbtest3</location> <!--注意:替換為您的MySQL IP和Port-->  
    </property>  
    <property name="user">test</property> <!--注意:替換為您的MySQL用戶名-->  
    <property name="password">test</property> <!--注意:替換為您的MySQL密碼-->  
    <property name="sqlMode">STRICT_TRANS_TABLES</property>  
  </dataSource>  
</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中找到,代碼如下:

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE cobar:rule SYSTEM "rule.dtd">  
<cobar:rule xmlns:cobar="http://cobar.alibaba.com/">  
  
  <!-- 路由規則定義,定義什么表,什么字段,采用什么路由算法。-->  
  <tableRule name="rule1">  
    <rule>  
      <columns>id</columns>  
      <algorithm><![CDATA[ func1(${id})]]></algorithm>  
    </rule>  
  </tableRule>  
  
  <!-- 路由函數定義,應用在路由規則的算法定義中,路由函數可以自定義擴展。-->  
  <function name="func1" class="com.alibaba.cobar.route.function.PartitionByLong">  
    <property name="partitionCount">2</property>  
    <property name="partitionLength">512</property>  
  </function>  
</cobar:rule>

結合schema.xml中的內容,我們可以看出分表的規則是,按照id字段把tb2表中的數據分配到dnTest2和dnTest3兩個分區中,其中id小于512的數據會被放到dnTest2庫的分區中,而其余的會被放到dnTest3庫的分區中,更多路由算法可以參考《路由文檔》。最后,我們來看一下server.xml的配置,代碼如下。

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE cobar:server SYSTEM "server.dtd">  
<cobar:server xmlns:cobar="http://cobar.alibaba.com/">  
   
  <!--定義Cobar用戶名,密碼-->  
  <user name="root">  
    <property name="password">passwd</property>  
    <property name="schemas">dbtest</property>  
  </user>  
</cobar:server>

這里的server.xml配置比較簡單,只配置了本地Cobar服務的數據庫結構、用戶名和密碼。在啟動Cobar服務之后,使用用戶名root和密碼passwd就可以登錄Cobar服務。

4、運行Cobar

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

10:54:19,264 INFO  ===============================================  
10:54:19,265 INFO  Cobar is ready to startup ...  
10:54:19,265 INFO  Startup processors ...  
10:54:19,443 INFO  Startup connector ...  
10:54:19,446 INFO  Initialize dataNodes ...  
10:54:19,470 INFO  dnTest1:0 init success  
10:54:19,472 INFO  dnTest3:0 init success  
10:54:19,473 INFO  dnTest2:0 init success  
10:54:19,481 INFO  CobarManager is started and listening on 9066  
10:54:19,483 INFO  CobarServer is started and listening on 8066  
10:54:19,484 INFO  ===============================================

接著,我們就可以使用“mysql -h127.0.0.1 -uroot -ppasswd -P8066 -Ddbtest”命令來登錄Cobar服務了,再接下來的操作就和在其他MySQL Client中一樣了。比如,我們可以使用“show databases”命令查看數據庫,使用“show tables”命令查看數據表,如下圖:
Cobar使用文檔(可用作MySQL大型集群解決方案)
接著,我們按照下圖中的SQL指定向數據表插入測試記錄。
Cobar使用文檔(可用作MySQL大型集群解決方案)
可以看到,這里的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配置成下面的樣子。

... ...  
  <!-- 數據節點定義,數據節點由數據源和其他一些參數組織而成。-->  
  <dataNode name="dnTest1">  
    <property name="dataSource">  
      <dataSourceRef>dsTest[0]</dataSourceRef>  
    </property>  
    <!--Cobar與后端數據源連接池大小設置-->  
    <property name="poolSize">256</property>  
    <!--Cobar通過心跳來實現后端數據源HA,一旦主數據源心跳失敗,便切換到備數據源上工作-->  
    <!--Cobar心跳是通過向后端數據源執行一條SQL語句,根據該語句的返回結果判斷數據源的運行情況-->  
    <property name="heartbeat">select user()<property>  
  </dataNode>  
... ...

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

... ...  
  <!--組建一個Cobar集群,只需在cluster配置中把所有Cobar節點(注意:包括當前Cobar自身)都配置上便可-->  
  <cluster>  
    <!--node名稱,一個node表示一個Cobar節點,一旦配置了node,當前Cobar便會向此節點定期發起心跳,探測節點的運行情況-->  
    <node name="cobar1">  
      <!--Cobar節點IP, 表示當前Cobar將會向192.168.0.1上部署的Cobar發送心跳-->  
      <property name="host">192.168.0.1</property>  
      <!--節點的權重,用于客戶端的負載均衡,用戶可以通過命令查詢某個節點的運行情況以及權重-->  
      <property name="weight">1</property>  
    </node>  
    <!--當前Cobar將會向192.168.0.2上部署的Cobar發送心跳-->  
    <node name="cobar2">  
      <property name="host">192.168.0.2</property>  
      <property name="weight">2</property>  
    </node>  
    <!--當前Cobar將會向192.168.0.3上部署的Cobar發送心跳-->  
    <node name="cobar3">  
      <property name="host">192.168.0.3</property>  
      <property name="weight">3</property>  
    </node>  
    <!--用戶還可以將Cobar節點分組,以便實現schema級別的細粒度負載均衡-->  
    <group name="group12">  
      <property name="nodeList">cobar1,cobar2</property>  
    </group>  
     <group name="group23">  
      <property name="nodeList">cobar2,cobar3</property>  
    </group>  
  </cluster>  
... ...

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

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

下面是Cobar的網絡通訊模塊架構。
Cobar使用文檔(可用作MySQL大型集群解決方案)
從上圖中可以看出,Cobar采用了主流的Reactor設計模式來處理請求,并使用NIO進行底層的數據交換,這大大提升系統的負載能力。其中,NIOAcceptor用于處理前端請求,NIOConnector則用于管理后端的連接,NIOProcessor用于管理多線程事件處理,NIOReactor則用于完成底層的事件驅動機制,就是看起來和Mina和Netty的網絡模型比較相似。如果有興趣,大家還可以到Cobar站點的下載頁面(http://code.alibabatech.com/wiki/display/cobar/release)獲取該項目的源碼,真是太周到了,讓我們為富有開源精神的阿里人掌聲鼓勵一下!

 本文由用戶 w327 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!