MySQL 代理層:ProxySQL

文章目錄

    • 說明
    • 安裝部署
      • 1.1 yum 安裝
      • 1.2 啟停管理
      • 1.3 查詢版本
      • 1.4 Admin 管理接口
    • 入門體驗
    • 功能介紹
      • 3.1 多層次配置系統
    • 讀寫分離
      • 將實例接入到代理服務
      • 定義主機組之間的復制關系
      • 配置路由規則
      • 事務讀的配置
      • 延遲閾值和請求轉發
    • ProxySQL 核心表
      • mysql_users
      • mysql_servers
      • mysql_replication_hostgroups
      • mysql_query_rules
    • 高級特性
      • SQL 審計
      • SQL 黑名單
      • ProxySQL Cluster
        • 搭建 ProxySQL Cluster
    • 參考文檔

說明

MySQL 常見代理有 MySQ Proxy、Atlas、MaxScale、ProxySQ L其中 MySQL Proxy 是 MySQL 原廠研發的,沒有發布過 GA 版,項目已經 9 年沒有維護,官方不建議生產環境使用。另外三個項目都是第三方研發的開源代理,其中 ProxySQL 項目的 Star 最多,而且一直都在維護。本篇 SOP 主要介紹 ProxySQL 運維管理。

ProxySQL 官網:https://www.proxysql.com/

安裝部署

1.1 yum 安裝

以 CentOS Linux release 7.8.2003 (Core) 系統版本為例:

cat <<EOF | tee /etc/yum.repos.d/proxysql.repo
[proxysql_repo]
name= ProxySQL YUM repository
baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/centos/$releasever
gpgcheck=1
gpgkey=https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/repo_pub_key
EOF

使用 yum 安裝,可以指定版本:

yum install proxysql OR yum install proxysql-version

1.2 啟停管理

service proxysql start   # 啟動 proxysql
service proxysql stop    # 停止 proxysql
service proxysql status  # 查看 proxysql 狀態

1.3 查詢版本

proxysql --version

1.4 Admin 管理接口

當 ProxySQL 啟動后,將會監聽兩個端口:
**Admin 管理接口:**默認為 6032 該端口用于管理配置 ProxySQL。
**接收業務 SQL 接口:**默認為 6033 用于服務業務端口,類似于 MySQL 的 3306 端口。

請添加圖片描述

Admin 管理接口兼容 MySQL 客戶端協議,所以可以直接使用 MySQL 客戶端連接這個管理接口。

mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '

一般來講 Admin 接口不需要額外配置,最有可能需要配置的是 Admin 用戶的密碼。

Admin> select @@admin-admin_credentials;
+---------------------------+
| @@admin-admin_credentials |
+---------------------------+
| admin:admin               |
+---------------------------+

修改 Admin 接口密碼:

set admin-admin_credentials='admin:YouPassword';load admin variables to runtime; -- 立即生效
save admin variables to disk; -- 持久化磁盤

入門體驗

以下是測試使用的環境信息,操作系統均為 CentOS 7.9 版本。

ip 地址角色程序
172.16.104.56主節點MySQL 5.7.33
172.16.104.57備節點MySQL 5.7.33
172.16.104.55代理節點ProxySQL 2.4.3

接下來,一起簡單的測試一下 ProxySQL,使用下方命令登入管理端。

mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '-- 設置監控后端使用的賬號信息
set mysql-monitor_username = 'monitor';
set mysql-monitor_password = 'monitor';-- 配置生效
load mysql variables to runtime;
save mysql variables to disk;

在后端創建 ProxySQL 的監控賬戶:

create user 'monitor'@'%' identified with mysql_native_password by 'monitor';grant replication client on *.* to 'monitor'@'%';-- group replication
grant select on performance_schema.replication_group_member_stats to 'monitor'@'%';grant select on performance_schema.replication_group_members to 'monitor'@'%';

配置后端節點,寫入后端節點的 ip、端口、主機組。

insert into mysql_servers (hostgroup_id, hostname, port) values (1, '172.16.104.56', 3306);LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

配置訪問用戶,這里的用戶分為兩種含義:

  • 前端用戶:客戶端用來訪問 ProxySQL 的用戶。
  • 后端用戶:ProxySQL 用來訪問后端 MySQL 節點的用戶。

在此,案例中我們配置的前后端用戶一致。在 MySQL 中創建后端使用的賬號:

-- 創建后端用戶
create user 'op_user'@'%' identified by 'abc123';
grant all privileges on *.* to 'op_user'@'%';

將賬號信息錄入到 ProxySQL 中:

-- 寫入用戶信息
insert into mysql_users(username, password, default_hostgroup, comment) values ('op_user', 'abc123', 1, '后端用戶');-- 加載 & 持久化
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

連接代理節點,訪問數據庫:

mysql -u op_user -pabc123 -h 172.16.104.55 -P6033 -e'select @@hostname;'
+---------------+
| @@hostname    |
+---------------+
| 172-16-104-56 |
+---------------+

