PolarDB提供了四種一致性層級:最終一致性、會話一致性、全域一致性和全域一致性(高效能模式),滿足您在不同情境下對一致性層級的要求。
問題與解決方案
MySQL的讀寫分離代理功能,代理會偽造成MySQL與應用程式建立好串連,解析發送進來的每一條SQL,如果是UPDATE、DELETE、INSERT、CREATE等寫操作則直接發往主庫,如果是SELECT則發送到備庫,從而實現了讀寫分離。但是當資料庫負載很高時,例如對大表執行DDL(如加欄位)操作或大批量插入資料的時候,延遲會非常嚴重,從而導致無法從唯讀節點中讀取最新資料。MySQL的讀寫分離代理功能無法解決由於延遲導致的查詢不一致問題。
PolarDB採用了非同步物理複製方式實現了主節點和唯讀節點間的資料同步。主節點的資料更新後,相關的更新會應用到唯讀節點,具體的延遲時間與寫入壓力有關(一般在毫秒層級),通過非同步複製的方式確保了主節點和唯讀節點間資料的最終一致。PolarDB提供了如下四種一致性層級,滿足您在不同情境下對一致性層級的要求:
最終一致性
功能介紹
PolarDB是讀寫分離的架構,傳統的讀寫分離只提供最終一致性的保證,主從複寫延遲會導致從不同節點查詢到的結果不同,例如在一個會話內連續執行如下查詢,最後的SELECT結果可能會不同(具體的訪問結果由主從複製的延遲決定)。
INSERT INTO t1(id, price) VALUES(111, 96); UPDATE t1 SET price = 100 WHERE id=111; SELECT price FROM t1;適用情境
若需要減輕主節點壓力,讓盡量多的讀請求路由到唯讀節點,您可以選擇最終一致性。
會話一致性
功能介紹
針對最終一致性導致查詢結果不同的問題,通常需要將業務進行拆分,將一致性要求高的請求直接發往主節點,而可以接受最終一致性的請求則通過讀寫分離發往唯讀節點。這既增加了主節點的壓力,影響讀寫分離的效果,又增加了應用開發的負擔。
為解決上述問題,PolarDB提供了會話一致性(也稱因果一致性)。會話一致性保證了同一個會話內,一定能夠查詢到讀請求執行前已更新的資料,確保了資料單調性。
在PolarDB的鏈路中介層做讀寫分離的同時,中介層會追蹤各個節點已經應用的Redo日誌位點,即日誌序號(Log Sequence Number,簡稱LSN)。同時每次資料更新時PolarDB會記錄此次更新的位點為Session LSN。當有新請求到來時,PolarDB會比較Session LSN和當前各個節點的LSN,如果唯讀節點的LSN不滿足,會根據您配置的逾時時間等待唯讀節點同步到最新資料,僅將請求發往LSN大於或等於Session LSN的節點,從而保證了會話一致性。表面上看該方案可能導致主節點壓力大,但是因為PolarDB是物理複製,速度極快。

在上述情境中,當更新完成後,返回用戶端結果時複製就同步在進行,而當下一個讀請求到來時,主節點和唯讀節點之間的資料複製極有可能已經完成。且大多數應用情境都是讀多寫少,所以經驗證在該機制下既保證了會話一致性,又保證了讀寫分離負載平衡的效果。
適用情境
PolarDB的一致性層級越高,對主庫的壓力越大,叢集效能也越低。推薦使用會話一致性,該層級對效能影響很小而且能滿足絕大多數應用情境的需求。
全域一致性
功能介紹
在部分應用情境中,除了會話內部有邏輯上的因果依賴關係,會話之間也存在依賴關係,例如在使用串連池的情境下,同一個線程的請求有可能通過不同串連發送出去。對資料庫來說這些請求屬於不同會話,但是商務邏輯上這些請求有前後依賴關係,此時會話一致性便無法保證查詢結果的一致性。因此PolarDB提供了全域一致性來解決該問題。

每個讀請求到達PolarDB資料庫代理時,代理都會先去主節點確認當前最新的LSN位點,假設為LSN0(為了減少每次讀請求都去獲得主節點的最新LSN,內部做了批量最佳化), 然後等待至少一個唯讀節點的LSN更新至主節點的LSN0位點後,代理再將讀請求發送至唯讀節點。這樣就能保證該讀請求能夠讀到至請求發起時刻為止,任意一條已完成更新的資料。
全域一致性提供如下兩個配置參數:
參數
說明
ConsistTimeout
全局一致性读超时时间,讀請求等待唯讀節點同步LSN(位點)的最長時間。若超出該時間,PolarDB代理將根據ConsistTimeoutAction參數設定進行對應操作。
取值範圍:0~60000。預設值為20。單位為毫秒。
ConsistTimeoutAction
全局一致性读超时策略,若未能在參數ConsistTimeout設定的時間內將唯讀節點的LSN更新至主節點最新LSN,PolarDB代理將根據ConsistTimeoutAction參數設定進行對應操作。
取值範圍如下:
0(預設):將讀請求發送到主節點。
1:代理返回一個錯誤判文
wait replication complete timeout, please retry給應用端。
說明如何修改全局一致性读超时时间和全局一致性读超时策略,請參見設定資料庫代理。
適用情境
當主從延遲較高時,使用全域一致性可能會導致更多的請求被路由到主節點,造成主節點壓力增大,業務延遲也可能增加。因此建議在讀多寫少的情境下選擇全域一致性。
全域一致性(高效能模式)
PolarDB MySQL版推出了全域一致性(高效能模式)服務。全域一致性(高效能模式)具有比全域一致性更嚴格的強一致性要求。
PolarTrans事務系統利用提交時間戳記技術CTS和RDMA網路,在純核心層面提供RO節點強一致性讀服務,從而保證始終能看到RW和RO節點最新的資料,提供了叢集維度強一致性讀能力,保證發往叢集任意副本的讀請求都可以獲得強一致性的結果。
關於全域一致性(高效能模式)的更多細節(如使用限制、技術原理、開啟方式以及效能資料等),請參見全域一致性(高效能模式)。
如何選擇一致性層級
PolarDB一致性層級越高,叢集效能越低。
推薦使用會話一致性,該層級對效能影響很小而且能滿足絕大多數應用情境的需求。
若對不同會話間的一致性需求較高,可以選擇如下方案之一:
選擇全域一致性(高效能模式)或全域一致性。
說明對於PolarDB MySQL版5.7、8.0.1和8.0.2版本,若追求嚴格強一致性,更推薦全域一致性(高效能模式)。
對於PolarDB MySQL版5.6版本,若追求嚴格強一致性,由於該版本暫不支援全域一致性(高效能模式),可選擇全域一致性。
使用HINT將特定查詢強制發送至主節點執行。
/*FORCE_MASTER*/ select * from user;說明若您需要通過MySQL官方命令列執行上述Hint語句,請在命令列中加上-c參數,否則該Hint會被MySQL官方命令列過濾導致Hint失效,具體請參見MySQL官方命令列。
Hint的路由優先順序最高,不受一致性層級和事務拆分的約束,使用前請進行評估。
Hint語句裡不要有改變環境變數的語句,例如
/*FORCE_SLAVE*/ set names utf8;等,這類語句可能導致後續的業務出錯。
如何設定一致性層級
如何設定為全域一致性(高效能模式),請參見如何開啟全域一致性(高效能模式)。
如何設定為最終一致性、會話一致性和全域一致性,請參見設定資料庫代理。