ProxySQL官檔翻譯__12_ProxySQL配置之ProxySQL_Cluster

12_ProxySQL配置之ProxySQL_Cluster

備註:文章編寫時間201904-201905期間,後續官方在github的更新沒有被寫入
~
~
注意:ProxySQL羣集實現可能會發生變化,因爲roadmap(設計規劃圖)中的所有功能尚未實現。

一、前言[Preface]

ProxySQL是一個分散式的代理,通常建議將其部署在應用程序附近。這種方法似乎可以很好地擴展到數百個節點,因爲它被設計爲在運行時可以輕鬆重新配置。
它也允許你使用配置管理軟件(如Ansible/Chef/Puppet/Salt(按字母順序))或服務發現軟件(如Etcd/Consul/ZooKeeper)來協調和重新配置ProxySQL實例。
這使得ProxySQL可以高度自定義,並可以在任何使用這些技術的設置中採用,甚至可以通過自制工具重新配置。當然,使用這種管理方式來組建集羣也有一些缺點:

  • 1)這使得ProxySQL需要並依賴外部軟件(配置管理軟件本身);
  • 2)前一點也意味着這種方法本身不受支持;
  • 3)整個管理系統中的任務執行時長是不可預測的;
  • 4)沒有防止網絡分裂的保護;

因此,ProxySQL 1.4.x嘗試本機支持羣集。但,正如開頭已經指出的那樣,這些功能可能會發生變化,因爲並未實現(roadmap)設計規劃圖中的所有功能。

目前,ProxySQL集羣解決方案中有兩個主要組件:

  • 1)monitoring
  • 2)re-configuration

這兩個組件(monitoring和remote reconfiguration)可用於4個表:
mysql_query_rules
mysql_servers
mysql_users
proxysql_servers

將來會添加更多內容,請參閱roadmap(設計規劃圖)

二、Monitoring

爲了支持對羣集的監控,引入了幾個新的表、命令和變量。

1、Admin變量[Admin variables]

添加了與Cluster解決方案相關的幾個新變量。它們都是Admin的變量,這意味着要加載它們,需要LOAD ADMIN VARIABLES TO RUNTIME命令。

1)定義了同步內容的變量

admin-checksum_mysql_query_rules ==>布爾類型變量。當爲true(默認)時,每次執行LOAD MYSQL QUERY RULES TO RUNTIME時,ProxySQL都會生成新的配置校驗和。如果設置爲false,則不會自動傳播新配置,也不會從遠程節點同步;
admin-checksum_mysql_servers ==>布爾類型變量。當爲true(默認)時,每次執行LOAD MYSQL SERVERS TO RUNTIME時,ProxySQL都會生成新的配置校驗和。如果設置爲false,則不會自動傳播新配置,也不會從遠程節點同步;
admin-checksum_mysql_users ==>布爾類型變量。如果爲true(默認),則每次執行LOAD MYSQL USERS TO RUNTIME時,ProxySQL都會生成新的配置校驗和。如果設置爲false,則不會自動傳播新配置,也不會從遠程節點同步。如果您有數百萬用戶,請禁用此功能並且不要依賴它,因爲它可能非常慢;

2)定義憑證的變量

admin-cluster_username 和 admin-cluster_password ==>監視其他proxysql實例使用此憑據。請注意,對username/password也應該出現在admin-admin_credentials中,否則連接將失敗。如果未定義admin-cluster_username,則Clustering不會執行任何檢查;

3)定義檢查間隔/頻率的變量

admin-cluster_check_interval_ms ==>此變量定義前後2次校驗和檢查之間的時間間隔,單位毫秒。默認值:1000 最小值:10 最大值:300000
admin-cluster_check_status_frequency ==>如果大於0,則此變量定義了在每次執行狀態檢查時,需要執行多少次校驗和檢查。默認值:10 最小值:0 最大值:10000

在遠程同步完成後,立即將新的更改信息保存到磁盤通常是個好主意。這樣,服務重啓後配置將是已經同步過的。

與同步到磁盤相關的變量:
admin-cluster_mysql_query_rules_save_to_disk ==>布爾類型變量。當爲true(默認)時,如果在遠程同步並加載到RUNTIME層之後,則新的mysql查詢規則也會保存到磁盤;
admin-cluster_mysql_servers_save_to_disk ==>布爾類型變量。當爲true(默認)時,如果在遠程同步並加載到RUNTIME層之後,則新的mysql服務器也會保存到磁盤;
admin-cluster_mysql_users_save_to_disk ==>布爾類型變量。當爲true(默認)時,如果在遠程同步並加載到RUNTIME層之後爲,則新的mysql用戶也會保存到磁盤;
admin-cluster_proxysql_servers_save_to_disk ==>布爾類型變量。當爲true(默認)時,如果在遠程同步並加載到RUNTIME層之後爲,則新的proxysql服務器也會保存到磁盤;

由於各種不同的原因,可能會出現同時重新配置多個ProxSQL實例的情況。

例如,每個proxysql實例都可能監視一個mysql複製拓撲結構,它會自動檢測MySQL的故障轉移,並且在很短的時間內(可能不到一秒鐘)各個proxysql實例都會將最新信息聚合到相同的配置,而不需要彼此同步。

類似地,對於臨時的網絡問題或處理速度較慢的MySQL實例,當被所有代理檢測到時,它們可能會自動避開問題節點。所有代理將採取相同的操作,而無需彼此同步。或者,如果由於複製滯後而導致從屬設備滯後,則所有代理將自動避開該節點,並相互獨立地執行相同的規避處理操作。

因此,可以將ProxySQL Cluster配置爲不與遠程節點即刻同步信息,而是在觸發遠程同步之前等待一定次數的檢查(確認)。如果在此閾值之後本地和遠程配置仍然不同,則會觸發同步。

4)定義信息同步前執行檢查的變量

admin-cluster_mysql_query_rules_diffs_before_sync ==>定義出現多少次不匹配的檢查時將觸發mysql_query_rules的同步。默認值:3 最小值:0(從不同步)最大值:1000
admin-cluster_mysql_servers_diffs_before_sync ==>定義出現多少次不匹配的檢查時觸發mysql_servers的同步。默認值:3 最小值:0(從不同步)最大值:1000
admin-cluster_mysql_users_diffs_before_sync ==>定義出現多少次不匹配的檢查時觸發mysql_users的同步。默認值:3 最小值:0(從不同步)最大值:1000
admin-cluster_proxysql_servers_diffs_before_sync ==>定義出現多少次不匹配的檢查時觸發proxysql_servers的同步。默認值:3 最小值:0(從不同步)最大值:1000

2、Configuration tables

1)表 proxysql_servers

表結構如下:

Admin>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)

該表是配置表,定義了集羣中互相監控着的ProxySQL實例的列表。

hostname ==>集羣中同伴ProxySQL實例的主機名
port ==>集羣中同伴ProxySQL實例的端口
weight ==>集羣中同伴ProxySQL實例的權重
comment ==>集羣中同伴ProxySQL實例的備註信息

以上信息也支持配置文件中設置:

proxysql_servers =
(
    {
        hostname="172.16.0.101"
        port=6032
        weight=0
        comment="proxysql1"
    },
    {
        hostname="172.16.0.102"
        port=6032
        weight=0
        comment="proxysql2"
    }
)

2)表 runtime_proxysql_servers

表結構如下:

Admin>SHOW CREATE TABLE runtime_proxysql_servers \G
*************************** 1. row ***************************
       table: runtime_proxysql_servers
Create Table: CREATE TABLE runtime_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)

與其他runtime_類的表一樣,這是基表proxysql_servers 運行太下對應得表。

3)表 runtime_checksums_values

表結構如下:

Admin>SHOW CREATE TABLE runtime_checksums_values \G
*************************** 1. row ***************************
       table: runtime_checksums_values
Create Table: CREATE TABLE runtime_checksums_values (
    name VARCHAR NOT NULL,
    version INT NOT NULL,
    epoch INT NOT NULL,
    checksum VARCHAR NOT NULL,
    PRIMARY KEY (name))
1 row in set (0.00 sec)

表 runtime_checksums_values 是第一個runtime_類的表,但它不是基表的RUNTIME時的表示,而是記錄了LOAD TO RUNTIME命令執行時間的日誌類記錄表。
它的內容類似如下這樣:

Admin> SELECT * FROM runtime_checksums_values;
+-------------------+---------+------------+--------------------+
| name              | version | epoch      | checksum           |
+-------------------+---------+------------+--------------------+
| admin_variables   | 0       | 0          |                    |
| mysql_query_rules | 5       | 1503442167 | 0xD3BD702F8E759B1E |
| mysql_servers     | 1       | 1503440533 | 0x6F8CEF0F4BD6456E |
| mysql_users       | 1       | 1503440533 | 0xF8BDF26C65A70AC5 |
| mysql_variables   | 0       | 0          |                    |
| proxysql_servers  | 2       | 1503442214 | 0x89768E27E4931C87 |
+-------------------+---------+------------+--------------------+
6 rows in set (0,00 sec)

注意:
在6個LOAD RUNTIME命令中,只有4個可以生成校驗和信息:
LOAD MYSQL QUERY RULES TO RUNTIME ==>如果 admin-checksum_mysql_query_rules 參數爲true,則生成新的校驗和。
LOAD MYSQL SERVERS TO RUNTIME ==>如果 admin-checksum_mysql_servers 參數爲true,則生成新的校驗和。(mysql_group_replication_hostgroups表例外)
LOAD MYSQL USERS TO RUNTIME ==>如果 admin-checksum_mysql_users 參數爲true,則生成新的校驗和。
LOAD PROXYSQL SERVERS TO RUNTIME ==>始終生成新的校驗和。
LOAD ADMIN VARIABLES TO RUNTIME ==>不生成校驗和。
LOAD MYSQL VARIABLES TO RUNTIME ==>不生成校驗和。

新命令:
LOAD PROXYSQL SERVERS FROM MEMORY / LOAD PROXYSQL SERVERS TO RUNTIME ==>將ProxySQL服務器信息從MEMORY層數據庫加載到RUNTIME層數據結構中。
SAVE PROXYSQL SERVERS TO MEMORY / SAVE PROXYSQL SERVERS FROM RUNTIME ==>將ProxySQL服務器信息從RUNTIME層數據結構持久保存到MEMORY層數據庫。
LOAD PROXYSQL SERVERS TO MEMORY / LOAD PROXYSQL SERVERS FROM DISK ==>將ProxySQL服務器信息從DISK層數據庫加載到MEMORY層數據庫。
LOAD PROXYSQL SERVERS FROM CONFIG ==>將ProxySQL服務器信息從配置文件加載到MEMORY層數據庫。
SAVE PROXYSQL SERVERS FROM MEMORY / SAVE PROXYSQL SERVERS TO DISK ==>將ProxySQL服務器信息從MEMORY層數據庫持久保存到DISK層數據庫。

3、stats tables

在 stats 庫中新增了3個表。

1)表 stats_proxysql_servers_checksums

表結構如下:

Admin>SHOW CREATE TABLE stats.stats_proxysql_servers_checksums\G
*************************** 1. row ***************************
       table: stats_proxysql_servers_checksums
Create Table: CREATE TABLE stats_proxysql_servers_checksums (
    hostname VARCHAR NOT NULL,
    port INT NOT NULL DEFAULT 6032,
    name VARCHAR NOT NULL,
    version INT NOT NULL,
    epoch INT NOT NULL,
    checksum VARCHAR NOT NULL,
    changed_at INT NOT NULL,
    updated_at INT NOT NULL,
    diff_check INT NOT NULL,
    PRIMARY KEY (hostname, port, name) )
1 row in set (0.00 sec)

此表記錄了集羣中其他代理的校驗和及其狀態:
hostname ==>集羣中同伴ProxySQL實例;
port ==>集羣中同伴ProxySQL實例,默認6032;
name ==>在表 runtime_checksums_values 中記錄的模塊名稱;
version ==>在表 runtime_checksums_values 中記錄的模塊版本號;請注意,剛剛啓動的ProxySQL實例將具有version = 1的版本號:而ProxySQL實例是永遠不會與具有version = 1的另一個實例同步的, 因爲剛啓動的ProxyQL實例不太可能是真實信息的來源。這可以防止新的加入節點破壞當前的羣集配置。
epoch ==>在表 runtime_checksums_values 中記錄的模塊epoch號;
checksum ==>在表 runtime_checksums_values 中記錄的模塊校驗和(checksum);
changed_at ==>檢測到校驗和被更改的時間戳;
updated_at ==>此條目最近一次刷新的時間戳;
diffcheck ==>一個計數器,用於存放在對與當前ProxySQL實例進行狀態監控、信息交互的遠程ProxySQL實例(集羣中的同伴實例)的校驗和與本地校驗和進行檢查時出現結果不同的次數。當該值達到重新配置算法的閥值時,將觸發重新配置。如果同一配置同時應用於多個代理,或者在發生故障轉移時代理正在重新配置自己,並且它們很可能在不需要重新同步的情況下對配置進行了彙總,則此功能非常有用。(另請參見參數變量 cluster*_diffs_before_sync )如果diff_check在增加了很多的情況下卻沒有觸發同步,則意味着遠程對等方不是真實信息的可靠來源,例如,version=1。另一方面,如果遠程對等機與集羣的其他部分不同步,這意味着集羣沒有可靠的真實信息來源。當集羣中的所有代理以不同的配置啓動時,會發生這種情況,並且無法自動確定哪個配置正確。這時在其中一個節點上運行 LOAD module TO RUNTIME 命令,將自動"選擇"該節點以成爲該特定模塊的真實來源。

