程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL分片高可用集群之Cobar部署使用

MySQL分片高可用集群之Cobar部署使用

編輯:MySQL綜合教程

MySQL分片高可用集群之Cobar部署使用


Cobar是taobao公司用java開發的分布式MySQL中間件,可以支持數據的分片,且接口與mysql相同,因此可以無縫切換。並且不僅支持Mysql,而且還支持MariaDB哦,對版本的要求也很低,只要5.1以上就可以了。如果公司有較多的java項目,推薦使用。我們就來試試Cobar的集群搭建吧。   第一步:下載Cobar   現在可以從兩個官方地址下載,一個是github上:https://github.com/alibaba/cobar  可以下載源碼,也可以直接下載編譯好的包https://github.com/alibaba/cobar/releases  淘寶現在的開源網站也有:http://code.taobao.org/p/cloud-cobar/src/    兩個地方下載的目錄結構稍有不同,但目前內容基本一樣,且都可以運行,您可以自行選擇。本例子所用版本為1.2.7。   第二步:安裝多個MySQL數據庫   請參考文章http://bangbangba.blog.51cto.com/3180873/1703972  的第二步,不過Cobar不需要gtid支持,因此gtid相關的配置可選,如果是MariaDB,這幾行是不需要配的,此處我們使用的是MariaDB-10.1。   我們配置9個數據庫用於測試 作用        地址                端口          數據文件路徑               配置文件路徑 分片1     192.168.1.8    14011    /dev/shm/data/co11    cobra/co11.cnf 分片2     192.168.1.8    14021    /dev/shm/data/co21    cobra/co21.cnf 分片3     192.168.1.8    14031    /dev/shm/data/co31    cobra/co31.cnf 分片4     192.168.1.8    14041    /dev/shm/data/co41    cobra/co41.cnf 備份1     192.168.1.8    14051    /dev/shm/data/co51    cobra/co51.cnf 備份2    192.168.1.8    14061    /dev/shm/data/co61    cobra/co61.cnf 備份3    192.168.1.8    14071    /dev/shm/data/co71    cobra/co71.cnf 備份4    192.168.1.8    14081    /dev/shm/data/co81    cobra/co81.cnf 不分片     192.168.1.8    14091    /dev/shm/data/co91    cobra/co91.cnf 編輯好co11.cnf ~ co91.cnf 這9個配置文件,執行init_start.sh即可全部初始化好並啟動。這裡之所以配置為ip而不是localhost或127.0.0.1是為了後面集群做准備。     第三步:部署Cobar   Cobar只有配置文件,沒有其他的元數據,因此關鍵就在於配置文件的修改,下載的包裡面有一個例子配置文件,我們在此基礎上做修改。我們第一次先只使用分片1~4,後面的4個等下再使用。   首先我們修改schema.xml,我的內容如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 1999-2012 Alibaba Group. 。。。。-->
<!DOCTYPE cobar:schema SYSTEM "schema.dtd">
<cobar:schema xmlns:cobar="http://cobar.alibaba.com/">
  <!-- schema定義 name="lyw" 意思是對外顯示的數據庫名是lyw,dataNode="dnG"表示默認的數據節點是dnG -->
  <schema name="lyw" dataNode="dnG">
    <table name="h1" dataNode="dn0,dn1,dn2,dn3" rule="ruleLong" />
  </schema>
  <!-- 數據節點定義,數據節點由數據源和其他一些參數組織而成。ds[0]這樣的下標是dataSource中數據數組的序號 -->
  <dataNode name="dn0">
    <property name="dataSource">
      <dataSourceRef>ds[0]</dataSourceRef>
    </property>
  </dataNode>
  <dataNode name="dn1">
    <property name="dataSource">
      <dataSourceRef>ds[1]</dataSourceRef>
    </property>
  </dataNode>
  <dataNode name="dn2">
    <property name="dataSource">
      <dataSourceRef>ds[2]</dataSourceRef>
    </property>
  </dataNode>
  <dataNode name="dn3">
    <property name="dataSource">
      <dataSourceRef>ds[3]</dataSourceRef>
    </property>
  </dataNode>
  <!-- 不分片的數據源,跟schema第一個dataNode對應 -->
  <dataNode name="dnG">
    <property name="dataSource">
      <dataSourceRef>ds[8]</dataSourceRef>
    </property>
  </dataNode>
  <!-- 數據源定義,數據源是一個具體的後端數據連接的表示。 -->
  <dataSource name="ds" type="mysql">
    <property name="location">
      <location>192.168.1.8:14011/lyw</location>
      <location>192.168.1.8:14021/lyw</location>
      <location>192.168.1.8:14031/lyw</location>
      <location>192.168.1.8:14041/lyw</location>
      <location>192.168.1.8:14051/lyw</location>
      <location>192.168.1.8:14061/lyw</location>
      <location>192.168.1.8:14071/lyw</location>
      <location>192.168.1.8:14081/lyw</location>
      <location>192.168.1.8:14091/lyw</location>
    </property>
    <property name="user">lyw</property>
    <property name="password">123456</property>
    <property name="sqlMode">STRICT_TRANS_TABLES</property>
  </dataSource>
</cobar:schema>

 

  配置好schema.xml後,我們可以看到裡面有個字段rule="ruleLong",這個ruleLong的具體內容是配置在rule.xml文件中,我們這裡的配置如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 1999-2012 Alibaba Group. 。。。。-->
<!DOCTYPE cobar:rule SYSTEM "rule.dtd">
<cobar:rule xmlns:cobar="http://cobar.alibaba.com/">
  <!-- 路由規則定義,定義什麼表,什麼字段,采用什麼路由算法 -->
  <!--  所有路由規則tableRule都必須在所有函數function前面 -->
  <tableRule name="ruleLong">
    <rule>
      <columns>id</columns>
      <algorithm><![CDATA[ funcLong(${id}) ]]></algorithm>
    </rule>
  </tableRule>
   
  <!-- 路由函數定義,所有函數定義都需要在規則下面 -->
  <!---  partitionCount * partitionLength必須等於1024 -->
  <function name="funcLong"
    class="com.alibaba.cobar.route.function.PartitionByLong">
    <property name="partitionCount">4</property>
    <property name="partitionLength">256</property>
  </function>  
</cobar:rule>

 

  可以看到ruleLong規則中用到funcLong函數,funcLong函數在下面定義,注意所有函數定義都需要在規則下面,partitionCount * partitionLength必須等於1024,否則無法啟動。   然後是server.xml,這個文件修改下用戶名密碼就可以了,其他用默認參數。
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 1999-2012 Alibaba Group. -->
<!DOCTYPE cobar:server SYSTEM "server.dtd">
<cobar:server xmlns:cobar="http://cobar.alibaba.com/">
    <!-- 用戶訪問定義,用戶名、密碼、schema等信息。 -->
  <user name="lyw">
    <property name="password">123456</property>
    <property name="schemas">lyw</property>
  </user>
</cobar:server>

 

  另外還有個配置文件log4j.xml,無需修改。   我們的配置文件都已准備好,然後就啟動吧  
$ bin/startup.sh
$ jps
15894 CobarStartup
15946 Jps
$ netstat -nlp|grep java
tcp6       0      0 :::8066                 :::*                    LISTEN      15894/java      
tcp6       0      0 :::9066                 :::*                    LISTEN      15894/java

 

