星期三, 8月 10, 2011

MySQL Proxy & Amoeba

做MySQL的效能多會用load balance
目前MySQL的load balance多採用官方的MySQL Proxy及大陸的Amoeba
以下整理網路上收集到的資訊,挺多簡體翻的 要習慣一下
  • MySQL Proxy
    安裝:mysql proxy讀寫分流(一)-mysql proxy的安裝方式
    說明:MySQL Proxy位於 client及MySQL server(s)中間
    MySQL Proxy可以monitor, analyze or transform their communication. 可達到:
    • load balancing
    • failover
    • query analysis
    • query filtering and modification
    • ... and many more. 
  • Amoeba
    安裝:Amoeba For MySQL 實現資料庫負載平衡(讀寫分離)
    說明:Amoeba 也位於Client、Database Server(s)之間
     Amoeba 具有負載均衡、高可用性、 sql過濾
    可承受達到讀寫分離、Query Route(解析sql query語句,並且根據條件與預先設定的規則,請求到指定的目標數據庫。可並發請求多台數據庫合併結果)
    對客戶端透明。主要降低數據切分帶來的複雜多數據庫結構、數據切分規則給應用
    帶來的影響。
  • 比較 in action

    • Load Blance及讀寫分離
      Master:Server1(可讀寫)
      Slaves:Server2, Server3, Server4(3個平等的數據庫。只讀/負載均衡)

      • MySQL Proxy
        #設定db server變數
        Server1=10.1.1.1  #master
        Server2=10.2.1.1  #slave1
        Server3=10.3.1.1  #slave2
        Server4=10.4.1.1  #slave3
        ROOT_DIR=/usr/local

        #指定讀寫server
        LUA_PATH="$ROOT_DIR/mysql-proxy/share/mysql-proxy/?.lua" $ROOT_DIR/mysql-proxy/sbin/mysql-proxy \
        --daemon \
        --proxy-backend-addresses=$Server1:3306 \
        --proxy-read-only-backend-addresses=$Server2:3306 \
        --proxy-read-only-backend-addresses=$Server3:3306 \
        --proxy-read-only-backend-addresses=$Server4:3306 \
        --proxy-lua-script=$ROOT_DIR/mysql-proxy/share/mysql-proxy/rw-splitting.lua

        這個例子中10.1.1.1為可寫
        限制10.2.1.1,10.3.1.1,10.4.1.1只能讀
      • Amoeba
        amoeba提供讀寫分離pool相關配置。並且提供負載均衡配置。
        可配置server2、server3、server4形成一個虛擬的 virtualSlave,該配置提供負載均衡、failOver、故障恢復功能
        <dbServer name=“virtualSlave” virtual=“true”>
        <poolConfig>
        <className>com.meidusa.amoeba.server.MultipleServerPool</className>
        <!-- 負載均衡參數 1=ROUNDROBIN , 2=WEIGHTBASED -->
        <property name="loadbalance">1</property>

        <!-- 參與該pool負載均衡的poolName列表以逗號分割 -->
        <property name="poolNames"> Server2,Server3,Server4</property>
        </poolConfig>
        </dbServer>

        指派讀寫機
        <queryRouter>
        <className>com.meidusa.amoeba.mysql.parser.MysqlQueryRouter</className>
        <property name="LRUMapSize">1500</property>
        <property name="defaultPool">server1</property>

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

        <property name="needParse">true</property>
        </queryRouter>
        那麼遇到update/insert/delete將 query語句發送到 wirtePool,將 select發送到 readPool機器中執行。
    • 資料分割
      • MySQL Proxy
      • Amoeba
        SELECT * from user_event where user_id='test' and gmt_create between Sysdate() -1 and Sysdate()

        如果根據gmt_create 時間進行數據切分,比如 6個月進行切分一次
        amoeba提供利用類似sql表達式進行數據切分:
        • 規則1(對應服務器1):
          GMT_CREATE > to_date('2008-01-01','yyyy-mm-dd')
          AND GMT_CREATE < to_date('2008-05-31','yyyy-mm-dd')
        • 規則2(對應服務器2)
          GMT_CREATE > to_date('2008-06-01','yyyy-mm-dd')
          AND GMT_CREATE < to_date('2008-12-31','yyyy-mm-dd')
        上面的sql的條件 gmt_create 與規則裡面的的gmt_create 進行交集判斷,如果存在交集則表示符合規則。 則會將sql轉移到 規則1 的相應的服務器上面執行。
        利用amoeba寫出這種類似規則很容易,但是要想做到數據切分以後可線性擴容,那麼這樣的規則需要自己根據業務實際情況進行設置。
        amoeba可同時將sql 並發分發到多台服務器、然後將結果合併再反饋給客戶端,而且amoeba內部現成採用無阻塞模式,工作線程是不會等待的,並發請求多台 database server情況下,客戶端等待的時間基本上面是性能最差的那台 database server+amoeba內部解析協議的時間

    注意事項

    沒實作過,也不知要注意什麼 還是看別人寫的吧
    • MySQL Proxy
      • 同步延遲問題
        寫入後,其他slaves的同步問題,MySQL Proxy如何解決同步延遲問題
      • 資料是亂碼
        有看到2種解決方法,還沒試過
        • 設定mysql server
          set names "utf8"也沒有效果。
          [mysqld]
          skip-character-set-client-handshake
          init-connect='SET NAMES utf8'
          default-character-set=utf8
        • 修改/etc/my.cnf 設定檔
          加入底下設定,即可解決亂碼問題(當然您要依據您的環境做修改)
          default-character-set = utf8
          skip-character-set-client-handshake
          character-set-server = utf8
          collation-server = utf8_general_ci
          init-connect = SET NAMES utf8
    • Amoeba
        MySQL使用Amoeba作为Proxy时的注意事项 以下是截錄的
      • Amoeba不支持事务
        p.s. 還不知道"事務"是什麼 不過官網似乎提到有支援了
      • Amoeba不支持跨库join和排序
        跨庫的join和排序非常消耗資源,會導致性能嚴重下降,Amoeba沒有進行支持,只能做到分數據庫實例。
      • Amoeba不支持大數據量的查詢。
        不適合返回大量(超過10萬)數據的查詢,大數據量的查詢非常消耗內存,Amoeba在進行大數據量查詢時性能會非常差。當然,實際業務中需要進行大數據量查詢的情況會非常少或者根本沒必要實現這種情況。這裡所謂的大數據量查詢指的是一次查詢結果超過十萬行。
      • Amoeba需要更嚴格的SQL語句規範
        From 關鍵字後面如果不是子查詢,一律不能帶括號」()」;
        如果的表中字段名與關鍵字或者函數名一樣需要帶上字符` (比如:mytable.`order`)
      • 與直接操作mysql數據庫相比,amoeba性能的損失大概在怎麼一個範圍?
        amoeba是屬於代理層,起碼要消耗2次網絡IO,加上amoeba自身的計算時候的消耗,
        如果數據庫的性能非常高,或者sql的執行並不消耗數據庫的磁盤IO,那麼這時候完全不能體現amoeba的好處,反而會降低整體的性能。具體數據目前沒有算過。

    結論

    • 學習曲線
      由於MySQL Proxy需透過Lua Script
      看起來不難,不過要初學者在linux去碰這東西,還真是有難度

      而Amoeba設定就簡單的多
      只需要進行相關的XML配置就可以滿足需求
      SQLJEP語法寫規則
      雖然lua也不難,但比起設定檔的學習曲線還是有差
    • 效能方面
      比官方的mysql proxy性能大致低10%~20%左右
      在一次請求數據量比較大的情況下比如好幾千條數據,性能有所下降,這個原因是由於解析了mysql與客戶端之間交互的所有數據包,而mysql proxy在沒有使用lua特定腳本的時候是不會解析mysql數據包
      並發能力來說比mysql proxy會更強勁,還有穩定性方面都比mysql proxy強。從使用的連接數來看,在相同的客戶端並發連接情況下,與mysql數據庫的連接數將比mysql proxy少一半。
      在0.27版本以後,amoeba的性能逐漸超過了MySQL Proxy
    • 文件支援
      維護amoebad的人似乎不多
      在官網查相關文件都有些不清楚
      問題回覆也沒有歸類,有問題不好解決
    • 穩定性
      覺得Amoeba太新了
      官網上也有不少人回應bug的事
      穩定性也是需要考量的地方
    References

沒有留言: