技術分享 | ProxySQL 搭配 MySQL HA (下)

愛可生雲資料庫發表於2022-01-13

作者:楊濤濤

資深資料庫專家,專研 MySQL 十餘年。擅長 MySQL、PostgreSQL、MongoDB 等開源資料庫相關的備份恢復、SQL 調優、監控運維、高可用架構設計等。目前任職於愛可生,為各大運營商及銀行金融企業提供 MySQL 相關技術支援、MySQL 相關課程培訓等工作。

本文來源:原創投稿

*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。


通過上一章節的介紹,我們已經瞭解ProxySQL 如何基於 MySQL 主從以及組複製架構來構建讀寫分離、故障轉移等功能點,但沒有涵蓋ProxySQL 相關配置表的工作細節。那本章就對上節遺漏的內容進行一個延伸講解。

先來了解下 ProxySQL 的內建資料庫列表:
ytt:admin> show databases;
+-----+---------------+-------------------------------------+
| seq | name          | file                                |
+-----+---------------+-------------------------------------+
| 0   | main          |                                     |
| 2   | disk          | /var/lib/proxysql/proxysql.db       |
| 3   | stats         |                                     |
| 4   | monitor       |                                     |
| 5   | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)

以上所列資料庫中,main 代表 runtime ,也即執行時庫;disk 代表持久化庫;stats 代表統計資料庫;monitor 代表監控資料庫;stats_history 代表統計資料庫歸檔。

對於儲存 MySQL 主從、組複製、讀寫分離的幾張配置表,在每個庫裡都存在,不同的庫代表不同的執行範疇。

第一,後端主機後設資料庫表

mysql_servers:該表為儲存後端資料庫相關後設資料資訊的基礎表,所有的後續操作都需要訪問並且更新這張表。

其中主要幾個欄位如下:

hostgroup_id, 後端MySQL例項的主機組標誌,每個例項可以設定為一樣的數值或者設定為不相同的數值,推薦一組例項設定為相同。

gtid_port, Proxy Binlog Reader 元件需要監聽的埠。 不使用此元件可以保持預設即可。

status ,例項狀態值。

  1. online ,預設選項,線上提供服務,也即正常狀態;
  2. offline_soft ,非強制下線狀態,也即處理完當前會話後停止接受新請求;
  3. offline_hard ,強制下線,強制關閉目所有會話,並且不再接受新的請求;
  4. shunned ,後端例項由於太多錯誤連線而暫時關閉的狀態或者說由於超過設定的延遲時間而暫停處理新請求。

weight,一個組裡的例項優先順序,優先順序越高的越有機率被選中。比如多個從例項,可以提升一個節點的優先順序來保證流量分配優先。

compression ,是否壓縮連線請求。預設不壓縮,可以設定為1表示壓縮。

max_connections ,通過 ProxySQL 流量埠的最大連線數限制。

max_replication_lag,指定例項狀態被設定為 shunned 的延遲時間。 超過這個時間後,指定例項狀態由 online 變為 shunned ,直到積壓的請求處理完成。

比如下面 runtime 級別的 mysql_servers 表記錄: 由於這幾個節點都沒有執行,狀態都為 shunned :

ytt:admin> select hostgroup_id,hostname,port,status,max_connections from runtime_mysql_servers where hostgroup_id in (1,2);
+--------------+-----------+------+---------+-----------------+
| hostgroup_id | hostname  | port | status  | max_connections |
+--------------+-----------+------+---------+-----------------+
| 2            | 127.0.0.1 | 3341 | SHUNNED | 1000            |
| 2            | 127.0.0.1 | 3342 | SHUNNED | 1000            |
| 2            | 127.0.0.1 | 3340 | SHUNNED | 1000            |
+--------------+-----------+------+---------+-----------------+
3 rows in set (0.00 sec)

我啟動這三個主從節點,對應狀態自動更新為 online :

ytt:admin> select hostgroup_id,hostname,port,status,max_connections from runtime_mysql_servers where hostgroup_id in (1,2);
+--------------+-----------+------+--------+-----------------+
| hostgroup_id | hostname  | port | status | max_connections |
+--------------+-----------+------+--------+-----------------+
| 2            | 127.0.0.1 | 3341 | ONLINE | 1000            |
| 1            | 127.0.0.1 | 3341 | ONLINE | 1000            |
| 2            | 127.0.0.1 | 3342 | ONLINE | 1000            |
| 2            | 127.0.0.1 | 3340 | ONLINE | 1000            |
+--------------+-----------+------+--------+-----------------+
4 rows in set (0.00 sec)

