最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

分布式數(shù)據(jù)庫歷史變遷之旅

2023-07-07 13:07 作者:全家桶激活  | 我要投稿

我們正式開始分布式數(shù)據(jù)庫歷史變遷之旅。

單機數(shù)據(jù)庫的不可能三角

正如經(jīng)濟政策的不可能三角“不可能同時實現(xiàn)資本流動自由,貨幣政策的獨立性和匯率的穩(wěn)定”那樣,單機數(shù)據(jù)庫也有一個不可能三角,那就是:①持久化 ②事務隔離 ③高性能。

為什么不可能


  1. 持久化需要每一次寫數(shù)據(jù)都要落到磁盤上,宕機再啟動以后,數(shù)據(jù)庫可以自修復。如果只要求這一條,很好實現(xiàn)。


  2. 事務隔離需要每一次會話(session)的事務都擁有自己的數(shù)據(jù)庫版本:既要多個并行的事務相互之間不會寫到對方的虛擬數(shù)據(jù)庫上(讀提交),又要不能讀到對方的虛擬數(shù)據(jù)庫上(可重復讀),還要在一個事務內(nèi)不能讀到別的事務已經(jīng)提交的新增的數(shù)據(jù)(幻讀),終極需求則是完全串行化:我的讀 session 不結(jié)束,你就不能讀。這個需求和持久化需求結(jié)合以后,會大幅增加日志管理的復雜度,但,還是可以管理的。


  3. 讀寫都要盡量地快:單獨實現(xiàn)也很快,Redis 嘛,但是加上持久化和事務隔離,就很難做了:需要對前兩項進行妥協(xié)。

MySQL 選擇了哪兩個?

MySQL 首先選擇了持久化:失去人性,失去很多,失去持久化,失去一切。沒有持久化能力,那還當個毛的核心數(shù)據(jù)庫,所以這一條是所有磁盤數(shù)據(jù)庫的剛需,完全無法舍棄。

然后 MySQL 選擇了一部分高性能:MyISAM 就是為了快速讀寫而創(chuàng)造的,早期 MySQL 在低配 PC 機上就有不錯的性能。后來更高級的 InnoDB 出現(xiàn)了,小數(shù)據(jù)量時它的讀取性能不如 MyISAM,寫性能更是徹底拉胯,但是在面對大數(shù)據(jù)量場景時,讀性能爆棚,還能提供很多后端程序員夢寐以求的高級功能(例如豐富的索引),承擔了大部分互聯(lián)網(wǎng)核心數(shù)據(jù)庫的角色。

最后,MySQL 將事務隔離拆成了幾個級別,任君挑選:你要強事務隔離,性能就差;你能接受弱事務隔離,性能就強。你說無事務隔離?那你用 MySQL 干什么,Redis 它不香嗎。

所以 MySQL 其實選擇了 持久化_1 + 高性能_0.8 + 事務隔離*0.5,算下來,還賺了 0.3 ( ̄▽ ̄)"

不過,從 MySQL 也可以看出,“數(shù)據(jù)庫的不可能三角”并不是完全互斥的,是可以相互妥協(xié)的。

在開始細數(shù)分布式數(shù)據(jù)庫之前,我們先看一個非分布式的提升數(shù)據(jù)庫性能的方案,讀寫分離,主從同步。

讀寫分離

由于 web 系統(tǒng)中讀寫需求擁有明顯的二八分特征——讀取流量占 80%,寫入流量占 20%,所以如果我們能把讀性能拆分到多臺機器上,在同樣的硬件水平下,數(shù)據(jù)庫總 QPS 也是能提高五倍的。

各種主從架構(gòu)


無論是遠古時代谷歌的 MMM(Multi-Master Replication Manager for MySQL) 還是中古時代的 MySQL 官方的 MGR(MySQL Group Replication),還是最近剛剛完成開發(fā)且收費的官方 InnoDB Cluster,這些主從架構(gòu)的實現(xiàn)方式都是一致的:基于行同步或者語句同步,近實時地從主節(jié)點向從節(jié)點同步新增和修改的數(shù)據(jù)。


由于這種方法必然會讓主從之間存在有一段時間的延遲(數(shù)百毫秒到數(shù)秒),所以一般在主從前面還要加一個網(wǎng)關進行語句分發(fā):


  1. select等讀語句默認發(fā)送到從節(jié)點,以盡量降低主節(jié)點負載


  2. 一旦出現(xiàn)update、insert等些語句,立刻發(fā)送到主節(jié)點


  3. 并且,本次會話(session)內(nèi)的所有后續(xù)語句,必須全部發(fā)送給主節(jié)點,不然就會出現(xiàn)數(shù)據(jù)寫入了但是讀不到的情況


一主四從架構(gòu)圖

搭建一個一主四從的 MySQL 集群,總 QPS 就能從單節(jié)點的 1 萬提升到 5 萬,順便還能擁有主節(jié)點故障后高可用的能力。主從架構(gòu)比較簡單,也沒有什么數(shù)據(jù)沖突問題,就是有一個很大的弱點:

寫入性能無法提升:由于數(shù)據(jù)庫承載的單點功能實在是太多了(自增、時間先后、事務),導致哪怕架構(gòu)玩出了花,能寫入數(shù)據(jù)的節(jié)點還是只能有一個,所有這些架構(gòu)都只能提升讀性能。

那怎么提升寫性能呢?這個時候就要掏出分布式數(shù)據(jù)庫了。

分布式數(shù)據(jù)庫

由于數(shù)據(jù)庫的單點性非常強,所以在谷歌搞出 GFS、MapReduce、Bigtable 三駕馬車之前,業(yè)界對于高性能數(shù)據(jù)庫的主要解決方案是買 IOE 套件:IBM 小型機 + Oracle + EMC 商業(yè)存儲。而當時的需求也確實更加適合商用解決方案。

后來搜索引擎成為了第一代全民網(wǎng)站,而搜索引擎的數(shù)據(jù)庫卻“不那么關系型”,所以谷歌搞出了自己的分布式 KV 數(shù)據(jù)庫。后來谷歌發(fā)現(xiàn) SQL 和事務隔離在很多情況下還是剛需,于是在 KV 層之上改了一個強一致支持事務隔離的 Spanner 分布式數(shù)據(jù)庫。而隨著云計算的興起,分布式數(shù)據(jù)庫已經(jīng)成了云上的“剛需”:業(yè)務系統(tǒng)全部上云,總不能還用 Oracle 物理服務器吧?于是云上數(shù)據(jù)庫又開始大踏步發(fā)展起來。

下面我們按照時間順序,逐一梳理分布式數(shù)據(jù)庫的發(fā)展史。

第一代分布式數(shù)據(jù)庫:中間件

在 MySQL 體系內(nèi)演進

關系型數(shù)據(jù)庫為了解決不可能三角需求,其基本架構(gòu) 40 年沒有變過。

MySQL 自己其實已經(jīng)是一個非常優(yōu)秀的滿足互聯(lián)網(wǎng)業(yè)務場景的單體數(shù)據(jù)庫了,所以基于 MySQL 的基本邏輯進行架構(gòu)改進,是最穩(wěn)妥的方案。

在沒有分布式關系型數(shù)據(jù)庫技術出現(xiàn)的時代,后端開發(fā)者們往往只能選擇唯一的刀耕火種的路:在應用代碼里調(diào)用多個數(shù)據(jù)庫,以應對單個數(shù)據(jù)庫性能不足的困境。后來,有人把這些調(diào)用多個數(shù)據(jù)的代碼抽出來作為單獨的一層,稱作數(shù)據(jù)庫中間件。

數(shù)據(jù)庫中間件


首先,對數(shù)據(jù)表進行縱向分表:按照一定規(guī)則,將一張超多行數(shù)的表分散到多個數(shù)據(jù)庫中。


ShardingSphere 中的 Sharding-Proxy 工作方式

然后,無論是插入、更新還是查詢,都通過一個 proxy 將 SQL 進行重定向和拆分,發(fā)送給多個數(shù)據(jù)庫,再將結(jié)果聚合,返回。

大名鼎鼎的數(shù)據(jù)庫中間件,其基本原理一句話就能描述:使用一個常駐內(nèi)存的進程,假裝自己是個獨立數(shù)據(jù)庫,再提供全局唯一主鍵、跨分片查詢、分布式事務等功能,將背后的多個數(shù)據(jù)庫“包裝”成一個數(shù)據(jù)庫。

雖然“中間件”這個名字聽起來像一個獨立組件,但實際上它依然是強業(yè)務親和性的:沒有幾家公司會自己研發(fā)數(shù)據(jù)庫,但每家公司都會研發(fā)自己的所謂中間件,因為中間件基本上就代表了其背后的一整套“多數(shù)據(jù)庫分庫分表開發(fā)規(guī)范”。所以,中間件也不屬于“通用數(shù)據(jù)庫”范疇,在宏觀架構(gòu)層面,它依然屬于應用的一部分。我稱這個時代為刀耕火種時代。

那該怎么脫離刀耕火種呢?人類的大腦是相似的:既然應用代碼做數(shù)據(jù)規(guī)劃和邏輯判斷很容易失控,那我們在數(shù)據(jù)庫層面把這件事接管了行不行呢?當然可以,但是需要拿東西找信息之神交換

歷史上,第一個被放棄的是事務隔離,而它帶來的就是第二代分布式數(shù)據(jù)庫:KV 數(shù)據(jù)庫。

第二代分布式數(shù)據(jù)庫:KV

分布式時代的“新·不可能三角”

在分布式數(shù)據(jù)庫時代,持久化已經(jīng)不是分布式數(shù)據(jù)庫“真正的持久化”了,取而代之的是“數(shù)據(jù)一致性”:由于數(shù)據(jù)存在了多臺機器上,那機器之間數(shù)據(jù)的一致性就成了新時代的“持久化”。于是新不可能三角出現(xiàn)了:①一致性 ②事務隔離 ③高性能。

你是不是在期待 CAP 理論呀?別著急,我們后面會說。

分布式 KV 數(shù)據(jù)庫放棄了事務隔離

數(shù)據(jù)庫技術一共獲得過四次圖靈獎,后面三次都在關系型數(shù)據(jù)庫領域。事務隔離模型是關系型數(shù)據(jù)庫的核心,非常地簡潔、優(yōu)美、邏輯自恰。

Google 是第一個全民搜索引擎,系統(tǒng)規(guī)模也達到了史上最大。但是,搜索引擎技術本身卻不需要使用關系型數(shù)據(jù)庫來存儲:搜索結(jié)果中的網(wǎng)頁鏈接之間是離散的。這塊我要挖個坑,本系列完結(jié)以后,我會寫一篇如何自己開發(fā)搜索引擎的文章。

由于搜索不需要關系型數(shù)據(jù)庫,自然谷歌搞的分布式數(shù)據(jù)庫就是 KV 模型。谷歌的三駕馬車論文發(fā)布以后,業(yè)界迅速發(fā)展出了一個新的數(shù)據(jù)庫門類 NoSQL(Not Only SQL),專門針對非結(jié)構(gòu)化和半結(jié)構(gòu)化的海量數(shù)據(jù)。

目前,緩存(Redis)和文檔/日志(MongoDB)大家一般都會用 NoSQL 來承載。在這個領域,最成功的莫過于基于 Hadoop 生態(tài)中 HDFS 構(gòu)建的 HBase 了:它主要提供的是行級數(shù)據(jù)一致性,即 CAP 理論中的 CP,放棄了事務,可以高性能地存儲海量數(shù)據(jù)。

KV 數(shù)據(jù)庫結(jié)構(gòu)簡單,性能優(yōu)異,擴展性無敵,但是它只能作為核心數(shù)據(jù)庫的高性能補充,絕大多數(shù)場景下,核心數(shù)據(jù)庫還是得用關系型。

第三代分布式數(shù)據(jù)庫:以 Spanner 為代表的 NewSQL

從 2005 年開始,Google Adwords 開始基于 MySQL 搭建系統(tǒng),這也推動了 MySQL 在 Google 內(nèi)部的大規(guī)模使用。隨著業(yè)務的發(fā)展,MySQL 集群越來越龐大,其中最痛苦的就是“數(shù)據(jù)再分片”,據(jù)說有一次谷歌對數(shù)據(jù)庫的重新分片持續(xù)了 2 年才完成。于是谷歌痛定思痛,搞出了一個支持分布式事務和數(shù)據(jù)強一致性的分布式關系型數(shù)據(jù)庫:Google Spanner。

2012 年,谷歌發(fā)布了 Spanner 論文1,拉開了分布式強一致性關系型數(shù)據(jù)庫的大幕。這個數(shù)據(jù)庫是真的牛逼,當我第一次看到它機柜照片的時候直接震驚了:


這套系統(tǒng)采用了 GPS 授時 + 2 臺原子鐘 + 4 臺時間服務器,讓分布在全球多個數(shù)據(jù)中心的 Spanner 集群進行相當精確的時間同步:基于 TrueTime 服務,時間差可以控制在 10ms 之內(nèi)。這種真正的全球數(shù)據(jù)庫可以做到即使單個數(shù)據(jù)中心完全失效,應用也完全無感知。

當然,如此規(guī)模的全球數(shù)據(jù)庫全世界也沒有幾家公司有需求,如果我們只在一個數(shù)據(jù)中心內(nèi)署數(shù)據(jù)庫集群,時間同步可以很容易地做到 1ms 之內(nèi),原子鐘這種高端貨還用不到。

還記得上篇文章中數(shù)據(jù)持久性的關鍵步驟——redo log 嗎?

為什么上篇文章要寫一萬多字,就是為本文打基礎的,現(xiàn)在就用到了。

上文中我們說過,寫入型 SQL 會在寫入緩存頁 + 寫入磁盤 redo log 之后返回成功,此時,真正的 ibd 磁盤文件并未更新。所以,Spanner 使用 Paxos 協(xié)議在多個副本之間同步 redo log,只要 redo log 沒問題,多副本數(shù)據(jù)的最終一致性就沒有問題。

事務的兩階段提交

由于分布式場景下寫請求需要所有節(jié)點都完成才算完成,所以兩階段提交是必須存在的。單機架構(gòu)下的事務,也是某一旦一條 SQL 執(zhí)行出錯,整個事務都是要回滾的嘛。多機架構(gòu)下這個需求所需要的成本又大幅增加了,兩階段提交的流程是這樣的:


  1. 告訴所有節(jié)點更新數(shù)據(jù)


  2. 收集所有節(jié)點的執(zhí)行結(jié)果,如果有一臺返回了失敗,則再通知所有節(jié)點,取消執(zhí)行該事務

這個簡單模型擁有非??植赖睦碚摴收细怕剩阂坏┰诘谝徊綀?zhí)行成功后某臺機器宕機,則集群直接卡死:大量節(jié)點會被鎖住。

Spanner 使用 Paxos 化解了這個問題:只要 leader 節(jié)點的事務執(zhí)行成功了,即向客戶端返回成功,而后續(xù)數(shù)據(jù)的一致性則會基于prepare timestampcommit timestamp加上 Paxos 算法來保證。

多版本并發(fā)控制(MVCC)

Spanner 使用時間戳來進行事務之間的 MVCC:為每一次數(shù)據(jù)的變化分配一個全球統(tǒng)一的時間戳。這么做的本質(zhì)依然是“空間+時間”換時間,而且是拿過去的時間換現(xiàn)在的時間,特別像支持事后對焦的光場相機。


  1. 傳統(tǒng)的單機 MVCC 是基于單機的原子性實現(xiàn)的事務順序,再實現(xiàn)的事務隔離,屬于即時判斷。


  2. Spanner 基于 TrueTime 記錄下了每行數(shù)據(jù)的更新時間,增加了每次寫入的時間成本,同時也增加了存儲空間。


  3. 在進行多節(jié)點事務同步時,就不需要再和擁有此行數(shù)據(jù)的所有節(jié)點進行網(wǎng)絡通信,只依靠 TrueTime 就可以用 Paxos 算法直接進行數(shù)據(jù)合并:基于時間戳判斷誰前誰后,屬于事后判斷。

Spanner 放棄了什么

Spanner 是一個強一致的全球數(shù)據(jù)庫,那他放棄了什么呢?這個時候就需要 CAP 理論登場了。

一個分布式系統(tǒng)最多只能同時滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯性(Partition tolerance)這三項中的兩項。

Google Spanner 數(shù)據(jù)庫首先要保證的其實是分區(qū)容錯性,這是“全球數(shù)據(jù)庫”的基本要求,也最影響他們賺錢;然后是一致性,“強一致”是核心設計目標,也是 Spanner 的核心價值;谷歌放棄的是可用性(A),只有 majority available。

除此之外,為了“外部一致性”,即客戶端看到的全局強一致性,谷歌為每一個事務增加了 2 倍的時鐘延遲,換句話說就是增加了寫操作的返回時間,這就是分布式系統(tǒng)的代價:目前平均 TrueTime 的延遲為 3.5ms,所以對 Spanner 的每一次寫操作都需要增加 7ms 的等待時間。

Spanner 一致性的根本來源

大家應該都發(fā)現(xiàn)了,其實 Spanner 是通過給 Paxos 分布式共識算法加了一個“本地外掛” TrueTime 實現(xiàn)的海量數(shù)據(jù)的分布式管理,它實現(xiàn)全局強一致性的根本來源是PaxosTrueTime。而在普通單機房部署的分布式系統(tǒng)中,不需要 GPS 授時和原子鐘,直接搞一個時間同步服務就行。

NewSQL 時代

Google Spanner 的推出代表著一個新時代到來了:基于分布式技術的 SQL 兼容數(shù)據(jù)庫(NewSQL),而兼容到什么地步就看各家的水平了。

NewSQL 最大的特點就是使用非 B 樹磁盤存儲結(jié)構(gòu)(一般為 LSM-Tree),在上面構(gòu)筑一個兼容 SQL 常用語句和事務的兼容層,這樣既可以享受大規(guī)模 LSM-Tree 集群帶來的擴展性和高性能,也可以盡量少改動現(xiàn)有應用代碼和開發(fā)習慣,把悲傷留給自己了屬于是。

目前比較常見的 NewSQL 有 ClustrixDB、NuoDB、VoltDB,國內(nèi)的 TiDB 和 OceanBase 也屬于 NewSQL,但他們倆有本質(zhì)區(qū)別,我們下面會詳細討論。

在 NewSQL 時代之后,隨著云計算的興起,云上數(shù)據(jù)庫突然成為了市場的寵兒,市場占有率迅速上漲。它們其實都是對 MySQL 的改造,并不屬于 NewSQL 范疇,下面我們認識一下他們。

第四代分布式數(shù)據(jù)庫:云上數(shù)據(jù)庫

我實在是不想用“云原生”這個風口浪尖上的詞來形容美麗的云上數(shù)據(jù)庫們,它們就像 TCP/IP,簡潔但有用。市場從來不會說謊,它們一定是有過人之處的。

亞馬遜 Aurora 開天辟地

2014 年 10 月,亞馬遜發(fā)布了 Aurora 云上數(shù)據(jù)庫,開創(chuàng)性地在云環(huán)境中將計算節(jié)點和存儲節(jié)點分離:基于云上資源的特點,將計算節(jié)點 scale up(增配),將存儲節(jié)點 scale out(增加節(jié)點),實現(xiàn)了極佳的性能/成本平衡。Aurora 將云上關系型數(shù)據(jù)庫產(chǎn)品推向了一個新的高度。

計算與存儲分離

Aurora 提出的計算與存儲分離可以說是目前數(shù)據(jù)庫領域最火的方向,但是它火的原因我相信大多數(shù)人都認識的不對:不是因為性能強,而是因為便宜。

挖掘云計算的價值點

十年前我在 SAE 實習的時候,中午大家一起吃飯,組長說云計算就是云安全,這句話當然說的很對。從這句話推開,我們很容易就能找到云計算真正的商業(yè)價值在哪里:傳統(tǒng)托管式部署,哪些資源浪費的最多,哪里就是云計算的商業(yè)價值所在。

為了滿足業(yè)務波動而多采購的 CPU 和內(nèi)存,可能浪費了 50%;網(wǎng)絡安全設備,可以說 95% 以上的資源都是浪費;高端存儲,這個已經(jīng)不能用資源浪費來形容了,而是被云計算顛覆了:云廠商用海量的多地域多機房內(nèi)廉價的 x86 服務器里面的廉價磁盤,基于軟件,構(gòu)建出了超級便宜、多副本、高可用的存儲,唯一的問題是性能不是太好。亞馬遜 S3 和阿里云 OSS 就是最佳代表,可以說這類對象存儲服務,其單價已經(jīng)低于本地機房的 2.5 寸 SAS 機械磁盤了,更不要說本地機房還需要另外采購昂貴的存儲控制器和 SAN 交換機了。

云計算與特斯拉

云數(shù)據(jù)庫可以算是云服務廠商最重要的產(chǎn)品:受眾足夠廣,成本足夠低,性能足夠高。這一點很像特斯拉汽車,時至今日,特斯拉依然在瘋狂地想各種辦法壓低生產(chǎn)成本,雖然在降價,但是單車毛利依然維持在 30% 以上,是 BBA 的 2-3 倍。

Aurora 和 PolarDB 的核心價值是用一種低成本的方式,制造了一個 Oracle 要高成本才能做出來的軟件和服務,這才是真的“創(chuàng)造價值”。

計算與存儲分離是一種“低成本”技術

計算與存儲分離并不是什么“高性能”技術,而是一種“低成本”技術:關系型數(shù)據(jù)的存儲引擎 InnoDB 本身就是面向低性能的磁盤而設計的,而 CPU 和內(nèi)存卻是越快越好、越大越好,如果還把磁盤和 MySQL 進程部署在同一臺物理機內(nèi),一定會造成磁盤性能的浪費。計算與存儲分離的真正價值在于大幅降低了存儲的成本。

計算與存儲分離的技術優(yōu)勢

雖然說這個架構(gòu)的主要價值在于便宜,但是在技術上,它也是有優(yōu)勢的:

它顯著降低了傳統(tǒng) MySQL 主從同步的延遲。傳統(tǒng)架構(gòu)下,無論是語句同步還是行同步,都要等到事務提交后,才能開始同步,這就必然帶來很長時間的延遲,影響應用代碼的編寫。而計算和存儲分離之后,基于 redo log 傳遞的主從同步就要快得多了,從 1-2s 降低到了 100ms 以下。由于主從延遲降低,集群中從節(jié)點的個數(shù)可以提升,總體性能可以達到更高。

Aurora 的主從同步機制

看了上篇文章的人應該都知道,在更新數(shù)據(jù)時,主節(jié)點在完成了 redo log 寫入,并對內(nèi)存緩存 Buffer Pool 中相應的數(shù)據(jù)頁進行修改之后,就會返回成功。這個內(nèi)存緩存給 Aurora 從節(jié)點的數(shù)據(jù)更新造成了不小的影響:


  1. 主從節(jié)點之間只有 redo log 傳遞


  2. 從節(jié)點在拿到 redo log 之后,會刷新自己 Buffer Pool 中存在的數(shù)據(jù)頁,其它不存在的頁的信息會丟棄


  3. 這帶來了兩個問題:


    1. 從節(jié)點的客戶端在主從不同步的一段時間內(nèi),讀到的是舊數(shù)據(jù),這個需要網(wǎng)關或者應用代碼來處理


    2. 從節(jié)點的 Buffer Pool 有效性變差,命中率下降,引發(fā)性能下降


Aurora 的架構(gòu)局限

Aurora 的出現(xiàn)確實獨具慧眼,但是也會被時代所局限。

在 Aurora 論文2中,開篇就提到Instead, the bottleneck moves to the network between the database tier requesting I/Os and the storage tier that performs these I/Os。Aurora 認為網(wǎng)絡速度會成為云數(shù)據(jù)庫的瓶頸,而在它研發(fā)的 2012-2013 年也確實如此,當時萬兆網(wǎng)卡剛剛普及,CPU 單核性能也不足,軟件也沒有跟上,可以說速度比千兆網(wǎng)卡也快不了多少,所以亞馬遜又搞了神奇的技術:存儲節(jié)點具有自己將 redo log 寫入 ibd 文件的能力。

由于這個神奇能力的存在,Aurora 的多機之間采用傳輸 redo log 的方式來同步數(shù)據(jù),并用一種今天看起來不太靠譜的協(xié)議來保證最終一致性:consul 使用的那個 gossip 協(xié)議。由于 Aurora 采用六副本技術,所以每次寫入都需要發(fā)起六次不怎么快的網(wǎng)絡 IO,并且在其中 4 個成功以后才給客戶端返回成功。Aurora 確實便宜,但是單節(jié)點的性能也確實捉雞,這代表的就是寫入性能差,進而限制了整個集群的性能上限。而且,經(jīng)過比較長的時間(100ms)才能保證從從節(jié)點上讀到的數(shù)據(jù)是最新的,這會讓主節(jié)點壓力增大影響集群性能上限,或者讓應用代碼做長時間的等待,嚴重的會引起應用代碼的執(zhí)行邏輯變更,引入持久的技術債務。

那該怎么提升計算存儲分離情況下的集群性能呢?我們看阿里云是怎么做的。

阿里云 PolarDB 后來居上

阿里云 RDS 集群的成本已經(jīng)夠低了,不需要再用計算存儲分離技術降低成本了,而中國市場的用戶,普遍需要高性能的 MySQL 數(shù)據(jù)庫:ECS 價格太低了,如果不是運維方便和性能壓力過大,誰愿意用你昂貴的數(shù)據(jù)庫服務啊。

2015 年,PolarDB 開始研發(fā),當時 25Gb RDMA 網(wǎng)絡已經(jīng)逐漸普及,所以阿里云將視角放在了網(wǎng)絡速度之外:在 IO 速度沒有瓶頸以后,基于內(nèi)核提供的 syscall 所編寫的舊代碼將會成為新的性能瓶頸。

站在 2023 年初回頭看,阿里云的判斷是非常準確的。

計算存儲分離架構(gòu)下的整體性能極限

由于所有節(jié)點都使用了同一塊“邏輯磁盤”,所以雙主可寫想都不要想,一個計算存儲分離的數(shù)據(jù)庫集群的性能上限就是主節(jié)點的寫入性能上限。(Aurora 有多主可寫數(shù)據(jù)庫,對 ID 進行自動切分,使用時有一堆限制;PolarDB 也有多主可寫數(shù)據(jù)庫,但是更絕:每個庫/表只支持綁定到一個可寫節(jié)點,感情就是對多個數(shù)據(jù)庫做了個邏輯聚合,還不如中間件呢。)

在主節(jié)點不接受讀的情況下,主節(jié)點只承接寫入操作,以及和寫入操作在同一個會話 session 中的后續(xù)的讀請求。

那 PolarDB 是如何提升主節(jié)點性能的呢?

1. 共享的不是 redo log,而是 ibd 文件

主從之間并不是依靠純屬 redo log 來同步數(shù)據(jù)的,而是直接共享同一個 ibd 文件,即真正的共享磁盤。而且,基于塊設備的 Raft 算法也比基于文件的 gossip 協(xié)議要快很多。

2. 繞過內(nèi)核和網(wǎng)路棧:大幅提升存儲性能,降低延遲,減少 CPU 消耗

雖然對 redo log 的解析這一步在 Aurora 那邊是存儲做的,PolarDB 這邊是主節(jié)點做的,看似增加了 CPU 消耗,但是這并不是真正的性能瓶頸所在,真正的瓶頸是網(wǎng)絡棧和 UNIX 進程模型??催^我《性能之殤》系列文章的人應該都比較熟悉了,這是老生常談了。那 PolarDB 是怎么優(yōu)化的呢?


  1. 跳過 TCP/IP 網(wǎng)絡棧,直接使用 RDMA 網(wǎng)絡從存儲節(jié)點讀取數(shù)據(jù),延遲暴降


  2. 跳過 kernel 的線程調(diào)度,自行開發(fā)綁定 CPU 核心的狀態(tài)機,采用非阻塞 IO,在 CPU 占用下降的情況下,延遲進一步降低

3. 提出 ParallelRaft 協(xié)議,允許部分亂序提交

ParallelRaft 協(xié)議讓 Aurora 那邊需要執(zhí)行六次的網(wǎng)絡 IO 變成了一次:只需要向 leader 節(jié)點寫入成功,剩下的數(shù)據(jù)同步由 Raft 算法來執(zhí)行,這和 Google Spanner 的兩階段提交優(yōu)化是一個思路。

原始的 Raft 協(xié)議確實邏輯完備,實現(xiàn)簡單,就是一個一個地協(xié)商太慢了。ParallelRaft 讓收斂協(xié)商能夠并行起來,加速 redo log 落入 ibd 文件的過程。

4. 主從之間基于低延遲的共享存儲同步 redo log 數(shù)據(jù)以刷新 Buffer Pool

基于共享存儲的低延遲優(yōu)勢,PolarDB 主從之間使用共享存儲來同步 redo log 以刷新緩存,這一點邏輯上和 Aurora 一致,但是實際表現(xiàn)比較好,我實測主從同步時間在 20~70ms 范圍內(nèi)。

5. 單機性能比標準 MySQL 更強

RDMA 存儲比本地存儲更快,因為減少了計算和存儲爭搶中斷的問題:IO 這個 CPU 不擅長的東西完全卸載給了 RDMA 網(wǎng)卡。同配置下 PolarDB 比標準 MySQL 的性能要高幾倍。

PolarDB 有這么多的優(yōu)勢,那它付出了什么代價呢?

在各種實測里面,PolarDB 在相同規(guī)格下對其他的云上數(shù)據(jù)庫都擁有 2 倍的性能優(yōu)勢,但是它基于 RDMA 存儲的特點也讓它付出了兩個代價:1. 硬件成本高昂 2. 擴展性有上限。

是不是感覺很熟悉?Shared-Disk 的代表 Oracle RAC 也有這兩個缺點。不知道大家有沒有發(fā)現(xiàn),PolarDB 就是云時代的 RAC 數(shù)據(jù)庫:看起來是 Shared-Disk,其實是共享緩存讓他們的性能變的超強。


各代分布式數(shù)據(jù)庫的兼容性/擴展性對比

一句話概括 PolarDB:利用了高性能云存儲并且做了性能優(yōu)化的一主多從 MySQL 集群。

簡單討論一下 CAP 理論

一個分布式系統(tǒng)中,不可能完全滿足①一致性、②可用性、③分區(qū)容錯性。我們以一個兩地三中心的數(shù)據(jù)庫為例:


  1. 一致性:同一個時刻發(fā)送到三個機房的同一個讀請求返回的數(shù)據(jù)必須一致(強一致讀),而且磁盤上的數(shù)據(jù)也必須在一段時間后變的完全邏輯一致(最終一致)


  2. 可用性:一定比例的機器宕機,其它未宕機服務器必須能夠響應客戶端的請求(必須是正確格式的成功或失?。?,這個比例的大小就是可用性級別


  3. 分區(qū)容錯性:一個集群由于通信故障分裂成兩個集群后,不能變成兩個數(shù)據(jù)不一致的集群(腦裂),對外必須依然表現(xiàn)為一個邏輯集群

在一個分布式數(shù)據(jù)庫系統(tǒng)中,到底什么是可以放棄的呢?我覺得可以從分布式系統(tǒng)帶來了什么優(yōu)勢這個問題開始思考。

相比于單體系統(tǒng),一個分布式的數(shù)據(jù)庫,在一致性上進步了嗎?完全沒有。在可用性上進步了嗎?進步了很多。在分區(qū)容錯性上呢?單體系統(tǒng)沒有分區(qū),不需要容錯。所以,結(jié)論已經(jīng)一目了然了:

①和③都是分布式系統(tǒng)帶來的新問題,只有②是進步,那就取長補短,選擇犧牲可用性來解決自己引發(fā)的一致性和分區(qū)容錯性兩個新問題。這也正是目前常見分布式數(shù)據(jù)庫系統(tǒng)的標準做法。

TiDB 和 OceanBase 該怎么選?

TiDB 和 OceanBase 是目前中國 NewSQL 數(shù)據(jù)庫的絕代雙驕,爭論一直不絕于耳。

TiDB 是承襲 Spanner 思想的 NewSQL,對 MySQL 的兼容性一般,基于key+版本號的事務控制也比較弱,據(jù)說性能比較好,特別是寫入性能。

OceanBase 是基于 Shared-Nothing 思想原生開發(fā)的分區(qū)存儲數(shù)據(jù)庫,其每個節(jié)點都支持完整的 SQL 查詢,相互之間無需頻繁通信。OceanBase 還支持多租戶隔離,這明顯就是為了云服務準備的(無論是公有云還是私有云),和絕大多數(shù)企業(yè)無關。另外,OceanBase 對于 MySQL 的兼容性也幾乎是 NewSQL 里面最高的,畢竟它需要支持支付寶的真實業(yè)務,兼容性是硬性要求,業(yè)務屎山可沒人移得動 (づ??????)づ

下面我們詳細對比一下兩者的設計思路。

TiDB 的設計思路

我畫的架構(gòu)圖如下:


上圖中的“SQL 層”就是解析 SQL 語句并將其轉(zhuǎn)化為 KV 命令的一層,是無狀態(tài)的,下面的存儲層才是核心,它叫 TiKV。

TiKV 如何存儲數(shù)據(jù)

TiKV 官方原理圖如下:


TiKV 是 TiDB 的核心組件,一致性和事務隔離都是基于它的能力得以實現(xiàn)的。每個 TiKV 擁有兩個獨立的 RocksDB 實例,一個用于存儲 Raft Log,另一個用于存儲用戶數(shù)據(jù)和多版本隔離數(shù)據(jù)(基于key+版本號實現(xiàn)),從這里可以看出,TiDB 的存儲存在大量冗余,所以 TiDB 的測試性能才會如此的高,符合空間換時間的基本原理。

和 TiKV 并列的還有一個 TiFlash 列存儲引擎,是為了 OLAP 在線數(shù)據(jù)分析用的,我們在此不做詳細討論。


TiKV 數(shù)據(jù)分片

除此之外,TiKV 還發(fā)明了一層虛擬的“分片”(Region),將數(shù)據(jù)切分成 96MB~144MB 的多個分片,并且用 Raft 算法將其分散到多個節(jié)點上存儲。注意,在 TiKV 內(nèi)部存儲用戶數(shù)據(jù)的那個 RocksDB 內(nèi)部,多個分片是致密存儲的,分片之間并沒有邏輯關系。

TiDB 的實現(xiàn)風格比較狂野,所以不兼容的部分比較多:


TiDB 和 MySQL 不兼容的部分

TiDB 對 CAP 和不可能三角的抉擇

TiDB 放棄了新不可能三角中的事務隔離,和 Spanner 一樣放棄了 CAP 理論中的“完全可用性”:一旦出現(xiàn)腦裂,就會出現(xiàn)意外的返回結(jié)果(如超時),因為 TiDB 選擇了保證一致性:如果無法達到數(shù)據(jù)強一致,就要停止服務。

一句話概括 TiDB:①搭建在 KV 數(shù)據(jù)庫集群之上的②兼容部分 MySQL 語法的③有一些事務處理能力的高性能數(shù)據(jù)庫。

OceanBase 設計思路

我們以最新的 OceanBase 4.0 版本的架構(gòu)為目標進行討論。

TiDB 底層數(shù)據(jù)叫分片,那 OceanBase 為什么叫分區(qū)呢?因為分片的意思只是數(shù)據(jù)被分開了(本身 KV 數(shù)據(jù)之間也沒關系),但分區(qū)表示的是分區(qū)內(nèi)部的數(shù)據(jù)之間是有聯(lián)系的:OceanBase 的每個節(jié)點本身,依然是一個關系型數(shù)據(jù)庫,擁有自己的 SQL 引擎、存儲引擎和事務引擎。

簡單的分區(qū)

OceanBase 在建表時就需要設定數(shù)據(jù)分區(qū)規(guī)則,之后每一行數(shù)據(jù)都屬于且僅屬于某個分區(qū)。在數(shù)據(jù)插入和查詢的時候,需要找到這一行數(shù)據(jù)所在的區(qū),進行針對性地路由。這和第一代分布式——中間件的思想一致。這么做相當于簡單地并行執(zhí)行多條 SQL,以數(shù)據(jù)切分和數(shù)據(jù)聚合為代價,讓數(shù)據(jù)庫并行起來。而這個數(shù)據(jù)切分和數(shù)據(jù)聚合的代價,可以很小,也可以很大,需要 OceanBase 進行精細的性能優(yōu)化,我們下面還會說到。

分區(qū)之間,通過 Multi-Paxos 協(xié)議來同步數(shù)據(jù):每一個邏輯分區(qū)都會有多個副本分布在多臺機器上,只有其中一個副本會成為 leader,并接受寫請求。這里的架構(gòu)和 PolarDB 一樣了,此時,客戶端的一致性讀需要網(wǎng)關(OBProxy)來判斷,主從之間的同步是有可感知的延遲的。

節(jié)點存儲架構(gòu)


官方存儲架構(gòu)圖

OceanBase 數(shù)據(jù)庫的存儲引擎基于 LSM Tree 架構(gòu),將數(shù)據(jù)分為靜態(tài)基線數(shù)據(jù)(放在 SSTable 中)和動態(tài)增量數(shù)據(jù)(放在 MemTable 中)兩部分,其中 SSTable 是只讀的,一旦生成就不再被修改,存儲于磁盤;MemTable 支持讀寫,存儲于內(nèi)存。數(shù)據(jù)庫 DML 操作插入、更新、刪除等首先寫入 MemTable,等到 MemTable 達到一定大小時轉(zhuǎn)儲到磁盤成為 SSTable。在進行查詢時,需要分別對 SSTable 和 MemTable 進行查詢,并將查詢結(jié)果進行歸并,返回給 SQL 層歸并后的查詢結(jié)果。同時在內(nèi)存實現(xiàn)了 Block Cache 和 Row cache,來避免對基線數(shù)據(jù)的隨機讀。

當內(nèi)存的增量數(shù)據(jù)達到一定規(guī)模的時候,會觸發(fā)增量數(shù)據(jù)和基線數(shù)據(jù)的合并,把增量數(shù)據(jù)落盤。同時每天晚上的空閑時刻,系統(tǒng)也會自動每日合并。

OceanBase 數(shù)據(jù)庫本質(zhì)上是一個基線加增量的存儲引擎,在保持 LSM-Tree 架構(gòu)優(yōu)點的同時也借鑒了部分傳統(tǒng)關系數(shù)據(jù)庫存儲引擎的優(yōu)點。

以上是官方描述,我本來想簡化一下,讀了一遍覺得還是放原文吧,原文描述的就非常的清晰精煉了:OceanBase 用內(nèi)存 B+ 樹和磁盤 LSM-Tree 共同構(gòu)成了數(shù)據(jù)讀寫體系,和上一篇文章中的 InnoDB 是多么像啊!只是 OceanBase 做的更細:跟 TiDB 相比,就像是在 TiKV 上面加了一層 Buffer Pool 一樣。

還有一個細節(jié):OceanBase 除了記錄日志(Redo Log)并修改內(nèi)存緩存(MemTable)之外,只要內(nèi)存充足,白天 OceanBase 不會主動將內(nèi)存緩存中的數(shù)據(jù)刷洗到 SSTable 里的,官方更推薦每天凌晨定時刷洗。這是什么思想?可以說是空間(內(nèi)存)換時間,也可以說是拿未來的時間換現(xiàn)在的時間。

OceanBase 性能來源之一——充分的內(nèi)存緩存

從基礎電氣屬性上講,磁盤一定是慢的,內(nèi)存一定是快的,所以在數(shù)據(jù)量大于機器的內(nèi)存容量時,各種數(shù)據(jù)庫的性能差別可以聚焦到一個點上:內(nèi)存利用效率,即熱數(shù)據(jù)命中內(nèi)存緩存的概率。

為了提升緩存命中率,OceanBase 設計了很多層內(nèi)存緩存,盡全力避免了對磁盤的隨機讀取,只讓 LSM-Tree 的磁盤承擔它擅長的連續(xù)讀任務,包子有肉不在褶上,商用環(huán)境中捶打過的軟件就是不一樣,功夫都在細節(jié)里:



  1. BloomFilter Cache:布隆過濾器緩存


  2. MemTable:同時使用 B+ 樹和 HashTable 作為內(nèi)存引擎,分別處理不同的場景


  3. Row Cache:存儲 Get/MultiGet 查詢的結(jié)果


  4. Block Index Cache:當需要訪問某個宏塊的微塊時,提前裝載這個宏塊的微塊索引


  5. Block Cache:像 Buffer Pool 一樣緩存數(shù)據(jù)塊(InnoDB 頁)


  6. Fuse Row Cache:在 LSM-Tree 架構(gòu)中, 同一行的修改可能存在于不同的 SSTable 中,在查詢時需要對各個 SSTable 查詢的結(jié)果進行熔合,對于熔合結(jié)果緩存可以更大幅度地支持熱點行查詢


  7. Partition Location Cache:用于緩存 Partition 的位置信息,幫助對一個查詢進行路由


  8. Schema Cache:緩存數(shù)據(jù)表的元信息,用于執(zhí)行計劃的生成以及后續(xù)的查詢


  9. Clog Cache:緩存 clog 數(shù)據(jù),用于加速某些情況下 Paxos 日志的拉取

OceanBase 性能來源之二——直接變身內(nèi)存數(shù)據(jù)庫

為了極致的性能,OceanBase 直接取消了 MySQL 中“后臺進程每秒將 redo log 刷寫到 ibd 文件”這一步,等于放大了集群宕機重啟后恢復數(shù)據(jù)的時間(重啟后需要大量的時間和磁盤 IO 將 redo log 刷寫入磁盤),然后把這件事放到半夜去做:

當內(nèi)存的增量數(shù)據(jù)達到一定規(guī)模的時候,會觸發(fā)增量數(shù)據(jù)和基線數(shù)據(jù)的合并,把增量數(shù)據(jù)落盤。同時每天晚上的空閑時刻,系統(tǒng)也會自動每日合并。

把一整天的新增和修改的數(shù)據(jù)全部放到內(nèi)存里,相當于直接變身成了內(nèi)存數(shù)據(jù)庫(還會用 B 樹和 Hashtable 存兩份),確實是一種終極的性能優(yōu)化手段,OceanBase 真有你的。

填坑:OceanBase 如何提升并行查詢和數(shù)據(jù)聚合的性能

傳統(tǒng)的中間件 Sharding 技術中,也會做一些并行查詢,但是他們做的都是純客戶端的查詢:proxy 作為標準客戶端,分別從多臺機器拿到數(shù)據(jù)之后,用自己的內(nèi)存進行數(shù)據(jù)處理,這個邏輯非常清晰,但有兩個問題:1. 只能做簡單的并行和聚合,復雜的做不了 2. 后端數(shù)據(jù)庫相互之間無通信,沒有很好地利用資源,總響應時間很長。

OceanBase 讓一切盡可能地并行起來了:在某臺機器上的 proxy(OBServer) 接到請求以后,它會擔任協(xié)調(diào)者的角色,將任務并行地分發(fā)到多個其他的 OBServer 上執(zhí)行;同時,將多個子計劃劃分到各個節(jié)點上以后,會在各節(jié)點之間建立 M*N 個網(wǎng)絡通信 channel,并行地傳輸信息;此外,OceanBase 還對傳統(tǒng)數(shù)據(jù)庫的執(zhí)行計劃優(yōu)化做了詳細的拆分,對特定的關鍵詞一個一個地做分布式優(yōu)化,才最終達成了地表最強的成就。

由于本身就是為了兼容 MySQL 而設計的一種新技術實現(xiàn),所以它擁有非常優(yōu)秀的兼容性:


OceanBase 和 MySQL 不兼容的部分

OceanBase 對 CAP 和不可能三角的抉擇

由于數(shù)據(jù)是分區(qū)的,所以當腦裂時,兩個大腦的數(shù)據(jù)肯定已經(jīng)不完整了,相當于兩萬行的表只剩一萬行數(shù)據(jù)可以進行查詢和更新,此時,如果 OceanBase 梗著脖子非要追求數(shù)據(jù)強一致,也是可以讓所有的 OBProxy 拒絕服務的,但是 OceanBase 選擇了繼續(xù)茍著:互聯(lián)網(wǎng)公司嘛,能實現(xiàn)最終一致性就行了,要啥自行車。

OceanBase 放棄了 CAP 和新不可能三角中的一致性,只能做到最終一致性:為了事務隔離和性能,哥忍了。

其實,不追求強一致和我們下一篇《站在地球表面》中的終極高并發(fā)架構(gòu)在思想上是一致的,我想這就是經(jīng)歷過大規(guī)模生產(chǎn)應用的數(shù)據(jù)庫,被現(xiàn)實世界毒打過后的痕跡吧。

一句話概括 OceanBase:①世界第一性能的②高度兼容 MySQL 的③經(jīng)歷過生產(chǎn)系統(tǒng)考驗的高性能分布式關系型數(shù)據(jù)庫。

分布式數(shù)據(jù)庫,應該怎么選?

其實,分布式數(shù)據(jù)庫根本就輪不到你來選:應用準備好了嗎?有足夠的研發(fā)資源嗎?性能問題已經(jīng)大到壓倒其他需求了嗎?

如果你有一個正在成長的業(yè)務,影響最小、成本最低的方案就是選擇 Aurora/PolarDB 這種高兼容性數(shù)據(jù)庫,等到這類云數(shù)據(jù)庫的主節(jié)點達到性能上限了,再對應用做逐步改造,滾動式地替換每個部分的數(shù)據(jù)庫依賴。

如果壓力大到必須換分布式數(shù)據(jù)庫技術方案了,再看看你能獲得什么樣的分布式數(shù)據(jù)庫呢?無非是在哪個云平臺就用哪家唄。

番外篇

Shared-Nothing、Shared-Memory 和 Shared-Disk

Shared-Nothing 只是一種思想,并不是一種明確的數(shù)據(jù)庫架構(gòu),它非?;\統(tǒng),只是描述了一種狀態(tài)。在這里我們簡單討論一下 Shared-Nothing。

Shared-Nothing 描述的是一種分布式數(shù)據(jù)庫的運行狀態(tài):兩臺物理機,除了網(wǎng)絡通信之外,不進行任何資源共享,CPU、內(nèi)存、磁盤都是獨立的。這樣,整個系統(tǒng)的理論性能就可以達到單機的二倍。

怎么理解 Shared-Nothing 思想呢?把它和 Shared-Disk 放到一起就明白了:

Shared-Disk:多臺機器通過共享 SAN 磁盤的方式協(xié)同工作,讓系統(tǒng)整體性能突破單機的極限。Oracle RAC 是這個架構(gòu)的佼佼者,不過它的成功并不在于磁盤,而在于它的分布式鎖(CACHE FUSION):RAC 利用時間戳和分布式鎖實現(xiàn)了分布式事務和多臺機器同時可寫,大幅提升了集群的性能。注意,時間戳在這里又出現(xiàn)了。CACHE FUSION 其實已經(jīng)可以被稱作 Shared-Memory 了。感興趣的可以自己了解,我們不再深入。

21 世紀初,Oracle 推出了 Shared-Disk 的 RAC,IBM 推出了 Shared-Nothing 的 DB2 ICE。十年后,Oracle RAC 發(fā)展的如火如荼,而 DB2 ICE 已經(jīng)消失在了歷史的長河中。

但是,2012 年 Google 發(fā)布了 Spanner 論文,在非常成熟的世界上最大規(guī)模的 KV 數(shù)據(jù)庫之上,構(gòu)建 SQL 層,實現(xiàn)持久化、事務和多版本并發(fā)控制,扛起了 Shared-Nothing 技術方向的大旗,直到今天。

MongoDB 小故事

十年前我在新浪云(SAE)實習的時候,聽過一個關于 MongoDB 的技術小故事:當時,SAE 的 KV 服務是使用 MongoDB 實現(xiàn)的,在規(guī)模大到一定程度以后,性能會突然下降,SAE 自己解決不了這個問題,就給 MongoDB 開發(fā)組的各位大哥買機票請他們到北京理想國際大廈 17 層現(xiàn)場來幫忙,研究了幾天,MongoDB 開發(fā)組的人說:你們換技術吧,MongoDB 解決不了你們這個規(guī)模的問題,然后 SAE 的 KV 就更換技術方案來實現(xiàn)了。

DBA 暈倒砸爛花盆

也是在 SAE,我坐在廁所附近臨過道的工位(上廁所很方便),某天早上剛上班,我親眼看到 SAE 的一名 MySQL DBA 從廁所里出來后,暈倒在我面前,砸爛了一個大花盆。數(shù)據(jù)庫作為系統(tǒng)架構(gòu)中最重要的那個單點的殘酷,可見一斑。

列存儲思想

與其將列存儲認定為數(shù)據(jù)庫的一種,我倒覺得它更應該被稱作一種思想:觀察數(shù)據(jù)到底是被如何讀取,并加以針對性地優(yōu)化。

列存儲有點像第一性原理在數(shù)據(jù)庫領域的應用:不被現(xiàn)實世界所束縛,沒有屈服于 B 樹和它親戚們的淫威,勇敢地向更底層看去,思考著在我們大量讀取數(shù)據(jù)時,數(shù)據(jù)怎樣組織才能讀的更快。

在讀取一行數(shù)據(jù)時,顯然 B+ 樹的效率無人能及,但是當我們需要讀取 100 萬行數(shù)據(jù)中的某一列時,B+ 樹就需要把這 100 萬行數(shù)據(jù)全部載入內(nèi)存:每次將一頁 16KB 載入內(nèi)存,循環(huán)這一頁內(nèi)的 14 行數(shù)據(jù),把這個特定的字段復制出來;重復執(zhí)行這個操作 71429 次,才能得到我們想要的結(jié)果。這顯然是 B+ 樹非常不擅長的需求。

而列存儲將數(shù)據(jù)基于行的排布翻轉(zhuǎn)過來了:所有數(shù)據(jù)基于列,致密地排列在磁盤上,這樣對某一列的讀取就變成了磁盤順序讀,即便是機械磁盤,順序讀也非???。

列存儲數(shù)據(jù)庫 clickhouse 頗有毛子暴力美學的典范,和 Nginx 的氣質(zhì)很像

clickhouse 推薦使用盡量多的 CPU 核心,對單核性能無要求,我拿 E5-V2 舊服務器測過,速度確實非常驚人,8000 萬行的表,查詢起來不僅比 MySQL 快,比 Hadoop 也快特別多。

還記得我們的目標嗎?五百萬數(shù)據(jù)庫 QPS

在中國,我們現(xiàn)在有下面兩種方案可以選擇:


  1. OceanBase 已經(jīng)蟬聯(lián) TPC-C 數(shù)年的全球冠軍了,每分鐘可以處理 7.07 億個訂單,每秒訂單數(shù)都已經(jīng)過千萬了,更不要說 QPS 500 萬了,所以,如果你用 OceanBase,你的百萬 QPS 的高并發(fā)系統(tǒng)已經(jīng)搭建完成了! :-D


  2. 如果你用阿里云,那 1 主 4 從,88 vCore 710 GB * 5 個節(jié)點的 PolarDB 集群可以跑到大約 200 萬 QPS3。那離 500 萬還有不小的距離呢,不要著急,我們下篇文章解決這個問題。

接下來

接下來就是本系列最后一篇文章了:我們不僅要用架構(gòu)頂住五百萬數(shù)據(jù)庫 QPS,還會找出一個哲學♂辦法,打造能夠服務全人類的系統(tǒng)。

參考資料


  1. Google Spanner 論文(中文版) https://ying-zhang.github.io/time/2013-Spanner-cn.pdf


  2. 亞馬遜 Aurora 論文 https://web.stanford.edu/class/cs245/readings/aurora.pdf


  3. 復盤:我在真實場景下對幾款主流云原生數(shù)據(jù)庫進行極限性能壓測的一次總結(jié) https://cloud.tencent.com/developer/article/2066823


分布式數(shù)據(jù)庫歷史變遷之旅的評論 (共 條)

分享到微博請遵守國家法律
彭阳县| 山丹县| 舟山市| 介休市| 塘沽区| 桐梓县| 新乡县| 筠连县| 汝南县| 丰台区| 永平县| 沅陵县| 图们市| 宝丰县| 会东县| 大安市| 玛纳斯县| 布拖县| 泊头市| 沅江市| 砀山县| 嘉禾县| 都江堰市| 香河县| 贺州市| 黄浦区| 喀什市| 平潭县| 鄂尔多斯市| 车险| 玉环县| 吴堡县| 五大连池市| 竹溪县| 腾冲县| 饶平县| 富川| 韶关市| 河南省| 桓台县| 常州市|