Site icon Soul & Shell Blog

MySQL Replication 主從式架構設定教學

MySQL Replication 機制

資料庫可以說是應用程式的核心,但關聯式資料庫 (RDBMS) 基於 ACID 設計原則,傳統架構導致在運算能力的擴展上,變得不容易實現。擴充上除了典型的 Scale-up (擴充單一硬體能力) 之外,最常使用的就是 Replication 技術,Replication 泛指資料複製模式,會把資料完整的複製到另一個 MySQL 節點上,這樣的方式並不是分散儲存喔。

目前常使用且成熟的關聯式資料庫,一般官方都會提供 Replication 機制,通常官方內建的 Replication 機制已經很成熟,不像幾年前 Open Source RDBMS 都要自己編譯第三方 Replication 功能,當然也有第三方像是 Percona 這樣的套件。透過 Replication 將資料同步複製到其他主機,可以實現運算的擴充與高可用架構。大部分的資料庫應用情境都是 SELECT 居多,最常用到的就是讀寫分離的「主從架構」,如下圖所示:

主要的 MySql Master 節點負責「讀寫」,寫資料會透過 Binlog Relay 機制,以非同步模式複製 Binlog 到每一台 Slave 執行 (正確一點的說法應該是 Slave 透過 REPLICATION 權限連線到 Master 去抓 Binlog 回來執行),運作時就好像讓 Slave 與 Master 進行資料同步。一般來說,Slave 不提供寫入功能,只負責分散 SELECT 運算,這也是最典型的擴充架構。實作時有一個地方很麻煩,就是應用程式必須自行實作「讀寫分離」的機制 (有些 Framework ORM 會內建),自行再程式邏輯將 SELECT Query 分散到 Slave 執行,除非有使用商業的 Proxy Connection Pool 機制,才有提供自動讀寫分離的機制。如果是使用 MariaDB 的話也可以搭配 MaxScale 實現讀寫分離機制,但 MaxScale 我沒玩過,只是打打嘴砲。

此外,建構 Replication 還有一個很重要的好處,就是可以順便備份!一般的情況我們都是用 mysqldump 進行資料備份對吧!?但是如果你的資料已經大到一定的程度,想要 Dump DB 絕對是 GG,搞不好跑個日備份就超過一天了....... 這時候就要借助 Replication 的能力。

建置 MySQL Replication 主從架構環境

廢話說完了,那先來看看如何建置 MySql Master/Slave 這種最典型的架構。以 Ubuntu Server 14.04 為例,首先分別在兩台 Master 與 Slave 機器上,安裝官方提供的 MySQL Server (目前版本是 5.5),如下:

sudo apt-get install mysql-server

設定 MySql Master

我們先設定 Master,修改位於 /etc/mysql/my.cnf 的 MySQL 設定檔,內容如下 (GitHub):

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
bind-address    = 0.0.0.0
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

key_buffer         = 16M
max_allowed_packet = 16M
thread_stack       = 192K
max_connections    = 5000
table_cache        = 64
thread_concurrency = 8
query_cache_limit  = 1M
query_cache_size   = 16M
query_cache_type   = 1

log_error          = /var/log/mysql/error.log
log_slow_queries   = /var/log/mysql/mysql-slow.log
long_query_time    = 2
log-queries-not-using-indexes

# 需要才打開 slow log
server-id          = 1
log_bin            = /var/lib/mysql/mysql-bin.log
log-slave-updates  = 0
expire_logs_days   = 10
max_binlog_size    = 100M
innodb_flush_log_at_trx_commit = 1
sync_binlog        = 1
read_only          = 0

# innodb tune (optional)
innodb_change_buffering      = all
innodb_adaptive_hash_index   = ON
innodb_max_dirty_pages_pct   = 80
innodb_buffer_pool_size      = 256M
innodb_buffer_pool_instances = 2

[mysqldump]
quick
quote-names
max_allowed_packet = 16M

!includedir /etc/mysql/conf.d/

說明一下設定檔的幾個重點:

設定好之後重新啟動 MySql Server

sudo service mysql restart

重新啟動後透過 mysql 進入 shell,接著執行以下 SQL 建立用來 Replication 連線的使用者(請自行更換 <password> 為您的連線密碼),如下:

USE mysql;
CREATE USER 'replication'@'%' IDENTIFIED BY '<password>';
GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';
FLUSH PRIVILEGES;

接著透過 SHOW MASTER STATUS\G 命令查看 Master 執行狀態,如果沒有啟動可以執行 MASTER START 來啟動。執行畫面如下:

記下 File 與 Position 這兩個資訊,等等要設定到 Slave 進行同步。

接著我們設定另一台 Slave 節點,my.cfg 內容如下 (GitHub):

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
bind-address    = 0.0.0.0
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

key_buffer         = 16M
max_allowed_packet = 16M
thread_stack       = 192K
max_connections    = 5000
table_cache        = 64
thread_concurrency = 8
query_cache_limit  = 1M
query_cache_size   = 16M
query_cache_type   = 1

# 需要才打開 slow log
log_error          = /var/log/mysql/error.log
log_slow_queries   = /var/log/mysql/mysql-slow.log
long_query_time    = 2
log-queries-not-using-indexes

server-id          = 2
log_bin            = /var/lib/mysql/mysql-bin.log
log-slave-updates  = 0
expire_logs_days   = 10
max_binlog_size    = 100M
innodb_flush_log_at_trx_commit = 1
sync_binlog        = 0
read_only          = 1

# innodb tune (optional)
innodb_change_buffering      = all
innodb_adaptive_hash_index   = ON
innodb_max_dirty_pages_pct   = 80
innodb_buffer_pool_size      = 256M
innodb_buffer_pool_instances = 2

[mysqldump]
quick
quote-names
max_allowed_packet = 16M

!includedir /etc/mysql/conf.d/

說明一下 Slave 設定檔幾個不同的地方:

設定好之後重新啟動 MySql,透過 root 使用者登入後開始設定 Replication 連線,如下:

SLAVE STOP;

CHANGE MASTER TO
  MASTER_HOST='mysql-master',
  MASTER_USER='replication',
  MASTER_PASSWORD='<password>',
  MASTER_LOG_FILE='mysql-bin.00005',
  MASTER_LOG_POS=529;

SLAVE START;

由於我比較習慣用 hosts 管理主機,MASTER_HOST 請填上要連線的 Master 位置,密碼就是剛剛 Master 設定的那一組。還記得 Master 啟動後要記下的資訊嗎 (請看上一張圖)?那個資訊就是要填在 MASTER_LOG_FILE 與 MASTER_LOG_POS 這兩個欄位,Slave 才知道要重哪個點開始同步。完成後 SLAVE START 來啟動同步工作,輸入 SHOW SLAVE STATUS\G 可以看到同步的狀態,畫面如下:

看到這樣的畫面就算完成囉。

測試 MySql Replication

測試一下,首先在 Master 建立資料庫與建立一張 Table 並且 Insert 資料:

接著到 Slave 看看

資料過去了,是不是很無聊

透過 HAProxy 實現 MySQL 主備自動切換

今天介紹的主從架構只能分散運算,並無法實現 HA 能力,如果採用 Master/Master 的配置方式就可以實現了,但是應用程式要如何判斷其他一台機器出問題呢?我們可以藉由 HAProxy 這個套件來實現。將其中一台機器上線,另一台基器備援 (Replication),當第一台機器發生問題時,自動由 HAProxy 轉接連線至備援機,以實現 HA 模式。HAProxy 的設定方式在 GitHub 上,這裡我們就不按圖施工囉,先介紹到這。掰啦.......

Exit mobile version