功能介紹

ProxySQL 默認的配置文件位于/etc/proxysql.cnf,第一次啟動 ProxySQL 會初始化配置數據庫,往后的所有配置都可以在 ProxySQL 數據庫中修復,直接修改配置文件則不會生效,除非重新初始化。

3.1 多層次配置系統

ProxySQL 為了實現動態修改大部分配置項,不需要重啟,設計了多級配置系統,將配置從運行時環境移到內存,并在有需求時持久化到磁盤上。
請添加圖片描述

  • 最底層的是 DISK 庫和 CONFIG FILE,負責持久化保存配置。這里的 CONFIG FILE 就是傳統的配置文件,ProxySQL 啟動時,主要是從 DISK 庫中讀取配置加載到內存并最終加載到 runtime 生效,只有極少的幾個特定配置內容是從 CONFIG FILE 中加載的,除非是第一次初始化 ProxySQL 運行環境或者 DISK 庫為空。
  • 中間層的是 MEMORY,表示的是內存數據庫,管理接口中的 main 庫。通過管理接口可以修改所有配置,都保存在內存數據庫中,此時并沒有生效也沒有持久化,需要 load 到上層 RUNTIME 才能生效,save 到下層 DISK 才能持久化保存。
  • 最上層的是 RUNTIME,它是 ProxySQL 相關線程運行時讀取的數據結構。該數據結構中的配置都是已生效的配置。修改了 main 庫中的配置后,必須 load 到 runtime 數據結構中才能使其生效。
    在這里插入圖片描述

在上面的多層配置系統圖中,標注了** [1]、[2]、[3]、[4]、[5] ** 的序號。每個序號都有兩個操作方向 from/to b 以下是各序號對應的操作:

  • [1] LOAD FROM MEMORY / LOAD TO RUNTIME
  • [2] SAVE FROM RUNTIME / SAVE TO MEMORY
  • [3] LOAD FROM DISK / LOAD TO MEMORY
  • [4] SAVE FROM MEMORY / SAVE TO DISK
  • [5] LOAD FROM CONFIG

另外,上面的 是什么?這表示要 加載/保存 的是哪類配置。 詳細如下:

+------------------------------------+
| tables                             |
+------------------------------------+
| global_variables                   |  # (1)
| mysql_collations                   |  # (N)
| mysql_group_replication_hostgroups |  # (2)
| mysql_query_rules                  |  # (3)
| mysql_query_rules_fast_routing     |  # (4)
| mysql_replication_hostgroups       |  # (5)
| mysql_servers                      |  # (6)
| mysql_users                        |  # (7)
| proxysql_servers                   |  # (8)
| scheduler                          |  # (9)
+------------------------------------+
  • (1)中包含兩類變量,以 amdin 為前綴的表示 admin variables,以 mysql 為前綴的表示 mysql variables。
  • (2,5,6)對應的都是 mysql servers。
  • (3,4)對應的是 mysql query rules。
  • (7)對應的 mysql users。
  • (9)對應的 scheduler。
  • (N)只是一張表,保存的是 ProxySQL 支持的字符集和排序規則,不需要修改。
  • (8)是 ProxySQL 的集群配置表,對應 proxysql_servers。

在 ProxySQL 客戶端使用 DML/SET 語句修改配置,是直接在內存中修改的,所以需要使用命令持久化和激活,這也是官方推薦的管理方式。下面提供常見的管理語句:

  1. 激活/持久化 MySQL 用戶配置:
# Active current in-memory MySQL User configuration
LOAD MYSQL USERS TO RUNTIME;# Save the current in-memory MySQL User configuration to disk
SAVE MYSQL USERS TO DISK;
  1. 激活/持久化 MySQL 服務器配置和主機組配置:
# Active current in-memory MySQL Server and Replication Hostgroup configuration
LOAD MYSQL SERVERS TO RUNTIME;# Save the current in-memory MySQL Server and Replication Hostgroup configuration to disk
SAVE MYSQL SERVERS TO DISK;
  1. 激活/持久化 MySQL 查詢規則:
# Active current in-memory MySQL Query Rule configuration
LOAD MYSQL QUERY RULES TO RUNTIME;# Save the current in-memory MySQL Query Rule configuration to disk
SAVE MYSQL QUERY RULES TO DISK;
  1. 激活/持久化 MySQL 管理變量:
# Active current in-memory MySQL Variable configuration
LOAD MYSQL VARIABLES TO RUNTIME;# Save the current in-memory MySQL Variable configuration to disk
SAVE MYSQL VARIABLES TO DISK;
  1. 激活/持久化 ProxySQL 管理變量:
# Active current in-memory ProxySQL Admin Variable configuration
LOAD ADMIN VARIABLES TO RUNTIME;# Save the current in-memory ProxySQL Admin Variable configuration to disk
SAVE ADMIN VARIABLES TO DISK;

讀寫分離

