MySQL Replication(Master Slave負載平衡)實作

網路上有很多人提供MySQL的負載方式,例如:Master Slave架構、MySQL MMM架構、DRBD、Cluster、HeartBeat…等一堆MySQL負載平衡的架構,一直MySQL負載平衡的架構,到底要選擇那一個方式才是最好的?
MySQL 的M/S架構(Master Slave)是負載平衡中最基礎的架構,也就是很多的架構都是從此延伸出去。如果可以閱讀英文的網友可以直接參考MySQL官網的資料 http://dev.mysql.com/doc/refman/5.0/en/replication.html

MySQL M/S架構的原理大致如下:
1.  新增(Add)、刪除(delete)、修改(update)的動作必須移至Master
2. Master會針對這些動作的語法自動產生binlog 檔案
3. Master會將binlog檔案同步(Replication)至所有的Slave
4. Slave會執行binlog檔案中的SQL語法

原理的圖形概念如下:


看到這個架構的原理,或者有些網友就想到了,程式中針對MySQL的動作(SELECT、UPDATE、DELETE、ADD…)都是固定在同一台MySQL中運作,除非是修改程式,否則要怎樣將讀寫分開呢?這個部份就要加入MySQL Proxy的概念了,MySQL Proxy可以自動將讀寫分開,不用修改程式碼,不過本章的重點不是在MySQL Proxy,有興趣的網友可以先參考 http://forge.mysql.com/wiki/MySQL_Proxy

了解MySQL M/S的運作原理之後,再來就是MySQL的設定了,假設要完成的架構如下:

    Master:192.168.1.215
    Slave:192.168.1.212
    只有同步(Replication) 資料庫test
    mysql版本:5.1.73(不同版本設定不太一樣)

MySQL Replication Master設定

Master要做的流程大概如下:
1. 設定 一個同步的帳號(如果是用root,可以忽略此步驟)
2. 設定my.cnf
3. 將資料庫變成唯讀(read only)
4. 將mytest資料匯出(mysqldump或tar)
5.  解除資料唯讀狀態
6. 重新啟動mysql讓剛設定的my.cnf 生效
7. 將匯出的資料拷貝(scp)至slave

下面針對Master流程的部份,做個詳細說明:
1. 設定一個同步的帳號repl,密碼為slavepass,讓repl具有REPLICATION的權限,相關指令如下:

    $mysql -u root -p    #進入mysql
    mysql>CREATE USER ‘repl’@'%’ IDENTIFIED BY ‘slavepass’;
    mysql>GRANT REPLICATION SLAVE ON *.* TO ‘repl’@'%’;

2. Master主機必須產生binlog檔案,並且指定只有同步 mytest 這個資料庫,/etc/my.cnf 的修改如下:

    [mysqld]
    server-id = 1   #此id不可以重覆
    log-bin = mysql-bin  #指定產生binlog檔案的開頭檔名
    binlog-do-db = test   #只針對mytest產生binlog,若想要同步全部就不要寫
    #bind-address = 127.0.0.1 開啟3306port

3. 在Replication完成前,Master跟Slave的資料必須一致,故在匯出資料前先Lock成唯讀

    mysql > FLUSH TABLES WITH READ LOCK;

4. 將mytest資料庫整個匯出,此方式可以使用mysqldump或者是tar的方式把檔案壓縮起來,底下範例使用mysqldump的方式匯mytest的資料

    $mysqldump -u root -p test > test.sql       #將mytest的資料匯出成test.sql

5. 將資料匯出後,解除資料唯讀狀態

    mysql>UNLOCK TABLES;

6. 重新啟動mysql,讓剛設定的my.cnf生效;重新啟動後,在Master主機上的add、update、delete等動作都會記錄在binlog檔案中

    $/etc/init.d/mysql restart

7. 最後將mytest.sql拷貝(scp)至slave主機

MySQL Replication Slave設定

Slave要做的流程大概如下:
1. 修改my.cnf
2. 匯入mytest資料庫的資料
3. 設定Master主機的相關訊息
4. 重新啟動mysql

下面針對Slave流程的部份,做個詳細說明:
1.  設定my.cnf相關訊息

    [mysqld]
    server-id = 2  #此id不可以重覆
    log-slave-updates   #告訴slave讀取binlog,啟動slave的重要選項之一
    log-bin = mysql-bin   #指定產生binlog檔案的開頭檔名
    binlog_format = mixed    #設定binlog的儲存格式,(maxed為預設值)
    relay-log = host_name-relay-bin    #記錄著binlog處理的過程,可以執行【FLUSH LOGS】讓mysql自動刪除較舊的檔案
    replicate-do-db = test    #限制slave只同步mytest資料庫的資料,若想要同步就不要寫
    master-connect-retry = 60   #當slave無法連線至master時,間隔60秒嘗試連線(預設為60秒)

2. 將test的資料匯入

    $mysql -u root -p test < test.sql

3. 設定Master主機的相關訊息,讓Slave知道Master的位置

以往的方式是直接在my.cnf中設定master的相關訊息;但是,這樣的方式已經改了,必須使用在 mysql下執行【CHANGE MASTER TO】的指令

底下在my.cnf中設定master

    master-host            = 192.168.1.215
    master-user            =  repl
    master-password = slavepass
    master-port            = 3306

*較新的mysql版本可以試試看在mysql下執行底下指令

    mysql>CHANGE MASTER TO
    MASTER_HOST=’192.168.10.2′,
    MASTER_USER=’repl’,
    MASTER_PASSWORD=’slavepass’;

4. 重新啟動mysql

    $/etc/init.d/mysql restart

設定完MySQL的M/S架構後,再來就是檢查及測試的動作了

要如何確定mysql slave是否正常運作?

因為使用phpMyAdmin工具,只要登入phpMyAdmin後,在【狀態】的分頁中往下拉,會看到一個Slave status的狀態表
如果底下2行都出現Yes的話表示slave是在執行中
Slave_IO_Running Yes
Slave_SQL_Running Yes

當然您也可以在mysql下執行【show slave status;】但是,顯示出來的格式有點亂,看不清楚是否正在執行

要如何關閉、啟動slave?

    mysql>slave stop;     #關閉slave服務
    mysql>slave start;    #啟動slave服務

測試資料是否有同步?

在master上面更新test資料庫裡面的資料後,再至slave查看是否有更新,就可以確認了

同步設定的過程中可能會發生錯誤例如 Slave_IO_Runnig No等等
請先用telnet 測試3306 port是否可以正常連線,記得iptables 3306開啟

留言

這個網誌中的熱門文章

c語言-關於#define用法

CMD常用網管指令

PHP 與 JavaScript 之間傳值利用 json