java7下可以直接啟動,如果時java8需要注釋掉startup.sh中的一行。       1   # JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSCompactAtFullCollection"   請檢查下進程是否啟動,如果配置有誤是無法啟動的。啟動後,我們可以看到已經開啟了兩個端口,8066和9066,其中8066是用於數據讀寫等操作的,9066是用於cobar自身管理的。我們迫不及待的要去試下了。   第四步:使用Cobar  
lyw@lywd:~/db/mariadb-10.1$ bin/mysql -ulyw -p123456 -h127.0.0.1 -P8066
MySQL [(none)]> show databases;
+----------+
| DATABASE |
+----------+
| lyw      |
+----------+
1 row in set (0.04 sec)
MySQL [(none)]> use lyw;
Database changed
MySQL [lyw]> show tables;
Empty set (0.00 sec)
MySQL [lyw]> create table h1 (id int primary key, v varchar(32));
Query OK, 0 rows affected (0.01 sec)
MySQL [lyw]> insert into h1 (id, v) values(1, 'aa'), (2, '2'), (256, 'cc'), (600,'dd'),(900, 'ee'), (1000, 'ff');
Query OK, 6 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0
MySQL [lyw]> select * from h1;
+------+------+
| id   | v    |
+------+------+
|  256 | cc   |
|  900 | ee   |
| 1000 | ff   |
|  600 | dd   |
|    1 | aa   |
|    2 | 2    |
+------+------+
6 rows in set (0.00 sec)
MySQL [lyw]> select * from h1 where id = 256;
+-----+------+
| id  | v    |
+-----+------+
| 256 | cc   |
+-----+------+
1 row in set (0.00 sec)
MySQL [lyw]> select * from h1 where id in (256, 900, 901);
+-----+------+
| id  | v    |
+-----+------+
| 256 | cc   |
| 900 | ee   |
+-----+------+
2 rows in set (0.00 sec)

 

  最後返回的結果看起來有點亂,並且每次執行這樣的select語句,順序都會不同,這是因為我們插入的這6條數據已經根據ruleLong的規則分散在了4個數據庫中,返回的時候cobar只是簡單的合並,並沒有排序。我們這時候可以到4個庫中分別查詢,每個庫都只包含其中的一部分數據。   注意:前面的insert語句中指定了列名(id, v),這是必須的,否則會將數據插入到所有數據庫中去,即插入1條等於插入4條。   select * from h1 where id = 256;  這行查詢語句指定了id = 256,因此cobar會計算256這個值是在哪個數據庫(第二個)因此這條語句只會在第二個數據庫中查找 select * from h1 where id in (256, 900, 901);  這行查詢語句指定了兩個id,cobar會計算這些id都屬於哪個庫,然後去對應的庫查詢,實際上會變成兩個語句,   在第二個庫執行select * from h1 where id in (256),    在第四個庫執行select * from h1 where id in (900, 901),   然後合並數據返回。   我們可以用explain命令查看cobar的拆分情況。這個命令只是語法分析,不會到mysql中執行。   MySQL [lyw]> explain select * from h1 where id in (256, 900, 901); +-----------+-----------------------------------------+ | DATA_NODE | SQL                                     | +-----------+-----------------------------------------+ | dn1       | SELECT * FROM h1 WHERE id IN (256)      | | dn3       | SELECT * FROM h1 WHERE id IN (900, 901) | +-----------+-----------------------------------------+ 2 rows in set (0.00 sec)   Cobar是不支持事務的,begin命令就不可以運行,很多操作盡量使用語句內原子操作。比如 update h1 set a=a+1 where id = 2;   而不是先讀出數據,再修改。拆成兩條就需要事務支持才安全了。   Cobar支持多庫同時操作,但只是在多個庫分別執行後,一起返回數據而已,我們試下下面的幾個語句   MySQL [lyw]> select * from h1 limit 1; +-----+------+ | id  | v    | +-----+------+ | 600 | dd   | | 256 | cc   | |   1 | aa   | | 900 | ee   | +-----+------+   我們是想要得到一條數據,而實際上是得到4條,並且是每個庫中一條,因此這樣的結果並不符合我們的初衷,所以對於分頁這樣的操作用cobar並不合適。大家還可以去試下sort,  group,join等操作,以及他們的組合操作,都是如此。   那Cobar合適的是什麼呢?cobar最合適的就是單行的操作,另外還有in這樣的多行操作。或者其他只需要一個庫就能搞定的操作。這也是需要我們在設計表結構的時候多下工夫才行。   第五步:多種分片方式配置   前面講了一個按照數字進行hash分片的例子。cobar自身提供了4種分片方法,分別是PartitionByLong,PartitionByString,PartitionByFileMap,Dimension2PartitionFunction。每種方法需要配置的參數都不同   PartitionByString 按字符串hash分片   我們需要修改rule.xml文件,如下部分,記得所有的tableRule 在所有的function前面 
 <tableRule name="ruleString">
    <rule>
      <columns>id</columns>
      <algorithm><![CDATA[ funcString(${id}) ]]></algorithm>
    </rule>
  </tableRule>
   
  <function name="funcString"
    class="com.alibaba.cobar.route.function.PartitionByString">
    <property name="partitionCount">4</property>
    <property name="partitionLength">256</property>
    <property name="hashSlice">:12</property>
  </function>

 

  其中hashSlice的含義是字符串的哪幾個字符進行hash運算,例子中:12表示前面的12個字符進行運算,另外還有負數表示法,表示從後面開始數。 在schema.xml增加一個表格 1 <table name="h3" dataNode="dn0,dn1,dn2,dn3" rule="ruleString" />   配置好後,我們可以用集群管理的reload方法熱更新配置文件。(注意端口是9066)   bin/mysql -ulyw -p123456 -h127.0.0.1 -P 9066 MySQL [(none)]> reload @@config; Query OK, 1 row affected (0.02 sec) Reload config success   PartitionByFileMap 按文件內容分片   我們需要修改rule.xml文件,如下部分,  
  <tableRule name="ruleFileMap">
    <rule>
      <columns>district </columns>
      <algorithm><![CDATA[ funcFileMap(${id}) ]]></algorithm>
    </rule>
  </tableRule>
  <function name="funcFileMap"
    class="com.alibaba.cobar.route.function.PartitionByFileMap">
    <property name="fileMapPath">/home/lyw/file_map.txt</property>
    <property name="defaultNode">0</property>
  </function>

 

  rule.xml中fileMapPath字段我們指定了一個配置文件/home/lyw/file_map.txt,這個文件內容的格式是k=v結構,k是分片的字符串,v是節點序號(不是hash值)。內容如下,您可自己多寫一些。 1 2 3 4 5 a=0 b=1 c=2 d=3 。。。。。。   defaultNode 字段表示如果key值不在這個配置文件中,那麼將數據存儲在這個節點中。   然後我們還要在schema.xml增加一個表格       <table name="h5" dataNode="dn0,dn1,dn2,dn3" rule="ruleFileMap" />   只有字符串完整地屬於配置文件中,才算匹配到,不是前綴,如例子中只有a,b,c,d可以找到對應的節點,其他任何值都將放入默認節點。因此這種方式一般不是用於id等主鍵字段,而是其他種類有限的字段,如國家、省份等。   Dimension2PartitionFunction 二維分片   二維分片有兩個維度,都需要配置,因此配置內容較多 rule.xml:
<tableRule name="rule2D">
    <rule>
      <columns>id, id2</columns>
      <algorithm><![CDATA[ func2D(${id}, ${id2}) ]]></algorithm>
    </rule>
    <rule>
      <columns>id</columns>
      <algorithm><![CDATA[ func2D(${id}, null) ]]></algorithm>
    </rule>
    <rule>
      <columns>id2</columns>
      <algorithm><![CDATA[ func2D(null, ${id2}) ]]></algorithm>
    </rule>
  </tableRule>
  <function name="func2D"
    class="com.alibaba.cobar.route.function.Dimension2PartitionFunction">
    <property name="keyTypeX">string</property>
    <property name="partitionCountX">2</property>
    <property name="partitionLengthX">512</property>
    <property name="hashSliceX">:12</property>
    <property name="keyTypeY">long</property>
    <property name="partitionCountY">2</property>
    <property name="partitionLengthY">512</property>
  </function>

 

  從rule.xml文件中我們看到tableRule配置了三個rule,其中第一個規則是有兩個參數的,後兩個規則只有一個參數,這3個rule不是必須全配置,但是要實現只匹配一個維度的話,就需要配置,否則當查詢語句中只有一個維度的key時會進行所有庫的執行,效率不高。   函數需要指定兩個維度,字符串和數字都可以,其他類型目前不支持。   同樣schema.xml增加一個表格      <table name="d1" dataNode="dn0,dn1,dn2,dn3" rule="rule2D" /> 如果需要二維分片,集群規模一般要相當大了,比如8*8=64,否則采用二維分片的意義不大。   第六步:Cobar自身集群配置   前面配置的cobar只是在一台機器上運行,而運行時cobar需要的資源是比較多的,一台cobar可以拖3台左右mysql服務器,而實際上只要用到cobar,mysql數量都在8台以上,所以需要多個cobar支撐,集群相關的內容在server.xml中配置, 
 <cluster>
    <node name="cobar1">
      <property name="host">192.168.1.8</property>
      <property name="weight">1</property>
    </node>
    <node name="cobar2">
      <property name="host">192.168.1.9</property>
      <property name="weight">1</property>
    </node>
    <node name="cobar3">
      <property name="host">192.168.1.10</property>
      <property name="weight">1</property>
    </node>
  </cluster>

 

  每增加一台機器就多配置一個node,然後將這個配置文件復制到每台cobar電腦上,並啟動。這時我們在任意一台電腦上用下面的命令查看活著的集群(宕機的節點不會顯示)  