同樣,啟動組複製例項,三個節點的狀態如下:

ytt:admin> select hostgroup_id,hostname,port,status from runtime_mysql_servers where hostgroup_id > 2;
+--------------+-----------+------+--------+
| hostgroup_id | hostname  | port | status |
+--------------+-----------+------+--------+
| 3            | 127.0.0.1 | 3343 | ONLINE |
| 5            | 127.0.0.1 | 3343 | ONLINE |
| 5            | 127.0.0.1 | 3344 | ONLINE |
| 5            | 127.0.0.1 | 3345 | ONLINE |
+--------------+-----------+------+--------+
4 rows in set (0.00 sec)
第二,使用者後設資料表

mysql_users: 此表儲存流量使用者的授權資料。 有幾個主要欄位:

transaction_persistent ,用來指定事務整體是否被分流。 設定為1則代表以事務為粒度分流到到預設主機組;為0則代表按照事務內部 SQL 為粒度來分流。 除了只讀事務,其他事務都應該作為一個整體,保持原有事務邏輯。

default_hostgroup ,預設主機組,沒有配置查詢規則的 SQL 統一分流到預設主機組。

frontend ,前端使用者,針對 ProxySQL 例項。

backend ,後端使用者,針對 MySQL 例項。

這兩個欄位預設都為1,通常定義一個後端 MySQL 例項使用者,會自動對映到前端 ProxySQL 例項。

比如下面主從流量使用者:從 mysql_users 表自動對映到 runtime_mysql_users 表,一個使用者同時為前後端。

ytt:admin> select username,active,default_hostgroup,frontend,backend from mysql_users where username = 'dev_user';
+----------+--------+-------------------+----------+---------+
| username | active | default_hostgroup | frontend | backend |
+----------+--------+-------------------+----------+---------+
| dev_user | 1      | 1                 | 1        | 1       |
+----------+--------+-------------------+----------+---------+
1 row in set (0.00 sec)

ytt:admin> select username,active,default_hostgroup,frontend,backend from runtime_mysql_users where username = 'dev_user';
+----------+--------+-------------------+----------+---------+
| username | active | default_hostgroup | frontend | backend |
+----------+--------+-------------------+----------+---------+
| dev_user | 1      | 1                 | 0        | 1       |
| dev_user | 1      | 1                 | 1        | 0       |
+----------+--------+-------------------+----------+---------+
2 rows in set (0.00 sec)
第三,主從後設資料表

mysql_replication_hostgroups: 此表配置主從例項主機組資訊。

ProxySQL 根據這張表的內容來分流前端請求,並且配合 mysql_servers 表來達成主從自動故障轉移目標。

writer_hostgroup ,寫主機組 ID 。 比如我們的例子裡設定為1,表示主機組 ID 為1的處理寫請求。

reader_hostgroup ,讀主機組 ID 。 比如我們的例子裡設定為2,表示主機組 ID 為2的處理讀請求。

check_type ,檢查 MySQL 只讀變數的值。在 read_only , innodb_read_only , super_read_only 這幾個變數裡選。

比如需要檢測 super_read_only , 如果為1,代表讀;為0,則為寫。

ytt:admin> select * from mysql_replication_hostgroups;
+------------------+------------------+-----------------+---------------------------------+
| writer_hostgroup | reader_hostgroup | check_type      | comment                         |
+------------------+------------------+-----------------+---------------------------------+
| 1                | 2                | super_read_only | MySQL Replication failover test |
+------------------+------------------+-----------------+---------------------------------+
1 row in set (0.00 sec)
第四,組複製後設資料表

mysql_group_replication_hostgroups: 此表配置組複製主機組資訊,同樣配合 mysql_servers 表來完成組複製節點無感知容錯功能,類似表 mysql_replication_hostgroups 。

writer_hostgroup ,reader_hostgroup ,這兩個分別代表寫和讀流量組。

offline_hostgroup ,下線主機組,狀態不正常的節點被放入這個組。

max_writers ,backup_writer_hostgroup , 這兩個用於多寫模式,如果寫例項數量多過max_writers 設定,則被放入主機組 backup_writer_hostgroup 。

max_transactions_behind , 類似主從延遲流量停用功能。設定一個節點落後的事務數量,達到這個數量後,節點狀態被設定為 shunned ,被完全處理完後,再變更為正常狀態。