在入門體驗中,已完成監控賬號、業務賬號的創建和配置,并將主節點完成接入。本小節,將介紹一個高頻的使用場景,就是讀寫分離。

將實例接入到代理服務

下圖,是當前的 mysql_servers 表的配置,只添加了主庫。

Admin> select * from mysql_servers;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1            | 172.16.104.56 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+

現在將備庫也接入進來:

insert into mysql_servers (hostgroup_id, hostname, port) values (2, '172.16.104.57', 3306);LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

定義主機組之間的復制關系

主機之間的復制關系是通過 hostgroup_id 來綁定的,關系定義使用的是 mysql_replication_hostgroups 表。

insert into mysql_replication_hostgroups(writer_hostgroup, reader_hostgroup, check_type, comment) values(1, 2, 'read_only', 'op 集群');LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

ProxySQL 會基于后端節點 check_type 的值,來動態調整它所屬的主機組,所以必須保證從庫的 read_only 參數為 on 的狀態。

配置路由規則

路由的規則是在 mysql_query_rules 中配置:

insert into mysql_query_rules(rule_id, active, match_pattern, destination_hostgroup, apply) values (1, 1, '^SELECT.*FOR UPDATE$', 1, 1);
insert into mysql_query_rules(rule_id, active, match_pattern, destination_hostgroup, apply) values (2, 1, '^SELECT', 2, 1);
  • rule_id:是規則 ID。
  • active:表示是否啟動規則。
  • match_pattern:表示匹配規則,支持正則匹配。
  • apply:設置為 1,如果當前的規則匹配,則不再進行后續其他規則的匹配。
  • destination_hostgroup:SQL轉發目的 hostgroup。

上方配置的路由規則效果如下:

  • 所有的 SELECT FOR UPDATE 操作將發往主庫執行。
  • 其他所有的 SELECT 操作將發往備庫執行。
  • 除此之外的所有操作將默認發往主庫處理。

配置完成后,驗證一下:

mysql -u op_user -pabc123 -h 172.16.104.55 -P6033-- 測試執行 SQL 語句
select * from test_semi;
select * from test_semi where a = 10 for update;

連接管理節點,查看日志:

mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '-- 查詢 SQL 執行情況
select hostgroup, digest_text from stats.stats_mysql_query_digest order by first_seen desc;
+-----------+------------------------------------------------+
| hostgroup | digest_text                                    |
+-----------+------------------------------------------------+
| 1         | select * from test_semi where a = ? for update |
| 2         | select * from test_semi                        |
+-----------+------------------------------------------------+

事務讀的配置

接下來我們驗證另外一個操作,顯式開啟事務后執行 SELECT 操作。

begin;
select * from test_semi;
update test_semi set c = 123 where a = 10;
select * from test_semi;
commit;

執行結果可以通過 stats.stats_mysql_query_digest 表進行觀測。這里直接說結論,顯式開啟事務后,會直接路由到主庫執行,該行為由 mysql_users 表中的 transaction_persistent 參數有關。創建用戶時,如果不指定 transaction_persistent 參數,其默認值為 1,表示事務開啟后,所有的操作都會在事務開啟的主機組中執行,此時會忽略所有的路由規則。
我們將 transaction_persistent 設置為 0 測試一下。

update mysql_users set transaction_persistent = 0 where username = 'op_user';-- 配置生效
LOAD MYSQL USERS TO RUNTIME;

開啟事務后,執行查詢可以看到是路由到了備庫,不過 transaction_persistent = 1 更符合我們對事務的認知習慣。

Admin> select hostgroup, digest_text from stats.stats_mysql_query_digest order by first_seen desc;
+-----------+----------------------------------------+
| hostgroup | digest_text                            |
+-----------+----------------------------------------+
| 1         | commit                                 |
| 1         | update test_semi set c = ? where a = ? |
| 2         | select * from test_semi                |
| 1         | begin                                  |
+-----------+----------------------------------------+

延遲閾值和請求轉發

上方是一個比較簡單的讀寫分離配置,實際上我們還會遇到如下問題:

  • 如果備庫宕機了,所有轉發的查詢都會失敗。
  • 如果備庫的延遲過高,查詢會讀取到舊數據。

接下來我們通過配置 延遲閾值路由權重 來解決。

  • 備庫宕機了,所有的請求都會轉發到主庫。
  • 為備庫設置延遲閾值,如果延遲大于該值,請求會自動轉發到主庫。
-- 寫入一個規則
insert into mysql_servers (hostgroup_id, hostname, port) values (2, '172.16.104.56', 3306);-- 修改備庫配置
update mysql_servers set weight = 100, max_replication_lag = 30 where hostname = '172.16.104.57';

第一條 SQL 將主庫加入到了 reader_hostgroup 中,這樣當備庫出現故障的時候,查詢會自動路由到主庫中。
第二條 SQL 調大了備庫的權重,這樣只有極少部分 SQL 會路由到主庫,同時將 max_replication_lag 調整到了 30,表示延遲如果大于 30 的時候,查詢會路由到主庫。