MySQL [lyw]> show cobar_cluster;
+--------------+--------+
| HOST         | WEIGHT |
+--------------+--------+
| 192.168.1.8  |      1 |
| 192.168.1.9  |      1 |
| 192.168.1.10 |      1 |
+--------------+--------+
3 rows in set (0.00 sec)

 

  此處雖然有host和weight兩個值,但是cobar並沒有做負載均衡相關的具體事情,只是告訴客戶端,cobar集群的運行情況,讓客戶端自己制定負載均衡策略。     第七步:Cobar自身管理   前面講的是數據操作,用的是8066端口,cobar提供集群管理功能默認用的是9066端口   bin/mysql -ulyw -p123456 -h127.0.0.1 -P9066 MySQL [(none)]> show @@help;   reload命令會是一個常用命令,當修改了配置文件,就執行下這個命令讓配置生效。   MySQL [(none)]> reload @@config; Query OK, 1 row affected (0.01 sec) Reload config success   注意server.xml中的system部分不可以熱加載,需要重啟生效。   如果加載後發現有誤,可以用rollback命令回滾配置,注意只能回滾一次。   假如我們要看下所有服務器的活動情況,我們可以用下面的命令
MySQL [(none)]> show @@heartbeat;
+--------+-------+-------------+-------+---------+-------+----------+---------+--------------+---------------------+-------+
| NAME   | TYPE  | HOST        | PORT  | RS_CODE | RETRY | STATUS   | TIMEOUT | EXECUTE_TIME | LAST_ACTIVE_TIME    | STOP  |
+--------+-------+-------------+-------+---------+-------+----------+---------+--------------+---------------------+-------+
| cobar1 | COBAR | 192.168.1.8 |  8066 |       1 |     0 | idle     |   10000 | 0,0,0        | 2015-10-22 10:33:28 | false |
| cobar2 | COBAR | 192.168.1.9 |  8066 |      -1 |     3 | checking |   10000 | 0,0,0        | 2015-10-22 10:33:27 | false |
| cobar3 | COBAR | 192.168.1.10|  8066 |      -1 |     1 | checking |   10000 | 0,0,0        | 2015-10-22 10:33:26 | false |
| dn0    | MYSQL | 192.168.1.8 | 14011 |       0 |     0 | idle     |      -1 | 0,0,0        | NULL                | false |
| dn1    | MYSQL | 192.168.1.8 | 14021 |       0 |     0 | idle     |      -1 | 0,0,0        | NULL                | false |
| dn2    | MYSQL | 192.168.1.8 | 14031 |       0 |     0 | idle     |      -1 | 0,0,0        | NULL                | false |
| dn3    | MYSQL | 192.168.1.8 | 14041 |       0 |     0 | idle     |      -1 | 0,0,0        | NULL                | false |
| dnG    | MYSQL | 192.168.1.8 | 14091 |       0 |     0 | idle     |      -1 | 0,0,0        | NULL                | false |
+--------+-------+-------------+-------+---------+-------+----------+---------+--------------+---------------------+-------+
8 rows in set (0.00 sec)

 

  前面3行是cobar自身集群,我這裡只啟動了一台,所以只有一台的狀態是正常的,其他兩台都不可用,一直在嘗試檢查是否活動起來。   下面5台並沒有開啟心跳,所以timeout是-1,不會進行檢查,直接認為是正常的。 其他命令您可以自己嘗試,都很好理解。     第八步:dataNode的高可用配置   細心的您一定發現了我們開始的時候部署了9個mysql,但是我們只有用到了5台,另外4台還沒有用起來,現在我們要將另外4台也用起來。   我們計劃將另外4台和前面4台兩兩配置為雙主(也可以是其他方案,如galera等) 然後修改我們的配置文件schema.xml中dataNode的內容,每個dataNode都增加一台對應的服務器,並且配置上心跳,(實際上心跳最好是寫操作的語句)   