目前組複製環境的配置表如下:

ytt:admin> select writer_hostgroup,backup_writer_hostgroup,reader_hostgroup from mysql_group_replication_hostgroups;
+------------------+-------------------------+------------------+
| writer_hostgroup | backup_writer_hostgroup | reader_hostgroup |
+------------------+-------------------------+------------------+
| 3                | 4                       | 5                |
+------------------+-------------------------+------------------+
1 row in set (0.00 sec)
第五,讀寫分離後設資料表

mysql_query_rules: 用來配置讀寫分離模式,非常靈活,可以配置統一埠匹配正規表示式或者根據不同埠來分流。(正規表示式依據的標準由引數 mysql-query_processor_regex 設定決定)幾個主要的欄位如下:

active ,是否啟用這個匹配模式。

username ,流量使用者名稱。

schemaname ,資料庫名。

match_pattern ,具體的匹配模式。

除了上一章節介紹的依賴正規表示式來分流讀寫流量到同一埠外,還可以設定多個埠來區分不同的例項組。比如主從流量走埠 6401 ,組複製流量走 6402 ,那麼可以直接這樣適配:

先把 ProxySQL 要監聽的埠新增到變數 mysql-interfaces 裡,完了重啟 ProxySQL 服務:

ytt:admin> SET mysql-interfaces='0.0.0.0:6033;0.0.0.0:6401;0.0.0.0:6402';
Query OK, 1 row affected (0.00 sec)

ytt:admin> SAVE MYSQL VARIABLES TO DISK;
Query OK, 140 rows affected (0.02 sec)

再把這兩個埠插入到這張表:

ytt:admin> INSERT INTO mysql_query_rules (rule_id,active,proxy_port,destination_hostgroup,apply)
    -> VALUES (1,1,6401,1,1), (2,1,6402,3,1);
Query OK, 2 rows affected (0.00 sec)

ytt:admin> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)

ytt:admin> SAVE MYSQL QUERY RULES TO DISK; 
Query OK, 0 rows affected (0.08 sec)

這張表現在內容如下:除了按照正則分流外,額外有兩條記錄來按照指定埠(6401 為主從分流埠,6402 為組複製分流埠)分流。

ytt:admin> select rule_id,active,username,schemaname,match_pattern,destination_hostgroup,proxy_port from runtime_mysql_query_rules;
+---------+--------+--------------+------------+---------------+-----------------------+------------+
| rule_id | active | username     | schemaname | match_pattern | destination_hostgroup | proxy_port |
+---------+--------+--------------+------------+---------------+-----------------------+------------+
| 1       | 1      | NULL         | NULL       | NULL          | 1                     | 6401       |
| 2       | 1      | NULL         | NULL       | NULL          | 3                     | 6402       |
| 13      | 1      | dev_user     | ytt        | ^select       | 2                     | NULL       |
| 14      | 1      | dev_user_mgr | ytt        | ^select       | 4                     | NULL       |
+---------+--------+--------------+------------+---------------+-----------------------+------------+
4 rows in set (0.00 sec)

來驗證下這個分流策略: 分別使用使用者 dev_user 連線埠 6401 ,使用者 dev_user_mgr 連線埠 6402 。

root@ytt-ubuntu:~# mysql -udev_user -pdev_user -P6401 -h ytt-ubuntu -e "use ytt;select count(*) from t1";
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------+
| count(*) |
+----------+
|        5 |
+----------+
root@ytt-ubuntu:~# mysql -udev_user_mgr -pdev_user_mgr -P6402 -h ytt-ubuntu -e "use ytt;select count(*) from t1";
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------+
| count(*) |
+----------+
|        1 |
+----------+

進入 ProxySQL 管理端, 檢視審計表: 以上不同使用者、不同埠分流到具體的主機組裡。

ytt:admin> select hostgroup,schemaname,username,digest_text,count_star from stats_mysql_query_digest where schemaname = 'ytt';
+-----------+------------+--------------+-------------------------+------------+
| hostgroup | schemaname | username     | digest_text             | count_star |
+-----------+------------+--------------+-------------------------+------------+
| 3         | ytt        | dev_user_mgr | select count(*) from t1 | 1          |
| 1         | ytt        | dev_user     | select count(*) from t1 | 1          |
+-----------+------------+--------------+-------------------------+------------+
2 rows in set (0.00 sec)

到這裡,對於 ProxySQL 來講,如何與 MySQL HA 進行搭配,相信已經有了一定的瞭解。

相關文章