ProxySQL 核心表

本節會介紹 ProxySQL 中常用的表,熟悉這些表中字段的含義。

mysql_users

該表用來配置用戶信息。

CREATE TABLE mysql_users (username VARCHAR NOT NULL,password VARCHAR,active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1,use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0,default_hostgroup INT NOT NULL DEFAULT 0,default_schema VARCHAR,schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0,transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 1,fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0,backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1,frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1,max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000,attributes VARCHAR CHECK (JSON_VALID(attributes) OR attributes = '') NOT NULL DEFAULT '',comment VARCHAR NOT NULL DEFAULT '',PRIMARY KEY (username, backend),UNIQUE (username, frontend)) 
  • username & password:用戶名和密碼。
  • active:是否激活賬號。
  • use_ssl:設置為 1,則強制用戶使用 SSL 證書進行身份驗證。
  • default_hostgroup:默認的主機組。如果沒有匹配的路由規則或路由規則沒配置,請求會轉發到默認主機組。
  • default_schema:默認的 schema。如果不設置,則由 mysql-default_schema 決定。
  • schema_locked:目前未實現。
  • transaction_persistent:設置為 1,則代表一個事務內的所有請求都會轉發到第一個主機組內執行。
  • fast_forward:設置為 1,則表示由該用戶發起的 SQL 會跳過重寫、緩存 等查詢處理層,執行轉發到后端。
  • backend & frontend:當前沒有實現前后端分離,默認為 1 即可。
  • max_connections:賬號的最大連接數,默認為 1。
  • attributes:目前未實現。
  • comment:注釋。

mysql_servers

用于配置后端的 MySQL 節點。

CREATE TABLE mysql_servers (hostgroup_id INT CHECK (hostgroup_id>=0) NOT NULL DEFAULT 0,hostname VARCHAR NOT NULL,port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306,gtid_port INT CHECK ((gtid_port <> port OR gtid_port=0) AND gtid_port >= 0 AND gtid_port <= 65535) NOT NULL DEFAULT 0,status VARCHAR CHECK (UPPER(status) IN ('ONLINE','SHUNNED','OFFLINE_SOFT', 'OFFLINE_HARD')) NOT NULL DEFAULT 'ONLINE',weight INT CHECK (weight >= 0 AND weight <=10000000) NOT NULL DEFAULT 1,compression INT CHECK (compression IN(0,1)) NOT NULL DEFAULT 0,max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 1000,max_replication_lag INT CHECK (max_replication_lag >= 0 AND max_replication_lag <= 126144000) NOT NULL DEFAULT 0,use_ssl INT CHECK (use_ssl IN(0,1)) NOT NULL DEFAULT 0,max_latency_ms INT UNSIGNED CHECK (max_latency_ms>=0) NOT NULL DEFAULT 0,comment VARCHAR NOT NULL DEFAULT '',PRIMARY KEY (hostgroup_id, hostname, port) )
  • hostgroup_id:主機組 ID。
  • hostname:后端節點的主機名或 IP。
  • port:后端節點的端口。
  • gtid_port:不詳。
  • status:節點的狀態,有 ONLINE、SHUNNED、OFFLINE_SOFT、OFFLINE_HARD 四個取值。
    • ONLINE:節點狀態正常,可對外服務。
    • SHUNNED:節點暫時離線,無法對外服務。
    • OFFLINE_SOFT:節點離線,在離線前會等待該節點的事務執行完。
    • OFFLINE_HARD:節點離線,如果當前節點有事務正在執行會 Kill 掉。
  • weight:讀寫分離的權重,權重越高被分發的請求就越多。
  • compression:是否開啟壓縮。
  • max_connections:限制 ProxySQL 到后端節點的最大連接數。
  • max_replication_lag:主備的延遲閾值。一旦超過該值,該節點的狀態會被設置為 SHUNNED,直到延遲恢復。
  • use_ssl:是否開啟 SSL 連接,針對的是 ProxySQL 與后端之間的連接。
  • max_latency_ms:ProxySQL 會定期對后端節點進行 ping 操作,如果 ping 的響應時間超過該參數,則會將該節點從連接池中剔除。
  • comment:注釋。

mysql_replication_hostgroups

用于配置復制關系的表。

CREATE TABLE mysql_replication_hostgroups (writer_hostgroup INT CHECK (writer_hostgroup>=0) NOT NULL PRIMARY KEY,reader_hostgroup INT NOT NULL CHECK (reader_hostgroup<>writer_hostgroup AND reader_hostgroup>=0),check_type VARCHAR CHECK (LOWER(check_type) IN ('read_only','innodb_read_only','super_read_only','read_only|innodb_read_only','read_only&innodb_read_only')) NOT NULL DEFAULT 'read_only',comment VARCHAR NOT NULL DEFAULT '', UNIQUE (reader_hostgroup))
  • writer_hostgroup:定義可寫的主機組。
  • reader_hostgroup:定義只讀的主機組。
  • check_type:檢測類型,提供了多種選擇,基本都是通過 read_only 的值來區分的。
  • comment:注釋。

將主庫和備庫的 hostgroup 配置到 mysql_replication_hostgroups 表中后,ProxySQL 會檢測主備庫的 read_only 狀態。
當檢測到 read_only 從 OFF 變成 ON 時,會將 writer_hostgroup 中的主機添加的 reader_hostgrup 中。
反之,當 read_only 從 ON 變成 OFF 時,會將其調整到 writer_hostgroup 組中。
由此可見,在 ProxySQL 中,一定要將備庫的 read_only 設置為 on,否則可能會出現雙寫。
當一個后端 MySQL 實例的 read_only 狀態從 ON 變成 OFF 時,會將該實例加入到 writer_hostgroup 中,同時該實例依然位于 read_hostgroup 中。如果需要將該實例從 read_hostgroup 中移除,需要將參數 mysql-monitor_writer_is_also_reader 設置為 false。

set mysql-monitor_writer_is_also_reader='false';
load mysql variables to runtime;

mysql_query_rules

用于配置路由關系的表。

CREATE TABLE mysql_query_rules (rule_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 0,username VARCHAR,schemaname VARCHAR,flagIN INT CHECK (flagIN >= 0) NOT NULL DEFAULT 0,client_addr VARCHAR,proxy_addr VARCHAR,proxy_port INT CHECK (proxy_port >= 0 AND proxy_port <= 65535),digest VARCHAR,match_digest VARCHAR,match_pattern VARCHAR,negate_match_pattern INT CHECK (negate_match_pattern IN (0,1)) NOT NULL DEFAULT 0,re_modifiers VARCHAR DEFAULT 'CASELESS',flagOUT INT CHECK (flagOUT >= 0),replace_pattern VARCHAR CHECK(CASE WHEN replace_pattern IS NULL THEN 1 WHEN replace_pattern IS NOT NULL AND match_pattern IS NOT NULL THEN 1 ELSE 0 END),destination_hostgroup INT DEFAULT NULL,cache_ttl INT CHECK(cache_ttl > 0),cache_empty_result INT CHECK (cache_empty_result IN (0,1)) DEFAULT NULL,cache_timeout INT CHECK(cache_timeout >= 0),reconnect INT CHECK (reconnect IN (0,1)) DEFAULT NULL,timeout INT UNSIGNED CHECK (timeout >= 0),retries INT CHECK (retries>=0 AND retries <=1000),delay INT UNSIGNED CHECK (delay >=0),next_query_flagIN INT UNSIGNED,mirror_flagOUT INT UNSIGNED,mirror_hostgroup INT UNSIGNED,error_msg VARCHAR,OK_msg VARCHAR,sticky_conn INT CHECK (sticky_conn IN (0,1)),multiplex INT CHECK (multiplex IN (0,1,2)),gtid_from_hostgroup INT UNSIGNED,log INT CHECK (log IN (0,1)),apply INT CHECK(apply IN (0,1)) NOT NULL DEFAULT 0,attributes VARCHAR CHECK (JSON_VALID(attributes) OR attributes = '') NOT NULL DEFAULT '',comment VARCHAR)
  • rule_id:指定規則的 ID。該值越小,越先匹配。
  • active:是否啟用規則。
  • username:基于用戶名進行匹配。
  • schemaname:基于 schema 名進行匹配。
  • flagIN & flagOUT:定義規則的入口和出口,用于實現鏈式匹配規則。
  • client_addr:基于客戶端地址進行匹配。通過 client_addr 實現簡單的白名單功能。
  • proxy_addr & proxy_port:如果 ProxySQL 部署的服務器中有多個 IP 地址,可匹配來自指定 IP 的流量。
  • digest:基于 Query ID 進行匹配。
  • match_digest & match_pattern:基于正則表達式進行匹配,match_digest 是匹配模版化后的 SQL,match_pattern 是匹配原 SQL。
  • negate_match_pattern:設置為 1,表示沒匹配上 match_digest & match_pattern 的規則才為真。
  • re_modifiers:設置正則引起的修飾符。
  • replace_pattern:替換后的文本,用于查詢重寫。
  • destination_hostgroup:規則目標的主機組。
  • cache_ttl:設置結果集的緩存時長,單位是毫秒。
  • cache_empty_result:是否緩存空的結果集。
  • cache_timeout:暫未實現。
  • reconnect:暫無實現。
  • timeout:定義查詢的超時時長,單位是毫秒。如果查詢在指定時間沒有完成,則會被 ProxySQL kill 掉,如果不指定該字段,則由全局參數控制該行為 mysql-default_query_timeout 默認為 10 小時。
  • retries:查詢失敗重試的次數。
  • delay:定義查詢延遲執行的時長,單位是毫秒。
  • mirror_flagOUT & mirror_hostgroup:用于景象功能。
  • error_msg:匹配規則的操作將返回 error_msg,用于實現黑名單的功能。
  • log:是否將匹配規則的查詢記錄到審計日志中。不指定的話,則由全局參數 mysql-eventlog_defalut_log 決定,默認為 0。
  • apply:若設置為 1 的話,則操作匹配到該規則時,會直接被轉發給后端節點處理,不會再進行其他規則的匹配。

