Ubuntu10下MySQL搭建Amoeba_讀寫分離+分片


一、背景知識

之前已經寫了一篇關於Amoeba讀寫分離:Ubuntu10下MySQL搭建Amoeba_讀寫分離,上篇文章只是簡單的測試下搭建讀寫分離,這里再加上一點的內容,在讀寫分離的基礎上再加入分片。

閱讀本篇文章之前建議你先閱讀:

Ubuntu10下MySQL搭建Master/Slave

Ubuntu10下搭建MySQL Proxy讀寫分離

測試內容:把數據分片到Master1與Master2,再由Master1同步到Slave1,Master2同步到Slave2,把對數據的讀取分布到Slave1和Slave2。

 

二、搭建過程

(一) 測試環境

Amoeba for MySQL:192.168.1.147

Master1:192.168.1.25

Slave1:192.168.1.30

Master2:192.168.1.35

Slave2:192.168.1.40

數據庫為:dba_db,帳號密碼統一為:test/123456,GRANT ALL ON *.* TO test@'%' IDENTIFIED BY '123456';

 

(二) 前期准備

1.      驗證Amoeba是否安裝成功的命令(如下圖):/usr/local/amoeba/bin/amoeba


(Figure1:安裝成功)

2.      啟動amoeba:/usr/local/amoeba/bin/amoeba start


(Figure 2:啟動成功)

 

(三) Amoeba讀寫分離+水平切片配置

1.      修改amoeba.xml,設置登陸amoeba的帳號密碼。

<property name="user">testuser</property>

<property name="password">password</property>

2.      測試使用上面帳號是否正常登陸,如果出現上面的圖2界面說明設置的帳號密碼成功。

#mysql -u testuser -p -h 192.168.1.147 -P 8066

3.      修改dbServers.xml,設置數據庫、登陸MySQL的帳號和密碼。

<property name="schema">dba_db</property>

<property name="user">test</property>

<property name="password">123456</property>

4.      修改dbServers.xml,設置數據庫服務器的IP地址和服務器別名。

    <dbServer name="Master1"  parent="abstractServer">

       <factoryConfig>

           <property name="ipAddress">192.168.1.25</property>

       </factoryConfig>

    </dbServer>

    <dbServer name="Slave1"  parent="abstractServer">

        <factoryConfig>

            <property name="ipAddress">192.168.1.30</property>

        </factoryConfig>

    </dbServer>

    <dbServer name="Master2"  parent="abstractServer">

         <factoryConfig>

              <property name="ipAddress">192.168.1.35</property>

         </factoryConfig>

</dbServer>

    <dbServer name="Slave2"  parent="abstractServer">

         <factoryConfig>

              <property name="ipAddress">192.168.1.40</property>

         </factoryConfig>

</dbServer>

修改dbServers.xml,設置ROUNDROBIN(輪詢策略);(省略或者注釋)

<dbServer name="virtualSlave" virtual="true">

<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">

<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->

<property name="loadbalance">1</property>

<property name="poolNames">Slave1,Slave2,Slave2</property>

</poolConfig>

</dbServer>

修改amoeba.xml,設置讀寫分離,修改queryRouter標簽下的;(省略或者注釋)

<property name="LRUMapSize">1500</property>

<property name="defaultPool">Master</property>

<property name="writePool">Master</property>

<property name="readPool">virtualSlave</property>

<property name="needParse">true</property>

5.      修改rule.xml,添加對label表的讀寫分離+水平切片規則;

<tableRule name="label" schema="dba_db" defaultPools="Master1,Slave1,Master2,Slave2" writePools="Master1,Master2" readPools="Slave1,Slave2">

<rule name="rule1" ruleResult="POOLNAME">

<parameters>ID</parameters>

<expression><![CDATA[

var hashid = abs(hash(ID)) % 2;

case hashid when 0 then (isReadStatement?'Slave1':'Master1');

when 1 then (isReadStatement?'Slave2':'Master2');

end case;

]]></expression>

</rule>

</tableRule>

