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

作者:楊濤濤

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

本文來源:原創投稿

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


ProxySQL 是一個使用非常廣泛並且較穩定的中間件,有很多功能點。比如查詢緩存,查詢重寫,讀寫分離,數據分片等等。

本篇要介紹的是 ProxySQL 和 MySQL Replication 以及 MySQL MGR 的初步結合,初步讀寫分離以及 failover 功能的體驗。
在本機安裝一個 ProxySQL 實例,六個 MySQL 實例;ProxySQL 和 MySQL 版本均是最新版。

ProxySQL: 管理端口6032,流量端口6033。

MySQL Replication:流量端口分別爲:3340、3341、3342
MySQL MGR:流量端口分別爲:3343、3344、3345
第一,ProxySQL 以及六個 MySQL 部署。
ProxySQL 安裝比較簡單,官網 apt/yum ,或者自己下載安裝。裝好六個 MySQL 實例,並且配置好 MySQL 主從以及組複製環境。
第二,ProxySQL 記錄 MySQL 實例相關信息。
進入 ProxySQL 管理端,把以上六個 MySQL 實例信息依次插入到表 mysql_servers :主從實例的 hostgroup_id 統一設置爲1, 爲了不破壞後續 failover 相關 hostgroup_id 的連續性,組複製實例的 hostgroup_id 統一設置爲3。
Admin> select hostgroup_id, hostname,port,status from mysql_servers;
+--------------+-----------+------+--------+
| hostgroup_id | hostname | port | status |
+--------------+-----------+------+--------+
| 1 | 127.0.0.1 | 3340 | ONLINE |
| 1 | 127.0.0.1 | 3341 | ONLINE |
| 1 | 127.0.0.1 | 3342 | ONLINE |
| 3 | 127.0.0.1 | 3343 | ONLINE |
| 3 | 127.0.0.1 | 3344 | ONLINE |
| 3 | 127.0.0.1 | 3345 | ONLINE |
+--------------+-----------+------+--------+
6 rows in set (0.00 sec)
第三,MySQL 端創建 ProxySQL 所需的兩類用戶

ProxySQL 與 MySQL 交互,需要兩類用戶,這兩類用戶需要同時在主從和組複製環境創建。

1. 監控用戶:爲了免去後面重復設置監控用戶變量的工作,兩種架構用戶名和密碼保持一致,用戶名和密碼都是 proxysql_monitor 。proxysql_monitor 需要以下權限:
client,session_variables_admin,system_variables_admin,select

在 MySQL 主從以及組複製環境裏分別執行下面SQL:

 MySQL  localhost:3343 ssl  SQL > create user proxysql_monitor@'127.0.0.1' identified by 'proxysql_monitor';
Query OK, 0 rows affected (0.0596 sec)
MySQL localhost:3343 ssl SQL > grant replication client,session_variables_admin,system_variables_admin,select on *.* to proxysql_monitor@'127.0.0.1';
Query OK, 0 rows affected (0.0103 sec)

進入 ProxySQL 管理端,設置監控用戶:

Admin> set mysql-monitor_username='proxysql_monitor';
Query OK, 1 row affected (0.00 sec)

Admin> set mysql-monitor_password='proxysql_monitor';
Query OK, 1 row affected (0.00 sec)

2. 開發用戶:對於主從和組複製環境,分別創建此類用戶。

主從環境用戶創建:用戶名 dev_user

 MySQL  localhost:3343 ssl  SQL > create user dev_user@'127.0.0.1' identified by 'dev_user';
Query OK, 0 rows affected (0.1221 sec)
MySQL localhost:3343 ssl SQL > grant insert,delete,update,select,create on ytt.* to dev_user@'127.0.0.1';
Query OK, 0 rows affected (0.0359 sec)

組複製環境用戶創建:用戶名 dev_user_mgr

 MySQL  localhost:3343 ssl  SQL > create user dev_user_mgr@'127.0.0.1' identified by 'dev_user_mgr';
Query OK, 0 rows affected (0.1221 sec)
MySQL localhost:3343 ssl SQL > grant insert,delete,update,select,create on ytt.* to dev_user_mgr@'127.0.0.1';
Query OK, 0 rows affected (0.0359 sec)

進入 ProxySQL 管理端,分別插入主從以及組複製對應的開發用戶到表 mysql_users 。字段 transaction_persistent 爲1代表事務不拆分,統一去主庫檢索。

Admin> insert into mysql_users(username,password,active,default_hostgroup,transaction_persistent) 
values
('dev_user','dev_user',1,1,1),
('dev_user_mgr','dev_user_mgr',1,3,1);
Query OK, 1 row affected (0.00 sec)

Admin> select username,active,default_hostgroup from mysql_users;
+--------------+--------+-------------------+
| username | active | default_hostgroup |
+--------------+--------+-------------------+
| dev_user | 1 | 1 |
| dev_user_mgr | 1 | 3 |
+--------------+--------+-------------------+
2 rows in set (0.00 sec)
第四,配置讀寫分離

