mysql讀寫分離之amoeba

一.amoeba介紹

Amoeba(變形蟲)項目,該開源框架於2008年 開始發佈一款 Amoeba for Mysql軟件。這個軟件致力於MySQL的分佈式數據庫前端代理層,它主要在應用層訪問MySQL的 時候充當SQL路由功能,專一於分佈式數據庫代理層(Database Proxy)開發。座落與 Client、DB Server(s)之間,對客戶端透明。具備負載均衡、高可用性、SQL 過濾、讀寫分離、可路由相關的到目標數據庫、可併發請求多臺數據庫合併結果。 經過Amoeba你可以完成多數據源的高可用、負載均衡、數據切片的功能,目前Amoeba已在不少 企業的生產線上面使用。前端

在MySQL proxy 6.0版本 上面若是想要讀寫分離而且 讀集羣、寫集羣 機器比較多狀況下,用mysql proxy 須要至關大的工做量,目前mysql proxy沒有現成的 lua腳本。mysql proxy根本沒有配置文件, lua腳本就是它的所有,固然lua是至關方便的。那麼一樣這種東西須要編寫大量的腳本才能完成一 個複雜的配置。而Amoeba for Mysql只須要進行相關的配置就能夠知足需求。java

目前不足:mysql

  1. 目前還不支持事務
    2.暫時不支持存儲過程(近期會支持)
    3.不適合從amoeba導數據的場景或者對大數據量查詢的query並不合適(好比一次請求返回10w以上甚至更多數據的場合)
    4.暫時不支持分庫分表,amoeba目前只作到分數據庫實例,每一個被切分的節點須要保持庫表結構一致。web

  2. 原理流程圖
    sql

技術分享

二 安裝amoeba

wget http://sourceforge.net/projects/amoeba/files/Amoeba%20for%20mysql/2.x/amoeba-mysql-binary-2.1.0-RC5.tar.gz數據庫

mkdir -pv /usr/loca/amoeba/後端

tar -zxvf amoeba-mysql-binary-2.1.0-RC5.tar.gz -C /usr/loca/amoeba/服務器

而後進入bin目錄運行amoeba start或者amoeba start &後臺的形式運行,不過下面咱們先看配置文件; 最流行的java後臺框架獲取【下載地址】 網絡

三 配置amoeba

1.想象Amoeba做爲數據庫代理層,它必定會和不少數據庫保持通訊,所以它必須知道由它代理的數據庫如何鏈接,好比最基礎的:主機IP、端口、Amoeba使用的用戶名和密碼等等。這些信息存儲在$AMOEBA_HOME/conf/dbServers.xml中。
2.Amoeba爲了完成數據切分提供了完善的切分規則配置,爲了瞭解如何分片數據、如何將數據庫返回的數據整合,它必須知道切分規則。與切分規則相關的信息存儲在$AMOEBA_HOME/conf/rule.xml中。
3.當咱們書寫SQL來操做數據庫的時候,經常會用到不少不一樣的數據庫函數,好比:UNIX_TIMESTAMP()、SYSDATE()等等。這些函數如何被Amoeba解析呢?$AMOEBA_HOME/conf/functionMap.xml描述了函數名和函數處理的關係。
4.對$AMOEBA_HOME/conf/rule.xml進行配置時,會用到一些咱們本身定義的函數,好比咱們須要對用戶ID求HASH值來切分數據,這些函數在$AMOEBA_HOME/conf/ruleFunctionMap.xml中定義。
5.Amoeba能夠制定一些可訪問以及拒絕訪問的主機IP地址,這部分配置在$AMOEBA_HOME/conf/access_list.conf中
6.Amoeba容許用戶配置輸出日誌級別以及方式,配置方法使用log4j的文件格式,文件是$AMOEBA_HOME/conf/log4j.xml。架構

ok

配置以前咱們說說咱們的架構,很簡單,三臺主機

一臺 amoeba 192.168.127.140 來轉發請求;

一臺 master 192.168.127.141 能夠進行讀寫操做;

一臺 slave 192.168.127 只能進行讀取操做;

本場景是讀取數據量比較大,因此master能夠讀寫,slave只能讀取,最終的效果讀取比例是master:slave=1:3.

7 .配置amoeba節點

7.1紅色字體是主配置文件須要注意和修改的地方

<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">
<proxy>
 
 <!-- service class must implements com.meidusa.amoeba.service.Service -->
 <service name="Amoeba for Mysql" class="com.meidusa.amoeba.net.ServerableConnectionManager">#1.定義這是一個MySQL Proxy Service。相應的也會有MongoDB Proxy Service以及Aladdin Proxy Service。
 <!-- port -->
 <property name="port">8066</property> #2.數據庫客戶端用來登錄amoeba的端口;
 
 <!-- bind ipAddress -->
 <!-- 
 <property name="ipAddress">192.168.127.140</property> #3.數據庫客戶端用來登錄amoeba的IP,一般Proxy Service服務的主機地址並不須要定義,若是Amoeba所在的服務器在多個網絡環境內你能夠定義該機器的其中一個IP來指定Amoeba所服務的網絡環境。若是設置爲127.0.0.1將致使其餘機器沒法訪問Amoeba的服務。
 -->
 
 <property name="manager">${clientConnectioneManager}</property>
 
 <property name="connectionFactory">
 <bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory">
 <property name="sendBufferSize">128</property>
 <property name="receiveBufferSize">64</property>
 </bean>
 </property>
 
 <property name="authenticator">
 <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
 
 <property name="user">root</property> #6.數據庫客戶端用來登錄amoeba的用戶名;
 
 <property name="password">password</property>#7.數據庫客戶端用來登錄amoeba的密碼;
 
 <property name="filter">
 <bean class="com.meidusa.amoeba.server.IPAccessController"> 
 <property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
 </bean>
 </property>
 </bean>
 </property>
 
 </service>
 
 <!-- server class must implements com.meidusa.amoeba.service.Service -->
 <service name="Amoeba Monitor Server" class="com.meidusa.amoeba.monitor.MonitorServer">
 <!-- port -->
 <!-- default value: random number
 <property name="port">9066</property>
 -->
 <!-- bind ipAddress -->
 <property name="ipAddress">127.0.0.1</property>
 <property name="daemon">true</property>
 <property name="manager">${clientConnectioneManager}</property>
 <property name="connectionFactory">
 <bean class="com.meidusa.amoeba.monitor.net.MonitorClientConnectionFactory"></bean>
 </property>
 
 </service>
 
 <runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">#8.runtime元素定義了一些Proxy相關的運行期配置,如客戶端及數據庫服務器端的線程數以及SQL超時時間設定等等。
 <!-- proxy server net IO Read thread size -->
 <property name="readThreadPoolSize">20</property>
 
 <!-- proxy server client process thread size -->
 <property name="clientSideThreadPoolSize">30</property>
 
 <!-- mysql server data packet process thread size -->
 <property name="serverSideThreadPoolSize">30</property>
 
 <!-- per connection cache prepared statement size -->
 <property name="statementCacheSize">500</property>
 
 <!-- query timeout( default: 60 second , TimeUnit:second) -->
 <property name="queryTimeout">60</property>
 </runtime>
 
 </proxy>
 
 <!-- 
 Each ConnectionManager will start as thread
 manager responsible for the Connection IO read , Death Detection
 -->
 <connectionManagerList> #9.connectionManagerList定義了一系列鏈接管理器,這些鏈接管理器能夠在其餘地方被引用,好比clientConnectioneManager在amoeba.xml中被引用做爲MySQL Proxy Service的客戶端鏈接管理器;defaultManager在dbServers.xml中被引用做爲dbServer的數據庫服務器端鏈接管理器。鏈接管理器主要配置了用於網絡處理的CPU核數,默認其processor屬性爲Amoeba所在主機的CPU核數。
 <connectionManager name="clientConnectioneManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
 <property name="subManagerClassName">com.meidusa.amoeba.net.ConnectionManager</property>
 <!-- 
 default value is avaliable Processors 
 <property name="processors">5</property>
 -->
 </connectionManager>
 <connectionManager name="defaultManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
 <property name="subManagerClassName">com.meidusa.amoeba.net.AuthingableConnectionManager</property>
 
 <!-- 
 default value is avaliable Processors 
 <property name="processors">5</property>
 -->
 </connectionManager>
 </connectionManagerList>
 
 <!-- default using file loader -->
 <dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader">
 <property name="configFile">${amoeba.home}/conf/dbServers.xml</property>
 </dbServerLoader>
 
 <queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
 <property name="ruleLoader">
 <bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
 <property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
 <property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
 </bean>
 </property>
 <property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
 <property name="LRUMapSize">1500</property>
 <property name="defaultPool">master</property>#10.表示默認配置讀寫都會到數據池的master這個角色,在dbServer.xml中定義;
 
 <property name="writePool">master</property>#11.表示只寫的數據池指定master這個名稱的角色;
 <property name="readPool">virtualSlave</property>#12.表示只讀的數據池指定virtualSlave這個名稱的角色;
 <property name="needParse">true</property>
 </queryRouter>
</amoeba:configuration>

ok

7.2配置dbServer.xml

<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">
<!-- 
 Each dbServer needs to be configured into a Pool,
 If you need to configure multiple dbServer with load balancing that can be simplified by the following configuration:
 add attribute with name virtual = "true" in dbServer, but the configuration does not allow the element with name factoryConfig
 such as ‘multiPool‘ dbServer 
 -->
 <dbServer name="abstractServer" abstractive="true"> #1.這份dbServers配置文件中,咱們定義了三個dbServer元素,這是第一個dbServer元素的定義。這個名爲abstractServer的dbServer,其abstractive屬性爲true,這意味着這是一個抽象的dbServer定義,能夠由其餘dbServer定義拓展。
 <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
 <property name="manager">${defaultManager}</property> #2.manager定義了該dbServer選擇的鏈接管理器(ConnectionManager),這裏引用了amoeba.xml的配置
 <property name="sendBufferSize">64</property>
 <property name="receiveBufferSize">128</property>
 <!-- mysql port -->
 <property name="port">3306</property>#3.數據庫端口
 <!-- mysql schema -->
 <property name="schema">dongdong</property>#4.目標數據庫
 <!-- mysql user -->
 <property name="user">haha</property>#5.用於鏈接後端數據庫的用戶,注意須要給他賦予操做上面數據庫的權限;
 <!-- mysql password -->
 <property name="password">haha123</property>#6.haha用戶登錄的密碼
 </factoryConfig>
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">#7.dbServer下有poolConfig的元素,這個元素的屬性主要配置了與數據庫的鏈接池,與此相關的具體配置會在後面詳細介紹。
 <property name="maxActive">500</property>
 <property name="maxIdle">500</property>
 <property name="minIdle">10</property>
 <property name="minEvictableIdleTimeMillis">600000</property>
 <property name="timeBetweenEvictionRunsMillis">600000</property>
 <property name="testOnBorrow">true</property>
 <property name="testWhileIdle">true</property>
 </poolConfig>
 </dbServer><dbServer name="master" parent="abstractServer">#8.這個master是abstractServer的拓展,parent屬性配置了拓展的抽象dbServer,它拓展了abstractServer的ipAddress屬性來指名數據庫的IP地址,而在端口、用戶名密碼、鏈接池配置等屬性沿用了abstractServer的配置。
 <factoryConfig>
 <!-- mysql ip -->
 <property name="ipAddress">192.168.127.141</property>#9.master的地址;
 </factoryConfig>
 </dbServer>
 <dbServer name="slave" parent="abstractServer">
 <factoryConfig>
 <!-- mysql ip -->
 <property name="ipAddress">192.168.127.142</property>#9.slave的地址;
 </factoryConfig>
 </dbServer>
 <dbServer name="virtualSlave" virtual="true">#10. 這一段其實並不須要配置,並不會影響到基本使用。如下大體介紹下此配置的含義:multiPool是一個虛擬的數據庫節點,能夠將這個節點配置成好幾臺數據庫組成的數據庫池。好比上面這個配置中僅配置了一臺server1,負載均衡策略爲ROUNDROBIN(輪詢)。與虛擬數據庫節點相關的詳細教程會在後面的章節中介紹。
 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
 <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
 <property name="loadbalance">1</property>
 <!-- Separated by commas,such as: server1,server2,server1 -->
 <property name="poolNames">master,slave,slave,slave</property>#11.此處master和slave配置出現的此處就是給它們分配請求的比例,此處是1:3
 </poolConfig>
 </dbServer>
</amoeba:dbServers>

補充 定義abstractServer的緣由:當咱們有一個數據庫集羣須要管理,這個數據庫集羣中節點的大部分信息多是相同的,好比:端口號、用戶名、密碼等等。所以經過概括這些共性定義出的abstractServer極大地簡化了dbServers配置文件。

四.運行amoeba以及測試

1./usr/loca/amoeba/bin/amoeba start &

日誌顯示

open socket channel to server[192.168.127.141:3306] success!
open socket channel to server[192.168.127.142:3306] success!

若是沒有顯示就證實沒有鏈接到後端數據庫,筆者以前有一個鏈接不到,結果緣由是配置文件裏面的註釋未去掉,o(╯□╰)o

2.由於實際環境須要master與slave同步,不是本文重點,可看其餘文章;

這裏前提是關閉slave的同步,在slave上  stop slave,可是若是大量測試數據,那麼你可讓slave把master的數據庫同步過來在關閉也ok;

分別在master和slave上建立數據庫

grant all privileges on hehe.* to hehe@‘%‘ indefied by ‘hehe123‘;
 flush privileges;
create database hehe;
 use hehe;
create tables heheta(id int(10),name varchar(20));
insert into heheta (id,name,address)value(‘9,‘master‘,‘100‘); 給master插入數據
insert into heheta (id,name,address)value(‘10‘,‘slave‘,‘101‘);給slave插入數據
而後在amoeba主機上進行登錄以及測試
mysql -uroot -ppassword -h192.168.127.140 -P8066
use heheta;
mysql> select * from heheta;
+------+-------+---------+
| id | name | address |
+------+-------+---------+
| 10 | slave | 101 |
+------+-------+---------+
1 row in set (0.01 sec)
mysql> select * from heheta;
+------+-------+---------+
| id | name | address |
+------+-------+---------+
| 10 | slave | 101 |
+------+-------+---------+
1 row in set (0.00 sec)
mysql> select * from heheta;
+------+-------+---------+
| id | name | address |
+------+-------+---------+
| 10 | slave | 101 |
+------+-------+---------+
1 row in set (0.01 sec)
mysql> select * from heheta;
+------+--------+---------+
| id | name | address |
+------+--------+---------+
| 9 | master | 100 |
+------+--------+---------+
1 row in set (0.01 sec)

讀取比例master:slave=1:3

插入數據測試
insert into heheta(id,name,address)value(‘11‘,‘adddata‘,‘102‘);
查詢只能在負責寫入數據的master上纔會有數據
mysql> select * from heheta;
+------+-------+---------+
| id | name | address |
+------+-------+---------+
| 10 | slave | 101 |
+------+-------+---------+
1 row in set (0.01 sec)
mysql> select * from heheta;
+------+---------+---------+
| id | name | address |
+------+---------+---------+
| 9 | master | 100 |
| 11 | adddata | 102 |
+------+---------+---------+
2 rows in set (0.02 se
相關文章
相關標籤/搜索