這個規則的意思是:把數據取模切片到Master1與Master2,再由Master1同步到Slave1,Master2同步到Slave2,對數據的讀取分布到Slave1和Slave2。isReadStatement?'Slave1':'Master1'判斷是否是讀,如果是,分到Slave1,如果不是分到Master1。

6.      重新啟動amoeba,如果出現上面的圖2界面說明設置成功;

 

(四) MySQL的Master/Slave配置

1.      Master1服務器/etc/mysql/my.cnf目錄 [mysqld] 區塊中加上:

log-bin=mysql-bin

server-id=1

innodb_flush_log_at_trx_commit=1

sync_binlog=1

binlog_do_db=dba_db

binlog_ignore_db=mysql

2.      登陸Master1的MySQL,新建一個用戶賦予“REPLICATION SLAVE”的權限。你不需要再賦予其它的權限:(因為是有兩個Salve,所以使用了%)

mysql>use mysql;

mysql>create user viajar@'192.168.1.%' identified by '123456';

mysql>grant replication slave on *.* to viajar@'192.168.1.%' identified by '123456';

3.      重啟Master的MySQL:

#service mysql restart

4.      獲取Master1的binlog信息:(mysql-bin.000136,106)

mysql>SHOW MASTER logs;


Figure 3:Master信息)

5.      Slave1服務器/etc/mysql/my.cnf目錄 [mysqld] 區塊中加上:

server-id=2

6.      重啟Slave1的MySQL:

#service mysql restart

7.      登陸Slave1的MySQL,執行命令:

mysql> change master to master_host='192.168.1.25', master_user='viajar', master_password='123456', master_log_file='mysql-bin.000136', master_log_pos=106;

8.      啟動Slave1的Slave:

mysql>START SLAVE;

9.      檢查Slave1的Slave是否正常:

mysql>show slave status\G;

10.   以同樣的方式配置Master2、Slave2,第5步與第7步會有些差異。

 

(五) 驗證讀寫分離+水平切片

1.      登陸到amoeba(147),插入下面的測試數據

INSERT INTO label(Id,NAME,Description,AddOn)

VALUES (1,'viajar','我的博客',NOW());

INSERT INTO label(Id,NAME,Description,AddOn)

VALUES (2,'viajar','我的博客',NOW());

INSERT INTO label(Id,NAME,Description,AddOn)

VALUES (3,'viajar','我的博客',NOW());

INSERT INTO label(Id,NAME,Description,AddOn)

VALUES (4,'viajar','我的博客',NOW());

2.      登陸Master1(25)、Slave1(30)分別驗證數據的分布,看到數據都如下圖所示:

mysql> SELECT * FROM label;


(Figure 4:Master1、Slave1)

3.      登陸Master2(35)、Slave2(40)分別驗證數據的分布,看到數據都如下圖所示:

mysql> SELECT * FROM label;


(Figure 5:Master2、Slave2)

       圖4與圖5已經證明了數據進行了水平切片。

       為了更明顯的測試讀寫分離,我們修改幾台服務器上的值:

master1mysql>UPDATE label SET NAME = 'master1';

slave1mysql>UPDATE label SET NAME = 'slave1';

master2mysql>UPDATE label SET NAME = 'master2';

slave2mysql>UPDATE label SET NAME = 'slave2';

4.      登陸Amoeba(147)驗證數據的分布,看到數據都如下圖所示:

mysql> SELECT * FROM label;

(Figure 6:Amoeba)

5.      登陸Amoeba(147)驗證數據的分布,看到數據都如下圖所示:

mysql> SELECT * FROM label WHERE id =1;

(Figure 7:Amoeba)

圖4的意思是搭建從Master1到Slave1的replication成功了;

圖5的意思是搭建從Master2到Slave2的replication成功了;

圖6可以看到查詢的都是從服務器上的數據;

圖7的意思是在一定程度上達到了讀寫分離的效果了,Master2與Slave2同樣有ID=1的記錄,但是只返回了一條記錄。

我們再進一步驗證Amoeba讀取到的這條記錄是Master2還是Slave2的數據:

6.      停止Slave2上的Slave,刪除id為1的記錄,剩余圖8中顯示的數據:

mysql>stop slave

mysql>DELETE FROM label WHERE id =1;

(Figure 8:Slave2)

7.      到Amoeba上執行下面查詢,查詢返回的結果集:

mysql>SELECT * FROM label WHERE id =1;

(Figure 9:結果集為空)

到此Amoeba的讀寫分離+水平切片已經測試完畢。

 

三、注意事項

1.      在做Master/Slave的時候,我們有兩台Salve,而且是內網的機器,所以使用了“192.168.1.%”這樣的方式來創建用戶,在一定的程度上保障帳號的安全性,又方便管理,使用“*”是錯誤的;

2.      對於多Slave的帳號問題,還可以有其它方式來創建帳號的,就是在Master為每個Slave創建獨立的帳號和密碼;

3.      修改log4j.xml 取消日志文件生成(太大了,磁盤很容易滿),<param name="file" value="${amoeba.home}/logs/project.log"/>改成:<param name="file" value="<![CDATA[${amoeba.home}/logs/project.log>/dev/null]]>"/>

4.      性能優化,打開bin/amoeba,DEFAULT_OPTS="-server -Xms256m -Xmx256m -Xss128k"改成:DEFAULT_OPTS="-server -Xms512m -Xmx512m -Xmn100m -Xss1204k"Amoeba新版本MYSQL讀寫分離配置

5.      當tableRule中沒有任何規則能命中該表,將操作tableRule配置的writePools(若沒有配置則使用defaultPools)屬性中的數據庫節點;Amoeba切分規則配置詳解

6.      當某個表在任何tableRules都沒有被路由到,將操作queryRouter配置的writePools(若沒有配置則使用defaultPools)屬性中的數據庫節點。

7.      rule的屬性group表示規則的組名,若多個rule元素有相同的組名,則一旦命中不再驗證后面的規則。

8.      rule的屬性ruleResult有兩個選項:POOLNAME和BOOLEAN。配置為POOLNAME則expression返回數據庫節點名;配置為BOOLEAN則當expreesion返回true是操作writePools(若沒有配置writePools則操作defaultPools)

9.      defaultPools、readPools、writePools均是一個或多個數據庫節點名以逗號為分隔符連接的字符串。數據庫節點名必須在dbServers.xml定義。需要切分的表名可以使用正則表達式,但是不允許用“.”號,因為目前“.”號作為schema與table的分割符號。 比如如果需要通配以“blog”開頭的任意表名,需要寫成:“blog[A-Za-z0-9]*”。

10.   所有的切片規則都一樣,首先要知道切分規則並且要命中,所以要首先生成ID值,在插入的時候指明ID值;

 

四、疑問解答

1.      在Amoeba中執行mysql> SELECT * FROM label; 有可能會返回下圖的結果集,造成這樣的原因是在rule.xml的匹配過程中沒有符合規則的(查詢中沒有帶ID),所以它到每個數據庫都執行了一次全表查詢,再把數據記錄合並起來;

應該如何防止這些情況的出現呢?如何在rule.xml的匹配規則中防止全表的查詢?還有沒類似全表查詢這樣類似的情況呢?

(Figure 10:結果集)

在rule.xml的tableRule標簽中沒有設置writePools="Master1,Master2" readPools="Slave1,Slave2"

2.      rule.xml中使用的函數能自定義嘛?ruleFunctionMap.xml是如何使用的?類似於我能不能把對UUID做hash,再對key值取模等這些規則放到配置中去呢?自定義的函數。amoeba-mysql-binary-2.1.0-RC5.tar.gz暫時還沒有相關的文檔:Amoeba:分布式數據庫Proxy解決方案

 

五、參考文獻

在Master/Slave結構下的讀寫分離基礎

Amoeba切分規則配置詳解規則比較有含量

Amoeba新版本MYSQL讀寫分離配置log4j.xml設置

Amoeba for mysql讀寫分離比較多的測試

Amoeba搞定mysql主從讀寫分離比較多的測試

MYSQL之--amoeba 實現讀寫分離,負載均衡百度文庫

Amoeba使用指南

Mysql 基於 Amoeba 讀寫分離

Amoeba for Mysql 試用小結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM