前陣子一直在尋找MySQL負載平衡的方式,搞了一陣子後終於暫告一個段落,趁著記憶猶新時趕快做個筆記,給有需要的人參考,自己日後也可以參考啦!
網路上有很多人提供MySQL的負載方式,例如:Master Slave架構、MySQL MMM架構、DRBD、Cluster、HeartBeat…等一堆MySQL負載平衡的架構,一直MySQL負載平衡的架構,到底要選擇那一個方式才是最好的?
認為符合自己個人(公司)需求的架構最好,再來是穩定及簡單好維護;如果只是單純的公司形象網站或者是一般個人的Blog,總不能想著要架構Master + Slave,外加做讀寫分流,再替Master做個HeartBeat的備援,再後再加幾台memcached來加快搜尋速度….等,如果只是為了測試架構倒是可以玩一玩,如果是要用在運作中的主機的話,那丫忠勸您要3思 再3思了,不要搞到後來出問題時找不到問題,或者資料不一致時,到時候拜再多的神也沒用囉…
講了一堆哩哩扣扣都還沒進入主題,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 M/S的運作原理之後,再來就是MySQL的設定了,假設要完成的架構如下:
- Master:192.168.10.2
- Slave:192.168.10.3
- 只有同步(Replication) 資料庫mytest
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 = mytest #只針對mytest產生binlog
3. 在Replication完成前,Master跟Slave的資料必須一致,故在匯出資料前先Lock成唯讀
mysql > FLUSH TABLES WITH READ LOCK;
4. 將mytest資料庫整個匯出,此方式可以使用mysqldump或者是tar的方式把檔案壓縮起來,底下範例使用mysqldump的方式匯mytest的資料
$mysqldump -u root -p mytest > mytest.sql #將mytest的資料匯出成mytest.sql
5. 將資料匯出後,解除資料唯讀狀態
mysql>UNLOCK TABLES;
6. 重新啟動mysql,讓剛設定的my.cnf生效;重新啟動後,在Master主機上的add、update、delete等動作都會記錄在binlog檔案中
$/etc/init.d/mysql restart
7. 最後將mytest.sql拷貝(scp)至slave主機,如果這時候你問丫忠怎麼沒有scp的詳細指令,那丫忠可能會暈倒躺給你看@@….
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 = mytest #限制slave只同步mytest資料庫的資料
master-connect-retry = 60 #當slave無法連線至master時,間隔60秒嘗試連線(預設為60秒)
2. 將mytest的資料匯入
$mysql -u root -p mytest < mytest.sql
3. 設定Master主機的相關訊息,讓Slave知道Master的位置
以往的方式是直接在my.cnf中設定master的相關訊息;但是,這樣的方式已經改了,必須使用在 mysql下執行【CHANGE MASTER TO】的指令
底下在my.cnf中設定master是錯誤的
master-host = 192.168.10.2
master-user = repl
master-password = slavepass
master-port = 3306
請在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上面更新mytest資料庫裡面的資料後,再至slave查看是否有更新,就可以確認了
接下來是在此架構上再加上一個MySQL Proxy,來達到Read Write分離的架構了^^Y