<!-- 數據節點定義,數據節點由數據源和其他一些參數組織而成。 -->
  <dataNode name="dn0">
    <property name="dataSource">
      <dataSourceRef>ds[0]</dataSourceRef>
      <dataSourceRef>ds[4]</dataSourceRef>
    </property>
    <property name="heartbeatSQL">select user()</property>
  </dataNode>
  <dataNode name="dn1">
    <property name="dataSource">
      <dataSourceRef>ds[1]</dataSourceRef>
      <dataSourceRef>ds[5]</dataSourceRef>
    </property>
    <property name="heartbeatSQL">select user()</property>
  </dataNode>
  <dataNode name="dn2">
    <property name="dataSource">
      <dataSourceRef>ds[2]</dataSourceRef>
      <dataSourceRef>ds[6]</dataSourceRef>
    </property>
    <property name="heartbeatSQL">select user()</property>
  </dataNode>
  <dataNode name="dn3">
    <property name="dataSource">
      <dataSourceRef>ds[3]</dataSourceRef>
      <dataSourceRef>ds[7]</dataSourceRef>
    </property>
    <property name="heartbeatSQL">select user()</property>
  </dataNode>

 

  然後reload配置,在用show @@datanode;命令檢查下運行情況   MySQL [(none)]> show @@datanode; +------+-------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+ | NAME | DATASOURCES | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME | +------+-------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+ | dn0  | ds[0],ds[4] |     0 | mysql |      0 |    0 |  128 |       0 |          0 |        0 |       0 |            -1 | | dn1  | ds[1],ds[5] |     0 | mysql |      0 |    0 |  128 |       0 |          0 |        0 |       0 |            -1 | | dn2  | ds[2],ds[6] |     0 | mysql |      0 |    0 |  128 |       0 |          0 |        0 |       0 |            -1 | | dn3  | ds[3],ds[7] |     0 | mysql |      0 |    0 |  128 |       0 |          0 |        0 |       0 |            -1 | | dnG  | ds[8]       |     0 | mysql |      0 |    0 |  128 |       0 |          0 |        0 |       0 |            -1 | +------+-------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+ 5 rows in set (0.01 sec)   我們發現DATASOURCES中前面4個都有兩個節點,INDEX目前都是0,表示連接的是前面這個節點。   這時我們模擬宕機,將ds[0]這個節點kill掉,過幾秒鐘再用上面這個命令查看時,就會發現第一個INDEX變成了1,也就是說用到的是ds[4]節點。之後的讀寫都會在ds[4]中操作。   然後我們重新啟動ds[0],再查狀態,發現還是INDEX還是維持1,cobar不會主動切換回去。假如我們想切換回去,可以用命令switch @@datasource name:index,(序號參數可選)   MySQL [(none)]> switch @@datasource dn0:0; Query OK, 1 row affected (0.03 sec)   注意該功能只會修改當前cobar的配置,其他節點並不會一同修改,因此有一定風險。配置文件的加載也是一樣,多個節點間不會同步,因此也有一點風險。   至此Cobar的基本特性就是這樣了,更多的高級功能就在逐步的使用中去發現吧。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved