雲時代資料庫的核心特點

qiuyesuifeng發表於2016-10-11

引言

最近幾年,隨著雲端計算相關技術的發展,各種不同型別的雲層出不窮,服務越來越多不同型別的企業業務,傳統企業也漸漸開始探索上雲的道路。在雲上,作為業務最核心的資料庫,相比之前的傳統方案會有哪些變化呢?在正式聊雲時代的資料庫特點之前,我們需要了解一下目前雲時代架構發生的變化。

暢想一下,未來的服務都跑在雲端,任何的服務資源都可以像水電煤一樣按需選購。從 IaaS 層的容器/虛擬機器,到 PaaS 層的資料庫,快取和計算單元,再到 SaaS 層的不同型別的應用,我們只需要根據自身業務特點進行資源選配,再也不用擔心應用服務支撐不住高速的業務增長,因為在雲上一切都是彈性伸縮的。有了可靠的基礎軟體架構,我們就可以把更多精力放到新業務的探索,新模式的創新,就有可能產生更多不一樣的新場景,從而催生更強大能力的雲端服務,這是一件多麼 cool 的事情。

當然,理想要一步一步實現,未來的基礎軟體棧到底會怎樣呢?社群在這方面正在進行積極地探索,其中最有代表性的就是基於容器(以 Docker 為代表)的虛擬化技術和微服務(Microservice)。

在雲時代,一切都應該是可伸縮的,使用 k8s(Kubernetes)在保證資源平衡的前提下,通過 Docker 部署我們依託於容器的微服務模組,我們不用關心服務到底跑在哪裡,只需要關心我們需要多少服務資源。Docker 提供了極大的便利性,一次構建,到處執行,我們可以很好地解決開發、測試和上線的環境一致性問題。(如果不能很好地保證測試和實際上線環境的一致性,則很有可能需要花費遠超過開發的時間去發現和修復問題。)k8s 更是在 Docker 構建的基礎上增加了更多的雲特性,包括 Docker 的升級,高可用和彈性伸縮等等。 關於 Docker/k8s 相關的討論已經很多了,因為時間關係,關於具體的細節就不再展開。我們只需要瞭解,有了它,可以很輕鬆地解決服務的安裝和部署。

下面再聊聊微服務,微服務將一個服務拆分成相對獨立的更小的子服務單元,不同的子服務單元之間通過統一的介面(HTTP/RPC 等)進行資料互動。

相比於傳統的解決方案,這種架構有很多的優點。

  • 更好的開發效率和可維護性。微服務將一個單獨的服務進行更細力度的拆分,每一個子服務單元專注於更小的功能模組,可以更好地根據業務建立對應的資料模型,降低複雜度,使得開發變得更輕鬆,維護和部署變得更加友好.
  • 更好的可擴充套件性。每個不同的子服務單元相互獨立,彼此之間沒有任何依賴,所以可以根據業務的具體需要,靈活地部署多個子服務單元進行水平擴充套件。
  • 更強的容錯性。當其中一個子服務出現故障的時候,可以通過輔助的負載均衡工具,自動路由到其他的子服務,不會影響整體服務的可用性.

當然,微服務也不是一個銀彈,相對來說,這種方案會使整體系統的設計更加複雜,同時也加大了網路的延遲,對整個系統測試的複雜度也會更高。

Docker 提供的隔離型和可移植性,與微服務是一種天然的契合,微服務將整個軟體進行拆分和解耦,而通過 Docker/k8s 可以很自然地做到獨立的部署,高可用和容錯性,似乎一切都可以完美地運轉起來。但是真的是這樣麼?我們是不是忽略了什麼?

是的,我們在討論前面的問題的時候忽略了一個很重要的東西:狀態。

從整個技術發展的角度來看,微服務是一個非常有意義的探索。每個人都期望著每個微服務的子服務都是無狀態的,這樣我可以自由地啟停和伸縮,沒有任何的心智負擔,但是現實的業務情況是什麼樣的呢?比如一個電商網站,使用者正在下單購買一件商品,此時平臺是通過訂單子服務的 A 應用來提供服務的,突然,因為機器故障,訂單子服務的 A 應用不可用了,改由訂單子服務的 B 應用提供服務,那麼它是必須要知道剛才使用者的訂單資訊的,否則正在訪問自己訂單頁面的使用者會發現自己的訂單資訊突然不見了。雖然我們儘量想把子服務設計成無狀態的,但是很多時候狀態都是不可避免的,我們不得不通過儲存層儲存狀態,業界最主要的還是各種資料庫,包括 RDBMS 和 NoSQL,比如使用 MySQL、MongoDB、HBase、Cassandra 等,特別是有些場景還要考慮資料一致性問題的時候,更加重了對儲存層的依賴。

由此可見,雲端計算時代系統的架構發生了巨大的變化,這一方面為使用者提供了更優秀的特性,另一方面也對雲端計算的元件提出了更高的要求。資料庫作為雲端計算最基礎的元件之一,也需要適應這種架構的變化。(這裡我們主要關注 SQL 資料庫,雲時代的資料庫以下簡稱雲資料庫。)

那麼雲資料庫主要有一些什麼樣的特點呢?我認為主要有以下幾點。

彈性伸縮

傳統的資料庫方案,常見的會選用 Oracle,MySQL,PostgreSQL。在雲時代,資料量的規模有爆發性的增長,傳統的資料庫很容易遇到單機的儲存瓶頸,不得不選用一些叢集方案,常見的比如 Oracle RAC、 MySQL Sharding 等,而這些叢集方案或多或少都有一些不令人滿意的地方。

比如說,Oracle RAC 通過共享儲存的硬體方案解決叢集問題,這種方式基本上只能通過停機換用更大的共享記憶體硬體來解決擴容問題,RAC 節點過多會帶來更多的併發問題,同樣也會帶來更高的成本。

以 MySQL Sharding 為代表的資料分片方案,很多時候不得不提前對資料量進行規劃,把擴容作為很重要的一個計劃來做,從 DBA 到運維到測試到開發人員,很早之前就要做相關的準備工作,真正擴容的時候,為了保證資料安全,經常會選擇停服務來保證沒有新的資料寫入,新的分片資料同步後還要做資料的一致性校驗。當然業界大公司有足夠雄厚的技術實力,可以採用更復雜的方案,將擴容停機時間儘量縮短(但是很難縮減到 0),但是對於大部分中小網際網路公司和傳統企業,依然無法避免較長時間的停服務。

在雲時代,理想中所有的資源都是根據使用者業務需求按需分配的,伺服器資源,應用容器資源,當然也包括資料庫資源。新增或者減少新的資料庫資源,完全就像日常吃飯那樣稀疏平常,甚至使用者基本感知不到。比如作為一個電商使用者,在雙 11 促銷活動之前,可以通過增加資料庫節點的方式,擴大更多的資源池,用來部署相應的容器服務,當活動結束之後,再將多餘的資源移除去支援其他的服務,這樣可以極大地提高資源的利用率,同樣可以彈性地支撐各種峰值業務。

高可用

傳統的 MySQL 方案,資料複製的時候預設採用非同步的方式,對於一個寫入的請求,主庫寫入成功後就會返回成功資訊給客戶端,但是這個時候資料可能還沒有同步給從庫,一旦主庫這個時候掛掉了,啟動從庫的時候就會有丟失資料的風險。當然,也有人會選擇半同步的複製方式,這種方式在正常情況下是同步的,但是在遇到資料壓力比較大的時候,依然會退化為非同步的方式,所以本質上來說,同樣有丟失資料的風險。其他也有一些多主的同步方案,比如在應用層做資料同步,但是這種方式一是需要應用層的配合,二是在對網路超時的處理非常複雜,增加心智負擔。

在雲時代,因為所有的資料庫資源都是分散式儲存的,每個資料庫節點出現問題都是很正常的事情,所以就必須有一種可以實現資料一致性的資料複製方式來保證服務的高可用,業界給出的答案就是:Paxos/Raft(關於 Paxos 和 Raft 的實現細節我們不在這裡展開)。PingCAP 在做的 TiDB 就是選擇了 Raft 協議,Raft 協議看起來更像是一個多副本的自適應的主從複製協議,對於每次寫請求,Raft 都會保證大多數寫成功才會返回客戶端,即使 Raft Group 的 Leader 掛掉了,在一個有限的時間範圍內,會很快地選出一個新的 Leader 出來,繼續提供服務。同樣,對於一個 3 副本的 Raft Group,只要 2 個寫入成功,就可以保證成功,而大多數情況下,最先寫入成功的往往是與 Leader 網路情況最好的那個副本,所以這種 Majority 寫的方式,可以很自然地選擇速度最快的副本進行資料同步複製。另外,Raft 協議本身支援 Config Change,增加一個新的節點,可以很容易地做副本資料分佈的變更,而不需要停止任何服務。

同樣,在雲時代,資料庫的 DDL 操作也會是一個非常有趣的事情。以一個常見的 Add Column 操作為例,在表規模已經很大的情況下,在傳統的實現方案中,比較有參考意義的是,通過一些工具,建立類似表級別的觸發器,將原表的資料同步到一個新的臨時表中,當資料追平的時候,再進行一個鎖表操作,將臨時表命名為原表,這樣一個 Add Column 操作就完成了。但是在雲時代,分散式的資料儲存方式決定了這種方案很難實現,因為每個資料庫節點很難保證 Schema 狀態變更的一致性,而且當資料規模增長到幾十億,幾百億甚至更多的時候,很短的阻塞時間都有可能會導致很大的負載壓力變化,所以 DDL 操作必須是保證無阻塞的線上操作。值得欣慰的是,Google 的 F1 給我們提供了很好的實現參考,TiDB 即是根據 F1 的啟發進行的研發,感興趣的同學可以看下相關的內容。

易用透明
我們可以將雲資料庫想象成一個提供無限大容量的資料庫,傳統資料庫遇到單機資料儲存瓶頸的問題將不復存在。已有的程式基本上不怎麼需要修改已有的程式碼,就可以很自然地接入到雲資料庫中來獲得無限 Scale 的能力。增減資料庫節點,或者節點的故障恢復,對於應用層來說完全透明。另外,雲資料庫的監控、運維、部署、備份等等操作都可以在雲端通過高效的自動化工具來自動完成,極大地降低了運維成本。

多租戶
雲資料庫本身應該是可以彈性伸縮的,所以很自然的,從資源利用率的角度來考慮,多個不同使用者的資料庫服務底層會跑在一個共享的雲資料庫中。因此多租戶技術會成為雲資料庫的標配。但是這裡面就有一個不得不面對的問題,如何做到不同使用者的隔離性?使用者資料隔離是相對比較容易的,比如還是以電商使用者(這裡說的是電商企業,不是顧客客戶)為例,每個使用者都有一個唯一的 ID,這樣在雲資料庫的底層儲存中,可以保證每個使用者資料都帶有自己 ID 字首,使用者登陸進來的時候可以根據這個字首規則,獲取他對應的資料,同時他看不到其他使用者的資料。

在一個真實的多租戶環境下面,純粹的資料隔離往往是不夠的,你還需要做到資源公平性的隔離。比如有的使用者寫一個 SQL,這個 SQL 沒有做優化,主要做的事情是一個全表描掃,這個表的資料量特別特別大,這樣他會吃掉很多的 CPU、Memory、IO 等資源,導致其他使用者很輕量級的 SQL 操作都可能會變得很慢,影響到其他使用者實際的體驗。那麼針對這種情況怎麼做隔離?與此類似的還有,網路頻寬怎麼做隔離?大家都是跑在一個雲資料庫上面的,如果一個使用者存放的資料特別大,他把頻寬都吃掉了,別人就顯得非常慢了。

還有一種情況,如果我本身作為一個租戶,內部又怎麼做隔離,大家知道 MySQL 可以建很多 Database,不同的 Database 給不同的團隊來用,那麼他們之間內部隔離又怎麼做,這個問題就進一步更加複雜了。

目前來講沒有特別好的方法,在一個分散式的環境下面去做很好的隔離,有兩個方向可以考慮:

第一種是最簡單也是有效的方法,制定一些規則,把某些使用者特別大的資料庫表遷移到獨享的伺服器節點上面,這樣就不會影響其他使用者的服務,但是這裡面就涉及到定製化的事情了,本身理念其實與雲資料庫並不相符。

第二種就是依靠統計資訊,做資源隔離和排程,但是這裡面對技術的要求就比較高了。因為雲資料庫是分散式的,所以一般的統計都要橫跨很多的機器,因為網路原因,不可能做到完全準確的統計,所有統計都是有延遲的。比如說對於某個使用者,現在統計到的流量是 1 個 G,他可能突然就有一次峰值的網路訪問,可能下一次統計消耗的流量是 5 個 G(這裡面只是舉例說明問題),如果你給他流量限制是 1 個 G,中間統計的間隔是多少比較合適,如果間隔比較小,那麼這個對整個系統的壓力就比較大,可能影響正常的使用者 SQL 訪問,另外本身這個流量限制的系統也是很複雜的系統。

排程演算法一直是整個分散式系統領域很困難的一個問題,如何做到隔離性和公平排程也是未來雲資料庫非常有挑戰的一個事情。

低成本
低成本應該是雲時代基礎設施最明顯的特點。首先,雲資料庫的高可用和容錯能力,使得我們不再需要昂貴的硬體裝置,只需要普通的 X86 伺服器就可以提供服務。然後,受益於 Docker 的虛擬化技術,使得不同型別的應用容器可以跑在同一個物理機上,這樣可以極大地提高資源的利用率。其次,多租戶的支援,使得不同的使用者可以共用一套底層的資料庫儲存系統,在資料庫層面再一次提高了資源的利用效率。再次,雲資料庫的自動化運維工具,降低了整個核心資料庫的運維成本。最後,雲資料庫資源是按需分配的,使用者完全可以根據自身的業務特點,選購合適的服務資源。

高吞吐

雲資料庫雖然可以做到彈性擴容,但是本身是分散式儲存的,雖然可以通過 Batch Write、Pipeline 和 Router Cache 等方式加快訪問 SQL 請求的資料,但是相對傳統單機的資料庫來說,在資料訪問鏈路上至少也要多走一次網路,所以大部分併發量不大的小資料量請求,都會比單機延遲要高一些。也就是說,當沒有足夠高的併發 SQL 訪問的話,其實不能完全體現雲資料庫的效能優勢,所以這也是我們在選用雲資料庫的時候需要認識到的問題,雲資料庫更多的是追求高吞吐,而不是低延遲。當併發大到一定規模,雲資料庫高吞吐特性就顯現出來了,即使在很高的併發下,依然可以維持相當穩定的延遲,而不會像單機資料庫那樣,延遲線性增長。當然,延遲的問題,在合理的架構設計方案下,可以通過快取的方式得到極大的緩解。

資料安全
雲資料庫的物理伺服器分佈在多個機房,這就為跨資料庫中心的資料安全提供了最基礎的硬體支援。談到金融業務,大家耳熟能詳的可能就是兩地三中心,比如北京有兩個機房,上海有一個。未來一切服務都跑在雲上,金融類的業務當然也不例外。相比其他業務,金融類業務對資料安全要求就要高得多。當然,每個公司內部都有核心的業務,所以如果上雲的話,也會有同樣的強烈需要。這樣,對雲資料庫來說,資料的一致性、分散式事務、跨資料中心的資料安全等更高階的需求有可能會日益強烈。常見的資料備份也有可能會被其他新的模式所取代或者弱化,比如基於 Paxos/Raft 的多副本方案,本身就保證了會有多份備份。

自動負載平衡
對於雲資料庫來說,負載平衡是一個很重要的問題,它直接決定了整個雲資料庫系統效能的好壞,如果一個資料庫節點的資料訪問過熱的話,就需要考慮把資料遷移到其他的資料庫節點來分擔負載,不然就很容易出現效能瓶頸。整個負載平衡是一個動態的過程,排程演算法需要保證資源配比的最大平衡,還有保證資料遷移的過程對系統整體的負載影響最小。這在未來也是雲資料庫需要解決的一個核心問題。

小結
從目前已有的 SQL 資料庫實現方案來看,NewSQL 應該是最貼近於雲資料庫理念的實現。NewSQL 本身具有 SQL、ACID 和 Scale 的能力,天然就具備了雲資料庫的一些特點。但是,從 NewSQL 到雲資料庫,依然有很多需要挑戰的難題,比如多租戶、效能等。

上面提到的一些雲資料庫的特點,也是 PingCAP 目前在著力實現的部分,TiDB 作為國內第一個 NewSQL 的開源專案,在與社群的共同努力下,我們在上月底剛剛釋出了 Beta 版本,歡迎各位上 GitHub 瞭解我們。

隨著整個社群技術水平的發展和雲時代新的業務需求的驅動,除了 PingCAP 的 TiDB,相信會有更多的團隊在這方面進行探索, 期待早日看到雲資料庫成熟的那一天。

Q&A
問:由於客戶資料環境複雜多樣,在遷移到雲端的時候怎麼怎麼做規劃,以便後期統一運維管理?或者說,怎麼把使用者 SQL Server 或者 MongoDB 逐漸遷移到 TiDB 之類的分散式資料庫?
崔秋:因為每個業務場景都不太相同,所以在選用雲端服務的時候,首先要了解自身業務和雲服務具體的優缺點。 如果你的業務本身比較簡單,比如你之前用的 MongoDB,現在很多雲服務廠商都會提供雲端的 MongoDB 服務。這個時候你就要根據業務特點來做判斷,如果 MongoDB 本身容量不大,遠期的業務資料不會增長過快的話,這個時候其實你可以直接使用 MongoDB 的服務的。但是如果你本身的資料量比較大,或者資料增長比較快的話,就可能要考慮資料的擴容問題,MongoDB 在這方面做的不是太好。 你可以考慮 SQL 資料庫的叢集方案。比如 TiDB,它本身是支援彈性擴容,高併發高吞吐和跨資料庫中心資料安全的,另外有一點明顯的好處是 TiDB 相容 MySQL 協議,所以如果你的應用程式是使用 MySQL,就基本上可以無縫地遷移到 TiDB,這方面是非常方便的。後續我們會提供常用的資料庫遷移工具,幫使用者把資料從 MongoDB/SQL Server 等平滑遷移到 TiDB 上面。 還是那個原則,不要為了上雲而上雲,一定要了解清楚自己的業務特點,雲資料庫會幫助你提供很多特性,如果真的很適用你的業務的話,就可以考慮。

問:但從產品的角度來看,雲廠商提供的 RDS 產品是 Copy 客戶資料庫的思路,或者說是為了支援不同的資料庫而支援。請問這種局面以後會有什麼改變嗎?
崔秋:現在確實蠻多雲資料庫服務其實就是在傳統的 RDS 上面包了一層自動化的監控,運維和部署工具,就賣給使用者提供服務了,但是實際上本身解決的僅僅是自動化管控的問題,雲服務提供的資料庫特性還是單機的 RDS,或者 RDS Sharing 的特性。如果本身底層的資料庫滿足不了你的需求的話,雲服務也是滿足不了的。 如果你需要不停服務的彈性擴容,單機的 RDS 服務肯定是搞不定的,RDS Sharing 也很難幫助你做到,這就對底層的資料庫有了更高的要求,當然這方面是 TiDB 的強項了。 現在很多雲上的 RDS 產品還遠遠沒有達到理想中的雲資料庫的要求,不過隨著社群的發展和業務需求的推動,我個人覺得,這方面最近幾年會有更多的變化。如果對於這方面感興趣的話,可以關注下 TiDB。

問:從 Oracle 分流資料到 TiDB、Oracle 增量修改、Update 的記錄,如何同步到 TiDB?有沒有工具推薦,比如類似 Ogg?

崔秋:目前 TiDB 還沒有相應的工具。如果真的需要線上從 Oracle 這邊分流的話,可以考慮使用 Oracle 的觸發器,將資料的變化記錄下來,然後轉化為 SQL,同步到 TiDB,當然這需要一定開發的工作量。

原文連結

更多原創文章乾貨分享,請關注公眾號
  • 雲時代資料庫的核心特點
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章