高級特性

本小節,介紹一下 ProxySQL 實用的高級特性。

SQL 審計

ProxySQL 可將流經它的 SQL 語句全部記錄下來,用于審計分析和問題定位。是一個非常實用的功能,不過數據庫流量如果比較大的話,會占用很大的存儲空間。

Admin> show variables like 'mysql-eventslog%';
+-----------------------------+-----------+
| Variable_name               | Value     |
+-----------------------------+-----------+
| mysql-eventslog_filename    |           |
| mysql-eventslog_filesize    | 104857600 |
| mysql-eventslog_default_log | 0         |
| mysql-eventslog_format      | 1         |
+-----------------------------+-----------+

各參數含義如下:

  • mysql-eventslog_filename:日志前綴名。默認為空,代表 SQL 審計沒有開啟。
  • mysql-eventslog_filesize:日志的最大大小。超過此限制,會對日志進行切割,默認為 100MB。
  • mysql-eventslog_default_log:是否開啟操作審計,默認為 0 不記錄。
  • mysql-eventslog_format:日志的格式。1 表示二進制格式 2 表示 JSON 格式。如果要查看二進制格式的內容,必須使用專用的解析工具 eventslog_reader_sample。

下面我們進行一個測試:

set mysql-eventslog_filename = 'query';
set mysql-eventslog_format = 2;
set mysql-eventslog_default_log = 1;LOAD MYSQL VARIABLES TO RUNTIME;
{"client":"172.16.104.56:38474","digest":"0xDC257DF652F9B5E6","duration_us":1764,"endtime":"2024-06-26 14:43:39.203870","endtime_timestamp_us":1719384219203870,"event":"COM_QUERY","hostgroup_id":2,"query":"select * from fractest1","rows_affected":0,"rows_sent":1,"schemaname":"test","server":"172.16.104.57:3306","starttime":"2024-06-26 14:43:39.202106","starttime_timestamp_us":1719384219202106,"thread_id":2,"username":"op_user"}

SQL 黑名單

當有一類 SQL 突然并發較高,打滿數據庫資源時,往往會導致數據庫整體變慢。此時處理的方法,往往是讓研發定位接口,然后停掉相關業務,及時止血,但也需要一定的時間,此時業務可能已經受損。
如果使用 ProxySQL 可以通過 SQL 黑名單的方式解決。接下來我們介紹通過 SQL 指紋來屏蔽 SQL 語句。
狀態庫 stats_mysql_query_digest 表中,記錄了一些 TOP SQL 的信息,可從該表中獲取 SQL 指紋。

select * from stats.stats_mysql_query_digest;-- digest 字段是 SQL 指紋
-- 0xDC257DF652F9B5E6 | select * from fractest1

獲取指紋后,需要寫入路由規則,需要注意的是,路由規則是按 rule_id 順序匹配的,所以屏蔽規則需要放在 rule_id 小的規則中,之前演示 rule_id = 1 和 2,所以限制改大。

Admin> update mysql_query_rules set rule_id = 11 where rule_id = 1;
Query OK, 1 row affected (0.00 sec)Admin> update mysql_query_rules set rule_id = 12 where rule_id = 2;
Query OK, 1 row affected (0.00 sec)

插入屏蔽規則:·

insert into mysql_query_rules (rule_id, destination_hostgroup, digest, error_msg, active, apply, comment) values (1, 1, '0xDC257DF652F9B5E6', 'request denied by rule', 1, 1, 'request denied by rule');load mysql query rules to runtime;
save mysql query rules to disk;

驗證屏蔽效果:

op_user@mysql 15:15:  [test]>select * from fractest1;
ERROR 1148 (42000): request denied by rule

ProxySQL Cluster

ProxySQL 作為一個中間價,本身是無狀態的,如果代理節點出現故障,那就會導致業務無法訪問。所以線上一般會部署多個節點,使用 VIP 或者 LVS 來進行故障切換。既然涉及到多個節點,ProxySQL 的配置調整需要實時同步,這樣將流量切換到任意一個代理都是正確可用的。這就是接下來 ProxySQL Cluster 的作用。

搭建 ProxySQL Cluster

開啟 proxysql 的集群功能,需要:

  • 配置 cluster 賬號,用于查詢對比集群內各 proxysql 節點的配置信息
  • 配置 proxysql_servers,將集群內的 proxysql 節點信息添加到 proxysql_servers 表

以上操作需要到組成集群的每一個 proxysql 節點上執行。
通過參數 admin-cluster_username 和 admin-cluster_password 設置 cluster 賬號。不能使用 admin 賬號作為cluster 賬號,因為 admin 賬號只能在本地(127.0.0.1)登陸。
同時還需要將 cluster 賬號添加到參數 admin-admin_credentials 中。

set admin-admin_credentials = 'admin:admin;clusteradmin:passadmin';set admin-cluster_username='clusteradmin';
set admin-cluster_password='passadmin';load admin variables to runtime;
save admin variables to disk;

將組成 proxysql 集群的多個節點的信息添加到 proxysql_servers 表。

mysql> show create table proxysql_servers\G
*************************** 1. row ***************************table: proxysql_servers
Create Table: CREATE TABLE proxysql_servers (hostname VARCHAR NOT NULL,port INT NOT NULL DEFAULT 6032,weight INT CHECK (weight >= 0) NOT NULL DEFAULT 0,comment VARCHAR NOT NULL DEFAULT '',PRIMARY KEY (hostname, port) )
1 row in set (0.00 sec)insert into proxysql_servers values('172.16.104.55', 6032, 1, 'proxysql node 1');
insert into proxysql_servers values('172.16.104.56', 6032, 1, 'proxysql node 2');LOAD PROXYSQL SERVERS TO RUNTIME;
save PROXYSQL SERVERS TO disk;

參考文檔

【1】ProxySQL Multi layer configuration system

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40116.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40116.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40116.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java實現日志全鏈路追蹤.精確到一次請求的全部流程

廣大程序員在排除線上問題時,會經常遇見各種BUG.處理這些BUG的時候日志就格外的重要.只有完善的日志才能快速有效的定位問題.為了提高BUG處理效率.我決定在日志上面優化.實現每次請求有統一的id.通過id能獲取當前接口的全鏈路流程走向. 實現效果如下: 一次查詢即可找到所有關…

自定義一個背景圖片的高度,隨著容器高度的變化而變化,小于圖片的高度時裁剪,大于時拉伸100%展示

1、通過js創建<image?>標簽來獲取背景圖片的寬高比&#xff1b; 2、當元素的高度大于原有比例計算出來的高度時&#xff0c;背景圖片的高度拉伸自適應100%&#xff0c;否則高度為auto&#xff0c;會自動被裁減 3、背景圖片容器高度變化時&#xff0c;自動計算背景圖片的…

Android network - NUD檢測機制(Android 14)

Android network - NUD檢測機制 1. 前言2. 源碼分析2.1 ClientModeImpl2.2 IpClient2.3 IpReachabilityMonitor 1. 前言 在Android系統中&#xff0c;NUD&#xff08;Neighbor Unreachable Detection&#xff09;指的是網絡中的鄰居不可達檢測機制&#xff0c;它用于檢測設備是…

數據驅動測試實踐:Postman 中使用數據文件的指南

Postman 是一個強大的 API 開發和測試工具&#xff0c;它支持數據驅動測試&#xff0c;允許測試者使用外部數據文件來驅動測試&#xff0c;實現測試用例的參數化。數據驅動測試可以顯著提高測試效率&#xff0c;減少重復工作&#xff0c;并允許測試用例覆蓋更廣泛的輸入場景。本…

一文了解常見DNS問題

當企業的DNS出現故障時&#xff0c;為不影響企業的正常運行&#xff0c;團隊需要能夠快速確定問題的性質和范圍。那么有哪些常見的DNS問題呢&#xff1f; 域名解析失敗&#xff1a; 當您輸入一個域名&#xff0c;但無法獲取到與之對應的IP地址&#xff0c;導致無法訪問相應的網…

【代碼隨想錄算法訓練營第五十九天|卡碼網110.字符串接龍、105.有向圖的完全可達性、106.島嶼的周長】

文章目錄 卡碼網110.字符串接龍105.有向圖的完全可達性106.島嶼的周長 卡碼網110.字符串接龍 這題是在字符串上進行廣搜&#xff0c;字符串廣搜是對一個字符串按照位置來搜索&#xff0c;與原字符串只有一個位置字符不同那么就是在原字符串的基礎上距離加1。因此需要一個字典來…

獲取VC賬號,是成為亞馬遜供應商的全面準備與必要條件

成為亞馬遜的供應商&#xff0c;擁有VC&#xff08;Vendor Central&#xff09;賬號&#xff0c;是眾多制造商和品牌所有者的共同目標。這不僅代表了亞馬遜對供應商的高度認可&#xff0c;也意味著獲得了更多的銷售機會和更廣闊的市場前景。 全面準備與必要條件是獲取VC賬號的關…

代碼轉換成AST語法樹移除無用代碼console.log、import

公司中代碼存在大量,因此產生 可以使用 @babel/parser 解析代碼生成 AST (抽象語法樹),然后使用 @babel/traverse 進行遍歷并刪除所有的 console.log 語句,最后使用 @babel/generator 生成修改后的代碼。 這里有一個網址,可以線上解析代碼轉換成AST語法樹: https://astex…

