作者:莫那·魯道
原文:http://thinkinjava.cn/2019/02/yddh/

前言

隨着業務發展越來越快,數據量越來越多,用戶也越來越多,業務出現故障的機率也越來越大,而可用性是衡量一個系統的關鍵指標,application 由於是無狀態的,可用性很好保證,當一個應用掛掉,直接切到另一個即可,最關鍵的是數據庫的高可用,則是最複雜的。

今天我們將嘗試探討數據庫的異地多活高可用。注意,我們討論的都是超大數據量(50TB 級別)的數據庫。

第一種

直接上分佈式數據庫,目前市面上常見的有 3 種,TiDB,阿里雲 POLARDB,亞馬遜 Aurora。

雖然 TiDB 可以將數據 sharding 到各個城市,但由於各個城市的物理距離導致的網絡消耗,查詢的效率可想而知(或許可以通過 Hash 的方式解決?)。 POLARDB 和 Aurora 是相同的思路,計算節點是分佈式的,存儲使用共享存儲,帶來的問題還是單機房問題。

因此,分佈式數據庫解決的還是超大數據的存儲和單機房的 HA,一旦跨越城市,目前還沒有看到好的方案。

第二種

在分庫分表就能無限擴容嗎一文中,我們提到了單元化。單元化說白了,就是先分庫分表,然後,將數據庫劃分爲固定的幾個單元,使固定的業務進入固定的單元,這樣,就不會出現每個業務都需要連接所有的數據庫 —— 從而減小連接數。

在單元化的基礎上,我們可以實現異地多活。

最易懂的數據庫異地多活方案

解釋一下上圖: 我們將 數據分成了 3 個數據庫,同時,我們有3個城市的機房,紅色表示爲寫節點,每個 shard 庫最好只保證只有一個地方寫,儘量避免雙寫的問題。 另外,杭州機房作爲主機房。

上海機房的 shard 1 庫在寫入數據後,會同步到杭州主節點,北京機房的 shard 3 節點在寫入數據後,也會同步到杭州主節點,杭州機房的 shard 2 寫入數據後,也會同步到上海機房和北京機房。

其中,非紅色數據庫都是備庫或讀庫。

我們假設,上海機房斷電。

最易懂的數據庫異地多活方案

此時,杭州機房將會接管 shard 1 庫,變成寫入節點。

我們再假設,杭州機房斷電。

最易懂的數據庫異地多活方案

杭州機房斷電後,上海機房將會接管 shard 2 節點,同時,將 shard 2 節點的數據同步到北京機房,仍然保證可用性。

注意,這裏爲什麼是上海機房的 shard 2 接管,而不是北京機房的 shard 2 接管呢?實際上,我是隨便寫的,在生產環境中,如果有超過 2 個副本,那麼就需要使用 Raft 這種一致性協議來決策到底由誰來接管,這裏爲了簡單,就寫上海了。

我們觀察到,其中,同步是核心,注意,使用 mysql 自帶的同步是不可靠的,通常會自行開發一個穩定的,HA 的高可用複製系統,稱之爲 DRC,即數據複製中心,主要處理多城市或多機房的數據複製。

其中,阿里雲已經有商業版的 DRC ,即 DTS,支持數據同步,數據訂閱,數據遷移。而其底層則是 otter + canal,已經開源,不過比較簡陋,想上生產環境的話,還需要二次開發和優化。

總結

本文簡單的討論了數據庫的異地多活的方案,我們認爲,在單元化的方案中,同步是核心,穩定的同步是保證數據一致的關鍵,而這,在單個機房中,只需要通過簡單的 RPC 即可解決,但在跨機房,跨城市的網絡中,就顯得尤爲複雜。

那麼,如何打造一個高可用,低延遲,可靠的一致性,高吞吐的同步系統呢?

且聽下次分享。


擴展閱讀

Spring Boot實戰:數據庫操作

前端重構方案瞭解一下

Docker 基礎:數據管理

SpringBoot 多模塊項目實踐(附打包方法)

數據庫連接池DBCP的使用

談談實際項目中對 數據庫設計 的一些思考

相关文章