2)表 stats_proxysql_servers_metrics

表結構如下:

Admin>SHOW CREATE TABLE stats.stats_proxysql_servers_metrics \G
*************************** 1. row ***************************
       table: stats_proxysql_servers_metrics
Create Table: CREATE TABLE stats_proxysql_servers_metrics (
    hostname VARCHAR NOT NULL,
    port INT NOT NULL DEFAULT 6032,
    weight INT CHECK (weight >= 0) NOT NULL DEFAULT 0,
    comment VARCHAR NOT NULL DEFAULT '',
    response_time_ms INT NOT NULL,
    Uptime_s INT NOT NULL,
    last_check_ms INT NOT NULL,
    Queries INT NOT NULL,
    Client_Connections_connected INT NOT NULL,
    Client_Connections_created INT NOT NULL,
    PRIMARY KEY (hostname, port) )
1 row in set (0.00 sec)

該表記錄了集羣模塊在同伴實例上使用 SHOW MYSQL STATUS 命令檢查到的指標數據。
列含義如下:
hostname ==>集羣中同伴ProxySQL實例的主機名;
port ==>集羣中同伴ProxySQL實例的端口;
weight ==>集羣中同伴ProxySQL實例的權重與proxysql_servers.weight相同;
comment ==>集羣中同伴ProxySQL實例的備註與proxysql_servers.comment相同;
response_time_ms ==>運行SHOW MYSQL STATUS時的響應時間,以毫秒爲單位;
Uptime_s ==>集羣中同伴的正常運行時間(秒);
last_check_ms ==>上次執行檢測的時間(毫秒);
Queries ==>同伴執行的查詢數;
Client_Connections_connected ==>連接同伴的客戶端連接數;
Client_Connections_created ==>同伴創建的客戶端連接數;

注意:
所有的狀態變量都是由同伴實例檢索的,但是隻有很少的一部分被監視,以便能夠檢查同伴實例是否啓動、運行和處理流量。
目前,此功能僅用於調試目的,但未來版本將使用這些指標來了解遠程同伴的運行狀況。

3)表 stats_proxysql_servers_status

目前尚未使用

4、帶寬考慮[Bandwidth consideration]

在上述架構中,所有節點都監視所有其他節點。是完全網狀的點對點網絡。
爲了減少網絡使用,節點並不總是交換整個校驗和列表;相反,交換一個由所有版本和所有校驗和組合而成的校驗和。如果此全局校驗和被更改,則再檢索校驗和的詳細列表。使用這種技術,在一個200個節點的集羣中,每1000毫秒相互監視,每個節點需要50KBpb的帶寬。

三、重新配置[Re-configuration]

由於代理是互相監視的,所以它們可以立即知道配置的校驗和何時被更改了,這也意味着自身的配置也需要更改。如果某個配置發生了更改,則會對照其自身的配置進
行檢查,因爲遠程同伴機的配置及自己的配置可能同時或在短時間內發生了更改。
如果他們不同:

  • 1)如果自己的version是1,與找到的同伴的version是大於1並且擁有最高的epoch,則立即進行同步。
  • 2)如果自己的version大於1,則開始計算它們之間的檢查差異數。當它們的差異檢查數大於

clusternamediffs_before_sync 並且 clusternamediffs_before_sync
自身也大於0時,則查找version >1且具有最高epoch的同伴,找到後並立即同步(注意:可能出現檢測到的節點和執行同步的節點不一樣;即檢測到一個的節點,但同步是對另一個節點執行的。這是因爲同步是用具有最高epoch的節點完成的,所以所有節點都將聚合爲一致的配置。如果在檢測和執行同步的中間發生了聚合,那麼就會出現這樣的情況,但這不影響最後的結果)

執行同步的過程如下:

  • 1)同一個連接在執行健康檢測時會執行一系列的類似 SELECT _list_ofcolumns FROM runtime_module 的 SELECT 語句;
    例如:
    SELECT hostgroup_id, hostname, port, status, weight, compression, max_connections, max_replication_lag, use_ssl, max_latency_ms, comment FROM runtime_mysql_servers;
    SELECT writer_hostgroup, reader_hostgroup, comment FROM runtime_mysql_replication_hostgroups;
  • 2)刪除本地配置表。
    例如:
    DELETE FROM mysql_servers;
    DELETE FROM mysql_replication_hostgroups;
  • 3)將從遠程同伴機上檢索到的內容插入到本地配置表中。

  • 4)執行一個內部的 LOAD module_name TO RUNTIME 命令,這將增加版本號並創建一個新的校驗和。

  • 5)如果 clusternamesave_to_disk is true 爲true,則發出內部的 SAVE module_name TO DISK 。

四、研發中的功能[TODO]

  • 1)添加對MySQL Group Replication的支持。
  • 2)添加對Scheduler(調度)的支持。

1、設計規劃圖[Roadmap]

這只是與羣集相關的功能的概述,而不是完整列表。以下列表尚未實現。
實際實施可能與現在列出的不同:

  • 1)主從Master的選舉:這裏有意選擇Master這個詞而不是leader;
  • 2)只有master代理是可寫/可配置的;
  • 3)實現從主服務器到從服務器的類似MySQL的複製,允許實時推送配置而不是拉動配置;
  • 4)實現從主服務器到候選主服務器的類似MySQL的複製;
  • 5)實現從候選主服務器到從服務器的類似MySQL的複製;
  • 6)創建一個只包含候選master的法定人數:普通Slave不是法定人數的一部分。

五、疑問即答案[Q&A]

1、如果在每個proxysql服務器上同時加載不同的配置,那麼需要將哪個配置"傳播"到所有其他節點上呢?是最後一個嗎?

master的概念和master的選舉還沒有實施。這意味着一個 LOAD 命令可以同時在多個節點上執行(拿多主做個類比),並且每個節點都將觸發一個基於時間戳的衝突解決方案的自動重新配置。
如果在多個proxysql實例上同時加載相同的配置,那麼它們應該自動聚合爲一致的配置。
如果是在不同的時刻在多個proxysql實例上分別加載了不同的配置,則最終最後一個被加載的配置將勝出。
如果同時在多個proxysql實例上加載不同的配置,那麼這些不同的配置都將開始傳播,直到它們因爲衝突解決方式不可行而導致無法收斂到一個點爲止(聚合爲一致的配置)。
好在,每個proxysql都知道其他每個節點的配置校驗和,因此很容易檢測和監視不匹配的配置。

2、誰將此配置寫入所有這些節點?

目前使用的是拉取機制,因此檢測到需要重新配置的節點將從具有最新配置的節點中拉取配置並在本地應用。

3、你打算如何實施選舉?RAFT協議?

選舉的實施是寫入設計規劃圖中的,但可能不是RAFT共識協議。
ProxySQL使用表來存儲配置信息,它使用MySQL協議來爲查詢其健康狀況和配置信息的同伴實例執行請求,它使用MySQL協議來實現心跳等等:由於這些原因,在ProxySQL場景下,MySQL協議本身可能比RAFT協議更通用。

4、如果由於某種原因,在重新配置的情況下,其中一個節點將無法獲取新的配置,會發生什麼情況?

變更是異步傳播的。因此,其中一個節點是有可能無法獲取新的配置;例如,在ProxySQL開始重新啓動時發生了網絡問題情的況下。然而,一但環境正常後,當ProxySQL實例檢測到它的一個同伴實例有一個更新的配置時,它將自動獲取這個最新的配置信息。

5、CrossDC怎麼樣?在每個Docker中都有一個集羣,它的最佳實踐是什麼?

集羣沒有邊界,因此可以跨多個DC擁有單個集羣,或者在同一個DC擁有多個集羣,或者跨多個DC擁有多個集羣。這實際上取決於具體的使用場景。唯一的限制是每個proxysql實例都必須且只能屬於一個集羣。集羣沒有名稱,爲了確保節點不會錯誤地加入錯誤的集羣,確保每個集羣使用不同的憑證是很重要的。請查看admin-admin_credentials,
admin-cluster_username and admin-cluster_password.

6、在某種程度上通過複製拷貝的方式來配置crossdc可能是一個很好的特性,但它更喜歡將流量發送到最接近本地proxysql服務器的後端服務器。因而,我現在用權重來做流量分配管控。

對於這個特定的情況,我認爲爲每個DC創建一個不同的集羣更有意義,因爲配置會有所不同。

7、新的proxysql如何加入羣集?

引導非常簡單:在ProxySQL集羣中至少有一個同伴實例(對等機)在運行即可。

8、所有的其他ProxySQL服務器如何知道有一個新節點?

他們不會自動知道,這是爲了防止新節點損壞集羣。換句話說,一個新的節點可以在連接後立即提取配置,但不能將自己作爲真實信息的來源進行傳播。爲了讓其他proxysql實例知道存在一個新節點,只需在當前集羣的任何節點的PROXYSQL服務器中添加該新節點,並執行 LOAD PROXYSQL SERVERS TO RUNTIME 即可。

~
~
完畢!

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