Python爬蟲康復訓練——筆趣閣《神魂至尊》

還是話不多說&#xff0c;很久沒寫爬蟲了&#xff0c;來個bs4康復訓練爬蟲&#xff0c;正好我最近在看《神魂至尊》&#xff0c;爬個txt文件下來看看 直接上代碼 """ 神魂至尊網址-https://www.bqgui.cc/book/1519/ """ import requests from b…

【C++】 解決 C++ 語言報錯:未定義行為(Undefined Behavior)

文章目錄 引言 未定義行為&#xff08;Undefined Behavior, UB&#xff09;是 C 編程中非常危險且難以調試的錯誤之一。未定義行為發生時&#xff0c;程序可能表現出不可預測的行為&#xff0c;導致程序崩潰、安全漏洞甚至硬件損壞。本文將深入探討未定義行為的成因、檢測方法…

零基礎STM32單片機編程入門(七)定時器PWM波輸出實戰含源碼視頻

文章目錄 一.概要二.PWM產生框架圖三.CubeMX配置一個TIME輸出1KHZ&#xff0c;占空比50%PWM波例程1.硬件準備2.創建工程3.測量波形結果 四.CubeMX工程源代碼下載五.講解視頻鏈接地址六.小結 一.概要 脈沖寬度調制(PWM)&#xff0c;是英文“Pulse Width Modulation”的縮寫&…

通過營銷本地化解鎖全球市場

在一個日益互聯的世界里&#xff0c;企業必須接觸到全球各地的不同受眾。營銷本地化是打開這些全球市場的關鍵。它包括調整營銷材料&#xff0c;使其與不同地區的文化和語言細微差別產生共鳴。以下是有效的營銷本地化如何推動您的全球擴張&#xff0c;并用實際例子來說明每一點…

UrbanGPT: Spatio-Temporal Large Language Models

1.文章信息 本次介紹的文章是2024年arxiv上一篇名為《UrbanGPT: Spatio-Temporal Large Language Models》的文章&#xff0c;UrbanGPT旨在解決城市環境中的時空預測問題&#xff0c;通過大語言模型&#xff08;LLM&#xff09;的強大泛化能力來應對數據稀缺的挑戰。 2.摘要 Ur…

SQLAlchemy批量操作數據

批量插入 session.bulk_insert_mappings(ModelClass, list(dict()))批量更新 session.bulk_update_mappings(ModelClass, list(dict())

Flutter的生命周期方法

Flutter的生命周期執行時機可以分為兩個主要部分&#xff1a;Flutter本身的組件生命周期&#xff08;widget生命周期&#xff09;和平臺相關的應用程序生命周期&#xff08;APP生命周期&#xff09;。 Widget生命周期 Widget生命周期可以細分為三個階段&#xff1a; 初始化階…

centos ssh一鍵升級到9.8版本腳本

背景 前端時間暴露出ssh漏洞&#xff0c;需要將服務器ssh版本&#xff0c;目前ssh版本最新版為9.8&#xff0c;故在服務器測試&#xff0c;準備將所有服務器ssh版本升級。腳本在centos7.6上親測可用。#!/bin/bash #Author Mr zhangECHO_GREEN() {echo -e "\033[32m $1...…

昇思MindSpore學習總結九——FCN語義分割

1、語義分割 圖像語義分割&#xff08;semantic segmentation&#xff09;是圖像處理和機器視覺技術中關于圖像理解的重要一環&#xff0c;AI領域中一個重要分支&#xff0c;常被應用于人臉識別、物體檢測、醫學影像、衛星圖像分析、自動駕駛感知等領域。 語義分割的目的是對圖…

【楚怡杯】職業院校技能大賽 “Python程序開發”賽項樣題三

Python程序開發實訓 &#xff08;時量&#xff1a;240分鐘&#xff09; 中國XX 實訓說明 注意事項 1. 請根據提供的實訓環境&#xff0c;檢查所列的硬件設備、軟件清單、材料清單是否齊全&#xff0c;計算機設備是否能正常使用。 2. 實訓結束前&#xff0c;在實訓平臺提供的…

從數據到智能,英智私有大模型助力企業實現數智化發展

在數字化時代&#xff0c;數據已經成為企業最重要的資源。如何將這些數據轉化為實際的業務價值&#xff0c;是每個企業面臨的重要課題。英智利用業界領先的清洗、訓練和微調技術&#xff0c;對企業數據進行深度挖掘和分析&#xff0c;定制符合企業業務場景的私有大模型&#xf…

篩選有合并單元格的數據

我們經常會使用合并單元格&#xff0c;比如下面表格&#xff0c;因為一個部門中會有不同的員工&#xff0c;就會出現如下表格&#xff1a; 但是當按部門去篩選的時候&#xff0c;會發現并不是我們預期的結果&#xff0c;部門列有空值&#xff0c;每個部門只有第一行數據可以被…