傳統關係資料庫高可用的缺失

關係資料庫的事務(transaction)是一組操作序列,比如讀,插入,刪除,更新等等。事務有四個基本要素,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability),即ACID:

  • 原子性:事務的所有修改操作,要麼全部都執行,要麼全部都不執行。在任何情況下,都不能出現一個事務的部分操作執行、部分操作沒有執行的情況,比如一筆從賬戶A到賬戶B的轉賬,如果賬戶A狀態異常或者餘額不足,那麼轉賬壓根就不會發生,如果賬戶A狀態正常且餘額充足,那麼就可以對賬戶A進行扣款,但如果賬戶B狀態異常比如限額超出,那麼轉賬無法進行,賬戶A的扣款必須回滾。任何情況下都不應該出現賬戶A已扣款、賬戶B卻沒有入賬,或者賬戶A沒有扣款、但賬戶B卻已經入賬的情況。
  • 一致性:每一筆事務都把資料庫從一個一致的狀態變成另一個一致的狀態,比如新增一筆交易使得資料庫增加了一條交易記錄,但不論是交易前還是交易後,每一筆交易的「交易號」依然是唯一的。這種一致性也稱為資料庫內部的一致性。出於容災等因素的考慮,資料庫通常採用「主庫+備庫」的方案,一致性也指備庫的數據與主庫的數據的一致性,為了區別,這種一致性也稱為主備一致性。
  • 隔離性:通常情況下,資料庫常常有多個事務同時在執行,這些事務之間可能相互影響,從而產生預期之外的效果:例如賬戶A的餘額是80,事務1擬從A轉50到B,賬戶2擬從A轉70到C,兩個事務同時執行,它們分別檢查賬戶A的餘額的時候都是可以扣款的,但兩筆扣款後,賬戶A的餘額變成了負數,這顯然是不應該的,因此需要對並行執行的事務進行一定的隔離。最高級別的隔離是可串列化(serializable),即一個資料庫上所有並行執行的事務的結果等價於這些事務按某個順序一個一個地串列執行。可串列化的隔離最徹底,但常常對資料庫處理事務的性能產生較大的影響,因此SQL標準還定義了幾種隔離級別,即可重複讀(repeatable read),讀已提交(read committed),讀未提交(read uncommitted),其中讀已提交(read committed)較好地平衡了隔離效果和性能,因此在實際生產系統中普遍使用。此外,快照讀(snapshot isolation)隔離級別的隔離效果略低於可串列化,除了幾種特殊情況外基本等同於可串列化,因為實現簡單、效率高、隔離效果較好而常常採用。
  • 持久性:事務成功提交後,它對於資料庫的影響是永久性的,即使提交後出現了停電或者設備故障等。為了防止斷電導致事務丟失,事務在提交前通常持久化事務日誌(redo log)到硬碟,為了避免硬體故障或損壞導致事務丟失,資料庫系統通常採用「主庫+備庫」(即主備鏡像)來進一步保證持久性。

事務的ACID特徵是關係資料庫區別於其他數據存儲系統的根本點,也是金融、通信、交通、電力、商業等系統採用關係資料庫的根本原因,這使得關係資料庫成為了當今社會十分關鍵的信息基礎設施,因此關係資料庫系統的高可用至關重要。傳統關係資料庫的高可用機制主要是主備鏡像,銀行系統的兩地三中心(主庫+同城熱備庫+異地災備庫)是主備鏡像的一種形式。

主備鏡像的基本原理是:資料庫主庫提供讀寫服務(即執行事務),並同步事務日誌(redo log)到備庫,備庫通過回放日誌來保持與主庫一致,通常情況下備庫不提供服務,但備庫可以升級為主庫,比如主備切換或者主庫因災難無法恢復時升級備庫為主庫等,如下圖:

資料庫主備同步有三種模式:

  • 最大保護模式(max protection):每一筆事務在主庫執行後,事務日誌(redo log)必須同步到備庫才提交事務並應答客戶。這種模式下備庫與主庫是完全同步的,問題是,一旦主備之間的網路異常或是備庫異常,則主庫的寫入(增刪改)操作就會被阻塞,資料庫服務的可用性受到很大的影響,因此實際生產中極少採用。
  • 最高性能模式(max performance):主庫執行完事務後就提交事務並應答客戶,事務日誌(redo log)非同步傳輸到備庫。這種模式下資料庫的性能更好,但備庫數據相比主庫有少量延遲,主庫故障後備庫數據不完整。
  • 最大可用模式(max availability):主庫執行完事務後,事務日誌(redo log)盡量同步到備庫後再提交事務並應答客戶,如果備庫應答超時,則主庫也會提交事務並應答客戶。這種模式下多數情況下備庫與主庫是同步的,但異常情況下(例如網路抖動等)還是會導致備庫與主庫不同步,因此備庫與主庫的一致性無法完全保證。

以上分析發現主備鏡像下資料庫的主備一致性與可用性是衝突的,兩者無法同時保證。本質的原因是傳統關係資料庫軟體假設其所依賴硬體設備(伺服器、存儲等)是相當可靠的,其高可用完全依賴於這些可靠的硬體,資料庫軟體本身在高可用上其實是缺失的。

傳統資料庫軟體本身高可用的缺失導致了以下的缺陷:

  • 傳統資料庫無法做到主庫備庫完全一致:這個已經在前面進行了分析。眾所周知,就像為了消防安全必須經常進行消防演習一樣,銀行等關鍵行業和領域為了應對可能出現的電力、網路、火水、地震等災難也必須經常進行容災演習,但由於資料庫主庫備庫不一致,容災演習時的主備切換對用戶是有損的,需要人工對賬等手段控制因此而導致的資產損失和對用戶的影響,這使得容災演練相當困難和繁瑣。
  • 傳統資料庫系統的成本高昂:資料庫軟體本身高可用的缺使得傳統資料庫完全依賴於資料庫伺服器、存儲及網路等硬體的高可用,特別是存儲和網路,其五個九(即99.999%的年可用率)的高可用是資料庫五個九可用性的基礎和前提,這導致傳統資料庫系統的整體成本居高不下。
  • 分散式OLTP資料庫缺失:99.999%年可用率的硬體幾乎是當今單個硬體可用性的頂峰,然而當100台99.999%年可用率的硬體在一起同時提供服務時,整個系統的可用率大約只有99.9%,這完全無法滿足業務系統的高可用需求。這導致了分散式OLTP資料庫的缺失,並使得高並發的業務不得不使用昂貴的大型伺服器,進一步增加了成本。
  • 傳統資料庫無法水平伸縮:這其實是分散式OLTP資料庫缺失的必然結果。這使得傳統資料庫缺乏彈性,面對秒殺和雙11等場景傳統資料庫擴容後無法縮容,導致資源浪費。

推薦閱讀:

Mysql資料庫主從心得整理
Python採集微博熱評進行情感分析祝你狗年脫單
深入淺出hbase和bigtable
七周成為數據分析師:SQL,從熟練到掌握
為什麼Docker容器不適合資料庫服務(一)

TAG:資料庫 | 分散式系統 |