資料庫架構規劃有許多方式,例如:
- master-slave 架構
- 雙主架構
- cluster
- MHA 等架構
此文章會介紹教學如何架設 mariadb cluster。
而 mariadb galera cluster 提供了同步複製的功能,不會像 master-slave 那樣是異步的(會有延遲)。
特點如下:
- 任意節點的資料庫都是可讀可寫
- 自動剔除故障節點
- 自動增加節點
- 自動行級別的複製
同步複製的優點如下:
- 高可用(當節點當機時,資料不會遺失,因為資料一致性高)
- 跨叢集
- 高可用
缺點:
- 因為複製是同步的, 因此當節點數量越多時,較容易發生死鎖等問題
開始建置 mariadb cluster,以下範例準備兩台 ubuntu 18.04
- maraidb_1 ip 位址: 192.168.33.10
- maraidb_2 ip 位址 192.168.33.11
1.首先透過指令更新 ubuntu
sudo apt-get update -y
2. 安裝 maraidb-server 套件
sudo apt-get install mariadb-server -y
安裝完成後啟動 maraidb-server 以及 enable (開機時立馬啟動)
sudo systemctl start mariadb
sudo systemctl enable maraidb
接著透過 status 查看 maraidb 狀態
sudo systemctl status maraidb
初次安裝完 maraidb 時要使用 mysql_secure_installation 設定 mariadb 相關設定
sudo mysql_secure_installation
接著會出現如下問題:
- Enter current password for root (enter for none)
這邊因為還沒有設定密碼因此直接按 enter
2. Set root password? [Y/n]:
要設定 root 的密碼, 因此輸入 Y
3. New password:
輸入 root 的密碼
4. Re-enter new password:
再次輸入 root 密碼
5. Remove anonymous users?[Y/n]
是否移除匿名使用者, 這邊案 Y 刪除
6. Disallow root login remotely? [Y/n]
是否禁止別人使用 root 進行遠端登入, 為了安全請見,這邊輸入 Y
7. Remove test database and access to it? [Y/n]
是否刪除測試用的 database, 這邊也輸入 Y
8. Reload privilege tables now? [Y/n]
是否重新加載權限資訊, 這邊也輸入 Y
新增 sst_user for galera cluster 使用
- GRANT USAGE ON *.* to sst_user@’%’ IDENTIFIED BY ‘sst_user’;
創建 sst_user 帳號並且密碼為 sst_user
2. GRANT ALL PRIVILEGES on *.* to sst_user@’%’;
設定所有權限給 sst_user
3. FLUSH PRIVILEGES
權限 flush
安裝完成後接下來要設定 galera cluster 的設定檔
sudo vim /etc/mysql/my.cnf
my.cnf 內容如下
[galera]
wsrep_on = ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name="galera_cluster"
wsrep_cluster_address="gcomm://192.168.33.10,192.168.33.11"
wsrep_slave_threads=4 # 預設為1, 盡量設定成 CPU 數量的 4 倍binlog_format=ROW
default_storage_engine=InnoDBbind-address=0.0.0.0wsrep_node_name=node1
wsrep_node_address="192.168.33.10"
wsrep_sst_method=rsync
wsrep_sst_auth=sst_user:sst_userlog_error = /var/log/mysql/error.log
接著在第二台也做類似的設定, 只是 galera conf 的 wsrep_node_address 以及 wsrep_node_name 需要設定第二台的資料, 如下
wsrep_node_address="192.168.33.11"
wsrep_node_name=node2
設定完之後將每一台的 mariadb 先停止
sudo systemctl stop mariadb
都停止後再 node1 透過以下指令初始化 Galera Cluster 設定
sudo galera_new_cluster
接著可以透過以下指令查看 cluster 的節點數量,
在 node1 輸入以下值令
- 先進入 mysql
sudo mysql -uroot -p
2. 檢查 mariadb cluster 節點數量
show status like 'wsrep_cluster_size'
3. 接著進入 node2 的機器,將 mariadb 啟起來
sudo systemctl start mariadb
4. 接著在 node1 再重新下一次檢查節點數量的指令, 此時可以看到節點數量變為 2 個
show status like 'wsrep_cluster_size'
接著可以在 node1 去創建 database 後, 再去查考 node2 是否也同步新增了 node1 創建的 database
- 在 node1 新增 database 測試是否有同步複製
create database test
2. 在 node1 檢查是否有 test 的 database 被創建
show databases
3. 在 node2 也下 show database 此時會看到 node2 也多出了 test 的 database
建置 load balance 去分流 mysql 流量, 需要在建置一台 ubuntu 18.04 機器,
且該機器 ip 為 192.168.33.12
而HaProxy 還可以做到 failover, 當一個節點故障的話, 可以將使用者導向正常的節點
- 安裝 haproxy
sudo apt-get install haproxy
2. 接著我們看一下 haproxy 的設定檔
sudo vim /etc/haproxy/haproxy.cfg
會看到基本配置如下
global
# log required rsyslog log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s # user and group will be run as
user haproxy
group haproxy
daemon# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
在最上面設定 galera 的設定
listen galera
bind 192.168.33.12:3306
balance roundrobin # load balancer policy
mode tcp # (tcp 設置為 layer 7 , http 為 layer 4)
option tcpka # enable keepalive to maintain tcp connection
option mysql-check user haproxy # enable database server check
server node1 192.168.33.10:3306 check weight 1
server node2 192.168.33.11:3306 check weight 1
也可以查看 haproxy 節點等狀態
listen stats
bind 0.0.0.0:9000
mode http
stats enable # 啟用狀態
stats uri /stats # 網址路徑
stats realm HAProxy\ Statistics
stats auth howtoforge:howtoforge # 設定帳號密碼
stats admin if TRUE # 設定使用者登入後為管理者
stats refresh 30s # 每 30 秒刷新監控畫面
接著在網頁分頁輸入 http://192.168.33.12:9000/stats, 帳密為 howtoforge, 即可查看狀態, 如下
設定好之後重啟 haproxy
sudo systemctl restart haproxy
緊接著在任一個節點的 mysql 新增 mysql-check 的 user , 上方設定為 haproxy, 因此要建立 haproxy 的 user
首先進入 mysql
sudo mysql -uroot -p
接著新增 haproxy user
create user 'haproxy'@'192.168.33.12'; # 帳號@ip
重新刷新權限
flush privileges;
接著為了測試 haproxy 是否將我們導向不同的 mariadb , 我們對每個節點的 mariadb 設定專屬的 server-id
sudo mysql -h192.168.33.10 -uroot -p -e "SET GLOBAL server_id=167"sudo mysql -h192.168.33.11 -uroot -p -e "SET GLOBAL server_id=168"
透過以下指令檢查是否取得的 server id 每次都不同
sudo mysql -h192.168.33.12 -uroot -p -e "show variables like 'server_id'"
會發現每次取得的 server_id 都不同, 即代表 haproxy 做了 load balance
我們上面有講到 load balance policy, 而上方的範例的 balance policy 是使用 roundrobin
- Round Robin (roundrobin):
會根據 weight 有順序的循環將使用者導向到特定的節點
2. Static Round Robin(static-rr)
3. Least Connection (leastconn)
將使用者導向至連線數較少的節點
4. First
5. Source Tracking (source)
透過 ip range 將使用者導向到特定的節點, 因此相同的 ip 會被導向到相同的節點
haproxy logger 是使用 rsyslog
haproxy logging 參考資料
使用 galera cluster 建置 master-slave replication
# 以下操作皆在 mater node
先在 node1 的 my.cnf 設定參數
sudo vim /etc/mysql/my.cnf
要設定 replication 的話要多設定以下參數
server-id
log_slave_updates
wsrep_gtid_mode
wsrep_gtid_domain_id
log-bin
log-bin-index
gtid_domain_id
在 mariadb.cnf 設定以上參數
[mysqld]
wsrep_gtid_mode=on
wsrep_gtid_domain_id=1 # 每個節點設定一樣
log_slave_updates=on # 在 master node 設定此參數
server-id=1 # 每個節點設定一樣
log-bin=/var/log/mysql/master-bin
log-bin-index/var/log/mysql/master-bin.index
設定完 mariadb.cnf 後, 將所有節點的 mariadb 都先停止
sudo systemctl stop mariadb
重新初始化 galera cluster
sudo galera_new_cluster
以及在節點 2 將 mariadb 啟起來
sudo systemctl start mariadb
新增一個供 replication 存取 master 資料的帳號
create user 'replicant'@'%' identified by 'replicant';# 帳號密碼為 replicant
給予 replicant 帳號 replication slave 權限
grant replication slave on *.* to replicant;
倘若連線要求要使用 tls 的話, 要使用以下指令
grant replication slave on *.* to replicant require ssl;
權限資料表 flush
flush privileges;
緊接著在 slave node 做以下的設定
sudo vim /etc/mysql/my.cnfor sudo vim /etc/mysql/mariadb.conf.d/50-sever.cnf
啟用 reply log 等設定
[mysqld]
server-id = 2 # 要設定的跟 master node 不同
relay-log = /var/log/mysql-reply-bin
relay-log-index= /var/log/mysql-reply-bin.index
gtid_domain_id = 99 # 要設定的跟 master node 不同log-bin = /var/log/mysql/slave-bin
log-bin-index = /var/log/mysql/slave-bin.index
binlog_format = mixedread-only = 1 # enable readonly
innodb-read-only = 1 # 禁止任何人 change or delete 資料
假如只要 replicate 特定的 database 要做如下設定
replicate-do-db = db1
在 slave node 設定完成之後, 重啟 mariadb
sudo systemctl restart mariadb
接著在 node1 的 mysql 取得 binlog_pos
- 進入 mysql
sudo mysql -uroot -p
2. 查看 gtid_binlog_pos, 在後面會需要在 slave 設定這個 pos
show variables like 'gtid_binlog_pos'# gtid => global tranaction id
接著回到 slave node 設定要同步哪個 master node 資料
sudo mysql -uroot -pset global gtid_slave_pos = '1-1-3'; # 設定成 gtid_binlog_poschange master 'master01' to
master_host = '192.168.33.10',
master_user = 'replicant',
master_password = 'replicant',
master_port = 3306,
master_connect_retry = 10,
master_use_gtid_slave = slave_pos;
設定 connection name 為 master01
然後啟用 connection
start slave 'master01'; // master01 為 connection name
顯示 master01 connection 狀態
show slave 'master01' status \G; // 顯示 master01 connection 狀態
會看到如下資訊
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Slave_IO_Running: 會去讀取 master 的 binary log
Slave_SQL_Running: 會去讀取 relay log , 並且執行 transaction
停止 replication
stop slave 'master01';
重置 replication
reset slave 'master01';
接著可以來檢查一下 slave 是否會同步 master 的資料
我會在 node1 新增一個 database
create database test1
建立完 test1 後, 再去 slave node 看是否有多出 test1 database
show databases
也可以看一下 master 的 gtid_binlog_pos 跟 slave 的 gtid_slave_pos 是否同步
發現資料一致, 代表 master-slave 資料已同步
倘若機器因為一些原因重後起動後, 導致無法重新執行 sudo galera_new_cluster 的話, 可以使用如下方式
sudo vim /var/lib/mysql/grastate.dat
接著將 safe_to_bootstrap 改為 1
safe_to_bootstrap: 1
設定完後再重新執行 sudo galera_new_cluster 即可正常運行
參考資料:
- http://benjr.tw/95536
- https://akuma1.pixnet.net/blog/post/171497747-mariadb-cluster-%e6%9e%b6%e8%a8%ad%ef%bc%8d%ef%bc%8d%ef%bc%88%e4%ba%8c%ef%bc%89cluster%e7%92%b0%e5%a2%83%e8%88%87mariadb
3. https://www.howtoforge.com/how-to-setup-mariadb-galera-cluster-on-ubuntu-20-04/
5. https://galeracluster.com/library/documentation/ha-proxy.html
7. https://www.linuxbabe.com/mariadb/galera-cluster-ubuntu
8. https://cyral.com/blog/how-to-galera-mariadb-haproxy/
9. https://medium.com/platformer-blog/highly-available-mysql-with-galera-and-haproxy-e9b55b839fe0
11. https://www.linuxbabe.com/mariadb/master-slave-replication-galera-cluster