一、背景
崑崙分散式資料庫使用MySQL做儲存節點,稱為kunlun-storage。Kunlun-storage目前最新版本基於percona-mysql-8.0.26開發,在此社群版本基礎上,我們補充了MySQL的XA事務和binlog複製方面的容錯和資料一致性漏洞,增加了kunlun資料庫叢集需要的若干功能,並且增強了其效能。
我們也一直在合併上游版本,持續彙集MySQL社群的最新成果到kunlun-storage中。
在Kunlun-storage Fullsync機制開發完成之前,我們一直在使用MySQL Group Replication(MGR)實現儲存叢集高可用。
為了實現更好的資料寫入效能包括更高的吞吐量和更短的延時,以及降低對儲存系統和網路頻寬的消耗,並且在高可用方面實現更加靈活的策略,我們在kunlun-storage中設計並開發了Fullsync高可用機制。
二、Kunlun-storage Fullsync功能簡介
Kunlun-storage Fullsync
概況和原理
崑崙資料庫的Fullsync機制是一種儲存叢集的高可用機制,它用於確保一個儲存叢集在發生節點故障、網路分割槽等問題時,該叢集中存在可用的備機含有所有向使用者確認提交成功的事務的binlog,以便可以按需選舉出新的主節點,確保叢集持續可以寫入,實現高可用。
崑崙資料庫的Fullsync機制基於MySQL久經考驗的Row Based Replication(RBR)binlog複製機制,實現了主備複製的強同步,也就是確保主節點上提交的每一筆事務
---包括顯式普通事務(即begin 。。。Commit),autocommit的update/delete/insert語句,以及XA事務
---在完成內部的事務提交流程(即engine log和binlog flush&sync和engine commit 這三個階段)之後,持續等待直到收到了足夠數量的備機的確認(ACK)之後,才向客戶端(在崑崙資料庫中就是計算節點)確認這個事務成功提交。
一個ACK是一個binlog檔案標識和偏移值的組合,它代表的是這個位置之前的binlo
g都已經被這個備機收到並且持久儲存(刷盤)。
這樣,所有那些在主節點的binlog檔案中其binlog儲存在此位置之前的事務都得到了確認,它們的提交操作就都可以返回成功狀態給客戶端了。
一個備機傳送該ACK是向其主節點確認收到並持久化(刷盤)了一組事務的binlog到其relay log檔案中。只有主節點收到這個確認,才向客戶端返回事務提交成功的確認狀態,客戶端收到此結果後才能傳送下一條SQL語句給崑崙資料庫。
只有向客戶端返回事務成功提交(或prepare),崑崙分散式資料庫才有義務保障這樣的事務的改動不丟失(即ACID的D,Durability)。
Kunlun-storage Fullsync的前提條件
Kunlun-storageFullsync機制需要一組特定的引數組合才能正常工作。
Kunlun-storage自帶的引數配置模版檔案中含有經過我們開發團隊調優之後的引數設定,其中包含了fullsync功能需要的引數設定。
Kunlun資料庫叢集的所有儲存節點例項都是使用其自帶的引數模版建立的。
Kunlun-storage Fullsync的功能設計與實現
kunlun-storage的fullsync機制是一種after-commit的同步模式。
在處理使用者會話thd的工作執行緒thr 完成事務T提交或者prepare(XA prepare)並且還未向客戶端確認成功(即傳送OK包)之前,主節點檢查事務T的binlog是否已經收到了足夠數量的備機的ACK(備機的ACK 確認收到若干個事務的binlog)
---此條件稱為釋放條件。
如果釋放條件滿足那麼thr直接返回成功狀態給客戶端並且完成本次請求處理,否則工作執行緒thr就把會話物件thd放到fullsync ack等待佇列,然後去處理其他連線中收到的請求。
主節點收到ACK後會對等待佇列中的會話做釋放條件檢查,滿足釋放條件條件的會話會被釋放,也就是返回成功狀態給客戶端。在等待備機ACK的過程中,使用者回話並不佔用工作執行緒。
如果超時(fullsync_timeout)未收到足夠的ack來釋放一個等待的會話時,kunlun-storage有兩種策略,由全域性變數disable_fullsync_on_slave_ack_timeout來控制:
-
如果disable_fullsync_on_slave_ack_timeout=1,那麼fullsync會自動退化為非同步。這樣後續等待的事務將不再做fullsync等待。當主節點再次收到備機ack後,會自動啟用fullsync機制。
-
如果disable_fullsync_on_slave_ack_timeout=0,那麼fullsync等待超時的會話,會返回錯誤(錯誤號9000)給客戶端,對於崑崙資料庫叢集來說,就是計算節點收到了這個錯誤,會觸發主備切換。
備機收到事件組
(event group,即binlog事務,包括普通顯式事務,XA事務第一階段,XA事務第二階段,DDL語句,autocommit語句這幾種型別。下文簡稱EG)的終止binlog事件
(XID_EVENT,XA_PREPARE_LOG_EVENT或者DDL事務
)後,
它會決定是否需要把收到的若干個EG寫到relay log檔案並且刷到持久儲存系統中
(即flush&fsync relay log)
,然後傳送ACK給主節點來確認持久化了這些收到的EG。
這個決定基於最小化資源消耗和最最佳化效能來做出
---如果備機收到了足夠多的EG(配置引數:fullsync_fsync_ack_least_txns)或者足夠量的binlog(配置引數:fullsync_fsync_ack_least_event_bytes) ,或者太久沒有傳送ACK了( fullsync_fsync_ack_wait_max_milli_secs), 他就會flush&fsync relay log然後傳送ACK。
一個ACK包含這些資訊:備機的server_id,落盤的最後一個EG在主節點binlog中的終止位置(檔案編號和偏移值)。
主節點收到一個備機的ACK後就可以確信這個備機收到並持久儲存了ACK位置之前的所有EG。
使用fullsync_relaylog_fsync_ack_level 全域性變數來控制一個備機節點的Fullsync機制在flush&fsync relay log和傳送ACK的行為,其含義如下:
fullsync_relaylog_fsync_ack_level |
|
|
不flush或者fsync relay log也不傳送ACK |
|
|
|
Flush&fsync relay log後傳送ACK |
在主節點上開啟log_fullsync_replica_acks 可以在mysql執行日誌中記錄每一個收到的ACK,這個功能僅僅用於除錯備機ACK機制,在生產系統中千萬不要開啟否則會嚴重影響效能。
備機有兩種方法傳送ACK給主節點,這兩種方法都要求備機使用mysql客戶端庫連線主節點,這樣每個備節點有兩個連線連到主節點,一個是備機的IO執行緒的連線,另一個是備機傳送ACK的連線。
在此連線中備機傳送kunlun-storage特有的COM_BINLOG_ACK命令或者傳送kunlun-storage可以理解的SQL語句,前者效能更好,但是後者可以讓各種第三方binlog儲存元件向主節點傳送ACK。
-
COM_BINLOG_ACK使用kunlun-storage的客戶端庫檔案及其mysql.h 標頭檔案編譯程式,然後呼叫 mysql_send_binlog_ack() 函式傳送ACK。kunlun-storage fullsync功能使用此方法傳送ACK給其主節點。
-
SLAVE server_id CONSISTENT TO file_index offsetSQL 語句這種方法可以使用任何社群版mysql客戶端庫,kunlun-storage的主節點可以正確處理該語句,把它當作確認ACK。此方法特別適合各種binlog儲存元件。
3. Kunlun-storage Fullsync的狀態變數
這些狀態變數可以幫助DBA觀察fullsync的執行情況和效能,並且作為輔助調節fullsync配置引數的依據。其意義在表格中,都是簡單的英語,相信大家都能看懂,因此不再翻譯了。
|
|
fullsync_received_replica_acks |
NO. of received replica acks |
fullsync_old_acks_received |
NO. of received ACKs that are obsolete,i.e. an obsolete ACK ACKs a position already ACK'ed by previously received ACKs. |
|
NO.of txns the replica ACK'ed |
fullsync_txns_fully_acked_before_wait |
NO. of txns pre-ACK'ed before it starts to wait --- when the txn tries to wait for ack, its receives all needed ACKs from slaves |
fullsync_txns_acked_before_wait |
NO. of txns partly ACK'ed before it starts to wait, when the txn tries to wait for ack, its receives part of all needed ACKs from slaves |
fullsync_txns_long_wait_warnings_for_acks |
NO. of txns long wait warnings for ACKs. although the wait doesn't timeout, it's still long enough to trigger a fullsync warning. |
fullsync_txns_timed_out_waiting_for_acks |
NO. of txns timed out waiting for ACKs |
fullsync_txns_received_by_replica |
NO. of txns received by the replica |
|
|
fullsync_acks_sent_to_master |
NO. of ACKs sent to master |
fullsync_num_txns_in_acked_group |
set by a replica, NO. of txns flushed and fsync'ed corresponding to latest ACK |
fullsync_replica_skipped_old_trx_acks |
NO. of times the replica skipped sending ACKs because received txns are too old |
fullsync_replica_ack_upto_file and fullsync_replica_ack_upto_offset; |
fullsync replicas have ACKed upto this position(file and offset within master's binlog file). |
fullsync_replica_fully_acked_upto_file; and fullsync_replica_fully_acked_upto_offset; |
fullsync replicas have fully ACKed upto this position(file and offset within master's binlog file). |
Kunlun-storageFullsync支援豐富的配置引數讓使用者在效能、資源消耗和一致性方面取得適當的平衡。這些變數都是MySQL的全域性變數,其意義和用法說明見下面的表格,都是簡單的英語,相信大家都能看懂,因此不再翻譯了。
|
|
fullsync_consistency_level |
At end of transaction commit, whether and how to wait for fullsync replica ACKs before replying the client that a transaction has committed. 0:
no wait; 99: wait for simple majority replicas; 100: wait for all replicas; [1, 98]: wait for this number of ACKs. |
fullsync_relaylog_fsync_ack_level |
When fullsync is enabled, how should the replica fsync relay log and/or reply an ACK to primary after it write its received event group(s) to relay log file.\t" "0: don't fsync or send ACK; 1: don't fsync but send ACK; 2: fsync and send ACK |
fullsync_fsync_ack_least_event_bytes |
Accumulate at least this many relay log bytes before fsync'ing the relay log and sending an ACK. |
fullsync_fsync_ack_least_txns |
Accumulate at least this many event groups before fsync'ing the relay log and sending an ACK. |
fullsync_fsync_ack_wait_max_milli_secs |
Replica nodes wait for more event groups to arrive at most this many milli-seconds before fsync'ing the relay log and sending an ACK. |
skip_fullsync_replica_acks_older_than |
If a replica is this many milli-seconds later than the primary node, skip fsync'ing the relay log or sending ACKs. |
|
If a replica ACK arrives this many milli-seconds since the transaction started to wait for it, write a warning in error log. |
|
If a replica ACK doesn't arrive after this many milli-seconds since the transaction started to wait for it, return error to client and write an error in error log. |
log_fullsync_replica_acks |
Whether log replica ACKs to mysqld error log. Note that when fullsync is enabled there can be a huge amount of such logs which are seldom used. |
|
Whether enable fullsync mechanism. |
disable_fullsync_on_slave_ack_timeout |
Whether disable fullsync when replicas do not ACK in time and timeout happened, if this is false, then the primary node can't be written when it has no running replicas. |
Kunlun-storage Fullsync的優勢
與MySQL的半同步(semisync)外掛相比,kunlun-storage 的fullsync機制有如下優勢。
等待備機確認期間,客戶端會話及其事務不佔用工作執行緒。這樣就可以避免大量工作執行緒阻塞等待備機的ACK,導致執行緒池為了處理來自其他客戶端會話的持續大量到來的請求不得不啟動更多的工作執行緒,消耗過多系統資源。
備機會聚集若干個事務的binlog後(可配置),才對relay log做fsync,確保binlog落盤。這樣不僅可以避免備機斷電或者其OS crash或者重啟導致備機丟失了最近的relay log的嚴重問題,還不會對儲存裝置造成巨大的寫入負載。達到了效能,延時和儲存資源消耗之間的完美平衡。
Fullsync有靈活的配置能力,讓使用者在高可用性、資料強一致性和效能之間做出靈活的控制和取捨。
Fullsync提供豐富的執行狀態資訊,方便DBA監控fullsync的執行時狀態,為有效的fullsync相關配置提供完整的資訊
DBA可以配置主節點去等待若干個(可配置)備機返回ACK,從而達到更高的容錯級別。比如對於某些高價值業務,DBA可以配置一主四備,讓主節點為每個事務等待2個備機ACK。
任何一個事務提交操作完成後在返回給客戶端之前,必須等待收到兩個備機的ACK,這個事務提交狀態才能返回給客戶端。
同時,DBA還可以配置一個備機的特定channel是否傳送ACK,即使這個備機的fullsync_relaylog_fsync_ack_level為1或者2,達到靈活配置叢集高可用架構的目標。
推薦閱讀
END
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011764/viewspace-2885969/,如需轉載,請註明出處,否則將追究法律責任。