1. 程式人生 > >深入解讀阿裏雲數據庫POLARDB核心功能會話讀一致性

深入解讀阿裏雲數據庫POLARDB核心功能會話讀一致性

詳細介紹 復制延遲 般的 term 我們 現象 同時 系列 可用

POLARDB架構
我們知道,POLARDB是一個由多個節點構成的數據庫集群,一個主節點,多個讀節點。對外默認提供兩個地址,一個是集群地址,一個是主地址,推薦使用集群地址,因為它具備讀寫分離功能可以把所有節點的資源整合到一起對外提供服務。

技術分享圖片

MySQL讀寫分離解決和引入的問題
用過MySQL的都知道,MySQL的主從復制簡單易用,非常流行,通過把主庫的Binlog異步地傳輸到備庫並實時應用,一方面可以實現高可用,另一方面備庫也可以提供查詢,來減輕對主庫的壓力。

技術分享圖片

雖然備庫可以提供查詢,但存在兩個問題,一是主庫和備庫一般提供兩個不同的訪問地址,應用程序端需要選擇使用哪一個,對應用有侵入。二來MySQL的復制是異步的,即使是半同步也沒辦法做到100%強同步,因此備庫的數據並不是最新的,有延遲,無法保證查詢的一致性。

為了解決第一個問題,我們引入了讀寫分離代理,如下圖,對應用程序非常友好。一般的實現是,代理會偽造成MySQL與應用程序建立好連接,解析發送進來的每一條SQL,如果是UPDATE、DELETE、INSERT、CREATE等寫操作則直接發往主庫,如果是SELECT則發送到備庫。

技術分享圖片

但是第二個問題——延遲導致的查詢不一致——還是沒有解決,使用時,就不可避免地會遇到備庫SELECT查詢數據不一致的現象(因為主備有延遲)。MySQL負載低的時候延遲可以控制在5秒內,但當負載很高時,尤其是對大表做DDL(比如加字段)或者大批量插入的時候,延遲會非常嚴重。

POLARDB讀寫分離的會話讀一致性
POLARDB是讀寫分離的架構,傳統的讀寫分離都只提供最終一致性的保證,主從復制延遲會導致從不同節點查詢到的結果不同,比如一個會話內連續執行以下QUERY:

INSERT INTO t1(id, price) VALUES(111, 96);
UPDATE t1 SET price = 100 WHERE id=111;
SELECT price FROM t1;

在讀寫分離的下,最後一個查詢的結果是不確定的,因為讀會發到只讀庫,在執行SELECT時之前的更新是否同步到了只讀庫時不確定的,因此結果也是不確定的;因為有這個問題,所以就要求應用程序去適應最終一致性,而一般的解決方法是: 將業務做拆分,有高一致性要求的請求直連到主庫,可以接受最終一致性的部分走讀寫分離;顯然這樣會增加應用開發的負擔,還會增大主庫的壓力,影響讀寫分離的效果;

為了解決這個問題,在POLARDB中我們提供了會話一致性或者說因果一致性的保證,會話一致性即保證同一個會話內,後面的請求一定能夠看到此前更新所產生版本的數據或者比這個版本更新的數據,保證單調性,就很好的解決了上面這個例子裏的問題;

實現原理
技術分享圖片

在POLARDB的鏈路中間層做讀寫分離的同時,中間層會track各個節點已經apply了的redolog位點即LSN,同時每次更新時會記錄此次更新的位點為Session LSN, 當有新請求到來時我們會比較Session LSN 和當前各個節點的LSN,僅將請求發往LSN >= Session LSN的節點,從而保證了會話一致性;表面上看該方案可能導致主庫壓力大,但是因為POLARDB是物理復制,上一篇已詳細介紹過,速度極快,在上述場景中,當更新完成後,返回客戶端結果時復制就同步在進行,而當下一個讀請求到來時主從極有可能已經完成,然後大多數應用場景都是讀多寫少,所以經驗證在該機制下即保證了會話一致性,也保證了讀寫分離負載均衡的效果;

相關文章:
雲數據庫POLARDB優勢解讀系列文章之①——10分鐘入門
https://yq.aliyun.com/articles/673623

雲數據庫POLARDB優勢解讀系列文章之②——高性價比
https://yq.aliyun.com/articles/673636

雲數據庫POLARDB優勢解讀系列文章之③——分鐘級彈性
https://yq.aliyun.com/articles/669029

雲數據庫POLARDB優勢解讀系列文章之④——物理復制
https://yq.aliyun.com/articles/674229

雲數據庫POLARDB優勢解讀系列文章之⑤——會話讀一致性
https://yq.aliyun.com/articles/674234

深入解讀阿裏雲數據庫POLARDB核心功能會話讀一致性