進入 ProxySQL 管理端,插入之前創建的兩個開發用戶到表 mysql_query_rules ,定義最基本的讀寫分離策略,只要是 select 開頭的語句都分流到從庫。

Admin> INSERT INTO mysql_query_rules(username,schemaname,active,match_pattern,destination_hostgroup,apply) VALUES
('dev_user','ytt',1,'^select',2,1),
('dev_user_mgr','ytt',1,'^select',4,1);
Query OK, 2 rows affected (0.00 sec)

Admin> select username,schemaname,active,match_pattern,destination_hostgroup,apply from mysql_query_rules;
+--------------+------------+--------+---------------+-----------------------+-------+
| username | schemaname | active | match_pattern | destination_hostgroup | apply |
+--------------+------------+--------+---------------+-----------------------+-------+
| dev_user | ytt | 1 | ^select | 2 | 1 |
| dev_user_mgr | ytt | 1 | ^select | 4 | 1 |
+--------------+------------+--------+---------------+-----------------------+-------+
2 rows in set (0.00 sec)

設置好相關信息後把以上所有更改加載到內存,並且持久化到磁盤。
Admin> load mysql servers to runtime;
Query OK, 0 rows affected (0.01 sec)

Admin> load mysql users to runtime;
Query OK, 0 rows affected (0.00 sec)

Admin> load mysql variables to runtime;
Query OK, 0 rows affected (0.00 sec)

Admin> load mysql query rules to runtime;
Query OK, 0 rows affected (0.00 sec)

Admin> save mysql servers to disk;
Query OK, 0 rows affected (0.18 sec)

Admin> save mysql users to disk;
Query OK, 0 rows affected (0.13 sec)

Admin> save mysql variables to disk;
Query OK, 140 rows affected (0.17 sec)

Admin> save mysql query rules to disk;
Query OK, 0 rows affected (0.11 sec)

分別測試下主從和組複製兩種架構的讀寫分離效果:開發用戶dev_user/dev_user_mgr連接端口6033,創建一張表t1,插入一條記錄,並且簡單查詢一次。

-- 主從環境:
root@ytt-ubuntu:/home/ytt/scripts# mysql -u dev_user -p -h 127.0.0.1 -P 6033 -e " \
> use ytt;
> create table t1 (id int primary key,str1 varchar(100));
> insert t1 values (1,'replication');
> select * from t1;
> ";
Enter password:
-- 組複製環境把用戶dev_user和密碼替換爲dev_user_mgr和對應密碼重複執行一次。

進入 ProxySQL 管理端,檢索審計表 stats_mysql_query_digest :寫入請求和讀取請求根據不同的用戶被成功分發到 mysql_query_rules 表裏對應的 hostgroup 上。

Admin> select hostgroup,username,digest_text,count_star from stats_mysql_query_digest where schemaname = 'ytt';
+-----------+--------------+------------------------------------------------------+------------+
| hostgroup | username | digest_text | count_star |
+-----------+--------------+------------------------------------------------------+------------+
| 4 | dev_user_mgr | select * from t1 | 1 |
| 3 | dev_user_mgr | insert t1 values (?,?) | 1 |
| 3 | dev_user_mgr | create table t1 (id int primary key,str1 varchar(?)) | 1 |
| 2 | dev_user | select * from t1 | 1 |
| 1 | dev_user | insert t1 values (?,?) | 1 |
| 1 | dev_user | create table t1 (id int primary key,str1 varchar(?)) | 1 |
+-----------+--------------+------------------------------------------------------+------------+
6 rows in set (0.00 sec)
第五,配置主從自動 failover 功能:

進入 ProxySQL 管理端,把主從相關實例信息插入到表 mysql_replication_hostgroups 即可。

ProxySQL 通過實時監控 MySQL 系統變量('read_only','innodb_read_only','super_read_only' )開關與否來探測對應的 MySQL 實例是主庫還是從庫,完了自動更新 mysql_server 表主庫對應的IP和端口來達到 failover 的目的。

Admin> insert into  mysql_replication_hostgroups (writer_hostgroup,reader_hostgroup,check_type,comment)values(1,2,'super_read_only','MySQL Replication fa
ilover test');
Query OK, 1 row affected (0.00 sec)

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.01 sec)

Admin> load mysql servers to runtime;
Query OK, 0 rows affected (0.01 sec)

Admin> save mysql servers to disk;
Query OK, 0 rows affected (0.18 sec)


我用 MySQL Shell  操作副本集來手動進行主從切換,設置主庫爲端口3342。

 MySQL  localhost:3340 ssl  Py > rs = dba.get_replica_set()
You are connected to a member of replicaset 'rs1'.

MySQL localhost:3340 ssl Py > rs.set_primary_instance('root@localhost:3342')
127.0.0.1:3342 will be promoted to PRIMARY of 'rs1'.
The current PRIMARY is 127.0.0.1:3340.
...

127.0.0.1:3342 was promoted to PRIMARY.

查看 ProxySQL 日誌,已經感知到主從切換,新的主庫自動變爲127.0.0.1:3342

2021-12-15 16:02:08 [INFO] Regenerating read_only_set1 with 1 servers
2021-12-15 16:02:08 [INFO] read_only_action() detected RO=0 on server 127.0.0.1:3342 for the first time after commit(), but no need to reconfigure

也可以進入 ProxySQL 管理端來查詢表 mysql_servers 的字段 hostgroup_id=1 的匹配記錄是否已經變更爲新主庫:

Admin> select hostname,port from mysql_servers where hostgroup_id = 1;
+-----------+------+
| hostname | port |
+-----------+------+
| 127.0.0.1 | 3342 |
+-----------+------+
1 row in set (0.00 sec)
第六,配置組複製自動 failover 功能:
和主從配置類似,把組複製實例相關信息插入到表 mysql_replication_hostgroups 即可。

這裏和主從有點不一樣的地方:writer_hostgroup,backup_writer_hostgroup, reader_hostgroup, offline_hostgroup 這四個字段代表不同職責的 Hostgroup ,最好是設置不一樣。

Admin> insert into mysql_group_replication_hostgroups (writer_hostgroup,backup_writer_hostgroup, reader_hostgroup, offline_hostgroup,active,max_writers,writer_is_also_reader,max_transactions_behind) values (3,4,5,6,1,1,1,1000);
Query OK, 1 row affected (0.00 sec)

Admin> load mysql servers to runtime;
Query OK, 0 rows affected (0.01 sec)

Admin> save mysql servers to disk;
Query OK, 0 rows affected (0.19 sec)

進入 ProxySQL 管理端,查詢組複製日誌表 mysql_server_group_replication_log ,可以看到當前的組複製對應的實例數據,其中主庫爲:127.0.0.1:3343。

Admin> select hostname, port,viable_candidate,read_only, transactions_behind, error from mysql_server_group_replication_log where port in (3343,3344,3345) order by time_start_us desc limit 3;
+-----------+------+------------------+-----------+---------------------+-------+
| hostname | port | viable_candidate | read_only | transactions_behind | error |
+-----------+------+------------------+-----------+---------------------+-------+
| 127.0.0.1 | 3345 | YES | YES | 0 | NULL |
| 127.0.0.1 | 3344 | YES | YES | 0 | NULL |
| 127.0.0.1 | 3343 | YES | NO | 0 | NULL |
+-----------+------+------------------+-----------+---------------------+-------+
3 rows in set (0.00 sec)

同樣用 MySQL Shell 來驗證下組複製的主備角色切換後 ProxySQL 是否會自動感知:把實例 127.0.0.1:3344 提升爲主庫。

MySQL  localhost:3343 ssl  sys  Py > rc = dba.get_cluster();
MySQL localhost:3343 ssl sys Py > rc.set_primary_instance('root@localhost:3344');
Setting instance 'localhost:3344' as the primary instance of cluster 'ytt_mgr'...

Instance '127.0.0.1:3343' was switched from PRIMARY to SECONDARY.
Instance '127.0.0.1:3344' was switched from SECONDARY to PRIMARY.
Instance '127.0.0.1:3345' remains SECONDARY.

WARNING: The cluster internal session is not the primary member anymore. For cluster management operations please obtain a fresh cluster handle using dba.get_cluster().

The instance 'localhost:3344' was successfully elected as primary.
MySQL localhost:3343 ssl sys Py >

進入 ProxySQL 管理端,查詢組複製日誌:127.0.0.1:3344 自動變更爲主庫。

Admin> select hostname, port,viable_candidate,read_only, transactions_behind, error from mysql_server_group_replication_log where port in (3343,3344,3345) order by time_start_us desc limit 3;
+-----------+------+------------------+-----------+---------------------+-------+
| hostname | port | viable_candidate | read_only | transactions_behind | error |
+-----------+------+------------------+-----------+---------------------+-------+
| 127.0.0.1 | 3345 | YES | YES | 0 | NULL |
| 127.0.0.1 | 3344 | YES | NO | 0 | NULL |
| 127.0.0.1 | 3343 | YES | YES | 0 | NULL |
+-----------+------+------------------+-----------+---------------------+-------+
3 rows in set (0.00 sec)

或者查詢mysql_server表,查找hostgroup_id 爲3的記錄是否變更爲新主庫。

Admin> select port from mysql_servers where hostgroup_id = 3;
+------+
| port |
+------+
| 3344 |
+------+
1 row in set (0.00 sec)

總結

本篇簡單介紹 ProxySQL 配置 MySQL HA 的相關配置與驗證測試,更詳細的配置與驗證策略請關注後續。


文章推薦:

新特性解讀 | 來聊聊 MySQL8.0 的 json 模式校驗

技術分享 | TiDB 對大事務的簡單拆分

技術分享 | MySQL 內部臨時表是怎麼存放的



社區近期動態




本文關鍵字 #ProxySQL #  #MySQL  failover# #MySQL 主從# #MySQL 組複製
#  點一下“閱讀原文”瞭解更多資訊

本文分享自微信公衆號 - 愛可生開源社區(ActiontechOSS)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章