OceanBase架构浅析(一)
http://www.cnblogs.com/LiJianBlog/p/4779934.html
簡(jiǎn)介
OceanBase是阿里集團(tuán)研發(fā)的可擴(kuò)展的關(guān)系數(shù)據(jù)庫,實(shí)現(xiàn)了數(shù)千億條記錄、數(shù)百TB數(shù)據(jù)上的跨行跨表事務(wù),截止到2012年8月,支持了收藏夾、直通車報(bào)表、天貓?jiān)u價(jià)等OLTP和OLAP在線業(yè)務(wù),線上數(shù)據(jù)量已經(jīng)超過一千億條。
從模塊劃分的角度看,OceanBase可以劃分為四個(gè)模塊:主控服務(wù)器RootServer、更新服務(wù)器UpdateServer、基線數(shù)據(jù)服務(wù)器ChunkServer以及合并服務(wù)器MergeServer。OceanBase系統(tǒng)內(nèi)部按照時(shí)間線將數(shù)據(jù)劃分為基線數(shù)據(jù)和增量數(shù)據(jù),基線數(shù)據(jù)是只讀的,所有的修改更新到增量數(shù)據(jù)中,系統(tǒng)內(nèi)部通過合并操作定期將增量數(shù)據(jù)融合到基線數(shù)據(jù)中。
背景分析
淘寶收藏夾是淘寶線上應(yīng)用之一,淘寶用戶在其中保存自己感興趣的寶貝(即商品,此外用戶也可以收藏感興趣的店鋪)以便下次快速訪問、對(duì)比和購買等,用戶可以展示和編輯(添加/刪除)自己的收藏。淘寶收藏夾數(shù)據(jù)庫包含了收藏info表(一條一條的收藏信息)和收藏item表(被收藏的寶貝和店鋪)等:
●收藏info表保存收藏信息條目,數(shù)百億條。
●收藏item表保存收藏的寶貝和店鋪的詳細(xì)信息,數(shù)十億條。
●熱門寶貝可能被多達(dá)數(shù)十萬買家收藏。
●每個(gè)用戶可以收藏千個(gè)寶貝。
●寶貝的價(jià)格、收藏人氣等信息隨時(shí)變化。
?
如果用戶選擇按寶貝價(jià)格排序后展示,那么數(shù)據(jù)庫需要從收藏item表中讀取收藏的寶貝的價(jià)格等最新信息,然后進(jìn)行排序處理。如果用戶的收藏條目比較多(例如4000條),那么查詢對(duì)應(yīng)的item的時(shí)間會(huì)較長(zhǎng):假設(shè)如果平均每條item查詢時(shí)間是5ms,則4000條的查詢時(shí)間可能達(dá)到20s,如果真如此,則用戶體驗(yàn)會(huì)很差。
如果把收藏的寶貝的詳細(xì)信息實(shí)時(shí)冗余到收藏info表,則上述查詢收藏item表的操作就不再需要了。但是,由于許多熱門商品可能有幾千到幾十萬人收藏,這些熱門商品的價(jià)格等信息的變動(dòng)可能導(dǎo)致收藏info表的大量修改,并壓垮數(shù)據(jù)庫。
設(shè)計(jì)思路
OceanBase的目標(biāo)是支持?jǐn)?shù)百TB的數(shù)據(jù)量以及數(shù)十萬TPS、數(shù)百萬QPS的訪問量,無論是數(shù)據(jù)量還是訪問量,即使采用非常昂貴的小型機(jī)甚至是大型機(jī),單臺(tái)關(guān)系數(shù)據(jù)庫系統(tǒng)都無法承受。
一種常見的做法是根據(jù)業(yè)務(wù)特點(diǎn)對(duì)數(shù)據(jù)庫進(jìn)行水平拆分,通常的做法是根據(jù)某個(gè)業(yè)務(wù)字段(通常取用戶編號(hào),user_id)哈希后取模,根據(jù)取模的結(jié)果將數(shù)據(jù)分布到不同的數(shù)據(jù)庫服務(wù)器上,客戶端請(qǐng)求通過數(shù)據(jù)庫中間層路由到不同的分區(qū)。這種方式目前還存在一定的弊端,如下所示:
●數(shù)據(jù)和負(fù)載增加后添加機(jī)器的操作比較復(fù)雜,往往需要人工介入;
●有些范圍查詢需要訪問幾乎所有的分區(qū),例如,按照user_id分區(qū),查詢收藏了一個(gè)商品的所有用戶需要訪問所有的分區(qū);
●目前廣泛使用的關(guān)系數(shù)據(jù)庫存儲(chǔ)引擎都是針對(duì)機(jī)械硬盤的特點(diǎn)設(shè)計(jì)的,不能夠完全發(fā)揮新硬件(SSD)的能力。
另外一種做法是參考分布式表格系統(tǒng)的做法,例如Google Bigtable系統(tǒng),將大表劃分為幾萬、幾十萬甚至幾百萬個(gè)子表,子表之間按照主鍵有序,如果某臺(tái)服務(wù)器發(fā)生故障,它上面服務(wù)的數(shù)據(jù)能夠在很短的時(shí)間內(nèi)自動(dòng)遷移到集群中所有的其他服務(wù)器。這種方式解決了可擴(kuò)展性的問題,少量突發(fā)的服務(wù)器故障或者增加服務(wù)器對(duì)使用者基本是透明的,能夠輕松應(yīng)對(duì)促銷或者熱點(diǎn)事件等突發(fā)流量增長(zhǎng)。另外,由于子表是按照主鍵有序分布的,很好地解決了范圍查詢的問題。
萬事有其利必有一弊,分布式表格系統(tǒng)雖然解決了可擴(kuò)展性問題,但往往無法支持事務(wù),例如Bigtable只支持單行事務(wù),針對(duì)同一個(gè)user_id下的多條記錄的操作都無法保證原子性。而OceanBase希望能夠支持跨行跨表事務(wù),這樣使用起來會(huì)比較方便。
最直接的做法是在Bigtable開源實(shí)現(xiàn)(如HBase或者Hypertable)的基礎(chǔ)上引入兩階段提交(Two-phase Commit)協(xié)議支持分布式事務(wù),這種思路在Google的Percolator系統(tǒng)中得到了體現(xiàn)。然而,Percolator系統(tǒng)中事務(wù)的平均響應(yīng)時(shí)間達(dá)到2~5秒,只能應(yīng)用在類似網(wǎng)頁建庫這樣的半線上業(yè)務(wù)中。另外,Bigtable的開源實(shí)現(xiàn)也不夠成熟,單臺(tái)服務(wù)器能夠支持的數(shù)據(jù)量有限,單個(gè)請(qǐng)求的最大響應(yīng)時(shí)間很難得到保證,機(jī)器故障等異常處理機(jī)制也有很多比較嚴(yán)重的問題。總體上看,這種做法的工作量和難度超出了項(xiàng)目組的承受能力,因此,我們需要根據(jù)業(yè)務(wù)特點(diǎn)做一些定制。
通過分析,我們發(fā)現(xiàn),雖然在線業(yè)務(wù)的數(shù)據(jù)量十分龐大,例如幾十億條、上百億條甚至更多記錄,但最近一段時(shí)間(例如一天)的修改量往往并不多,通常不超過幾千萬條到幾億條,因此,OceanBase決定采用單臺(tái)更新服務(wù)器來記錄最近一段時(shí)間的修改增量,而以前的數(shù)據(jù)保持不變,以前的數(shù)據(jù)稱為基線數(shù)據(jù)。基線數(shù)據(jù)以類似分布式文件系統(tǒng)的方式存儲(chǔ)于多臺(tái)基線數(shù)據(jù)服務(wù)器中,每次查詢都需要把基線數(shù)據(jù)和增量數(shù)據(jù)融合后返回給客戶端。這樣,寫事務(wù)都集中在單臺(tái)更新服務(wù)器上,避免了復(fù)雜的分布式事務(wù),高效地實(shí)現(xiàn)了跨行跨表事務(wù);另外,更新服務(wù)器上的修改增量能夠定期分發(fā)到多臺(tái)基線數(shù)據(jù)服務(wù)器中,避免成為瓶頸,實(shí)現(xiàn)了良好的擴(kuò)展性。
當(dāng)然,單臺(tái)更新服務(wù)器的處理能力總是有一定的限制。因此,更新服務(wù)器的硬件配置相對(duì)較好,如內(nèi)存較大、網(wǎng)卡及CPU較好;另外,最近一段時(shí)間的更新操作往往總是能夠存放在內(nèi)存中,在軟件層面也針對(duì)這種場(chǎng)景做了大量的優(yōu)化。
系統(tǒng)架構(gòu)
整體架構(gòu)圖如下:
OceanBase由如下幾個(gè)部分組成:
●客戶端:用戶使用OceanBase的方式和MySQL數(shù)據(jù)庫完全相同,支持JDBC、 C客戶端訪問,等等。基于MySQL數(shù)據(jù)庫開發(fā)的應(yīng)用程序、工具能夠直接遷移到OceanBase。
●RootServer:管理集群中的所有服務(wù)器,子表(tablet)數(shù)據(jù)分布以及副本管理。 RootServer一般為一主一備,主備之間數(shù)據(jù)強(qiáng)同步。
●UpdateServer:存儲(chǔ)OceanBase系統(tǒng)的增量更新數(shù)據(jù)。UpdateServer一般為一主一備,主備之間可以配置不同的同步模式。部署時(shí),UpdateServer進(jìn)程和RootServer進(jìn)程往往共用物理服務(wù)器。
●ChunkServer:存儲(chǔ)OceanBase系統(tǒng)的基線數(shù)據(jù)。基線數(shù)據(jù)一般存儲(chǔ)兩份或者三份,可配置。
●MergeServer:接收并解析用戶的SQL請(qǐng)求,經(jīng)過詞法分析、語法分析、查詢優(yōu)化等一系列操作后轉(zhuǎn)發(fā)給相應(yīng)的ChunkServer或者UpdateServer。如果請(qǐng)求的數(shù)據(jù)分布在多臺(tái)ChunkServer上,MergeServer還需要對(duì)多臺(tái)ChunkServer返回的結(jié)果進(jìn)行合并。客戶端和MergeServer之間采用原生的MySQL通信協(xié)議,MySQL客戶端可以直接訪問MergeServer。
OceanBase支持部署多個(gè)機(jī)房,每個(gè)機(jī)房部署一個(gè)包含RootServer、MergeServer、ChunkServer以及UpdateServer的完整OceanBase集群,每個(gè)集群由各自的RootServer負(fù)責(zé)數(shù)據(jù)劃分、負(fù)載均衡、集群服務(wù)器管理等操作,集群之間數(shù)據(jù)同步通過主集群的主UpdateServer往備集群同步增量更新操作日志實(shí)現(xiàn)。客戶端配置了多個(gè)集群的RootServer地址列表,使用者可以設(shè)置每個(gè)集群的流量分配比例,客戶端根據(jù)這個(gè)比例將讀寫操作發(fā)往不同的集群,如下圖:
客服端
1)請(qǐng)求RootServer獲取集群中MergeServer的地址列表。
2)按照一定的策略選擇某臺(tái)MergeServer發(fā)送讀寫請(qǐng)求。客戶端與MergeServer之間的通信協(xié)議兼容原生的MySQL協(xié)議,因此,只需要調(diào)用MySQL JDBC Driver或者M(jìn)ySQL C客戶端這樣的標(biāo)準(zhǔn)庫即可。客戶端支持的策略主要有兩種:隨機(jī)以及一致性哈希。一致性哈希的主要目的是將相同的SQL請(qǐng)求發(fā)送到同一臺(tái)MergeServer,方便MergeServer對(duì)查詢結(jié)果進(jìn)行緩存。
3)如果請(qǐng)求MergeServer失敗,則從MergeServer列表中重新選擇一臺(tái)MergeServer重試;如果請(qǐng)求某臺(tái)MergeServer失敗超過一定的次數(shù),將這臺(tái)MergeServer加入黑名單并從MergeServer列表中刪除。另外,客戶端會(huì)定期請(qǐng)求RootServer更新MergeServer地址列表。
如果OceanBase部署多個(gè)集群,客戶端還需要處理多個(gè)集群的流量分配問題。使用者可以設(shè)置多個(gè)集群之間的流量分配比例,客戶端獲取到流量分配比例后,按照這個(gè)比例將請(qǐng)求發(fā)送到不同的集群。
RootServer
RootServer的功能主要包括:集群管理、數(shù)據(jù)分布以及副本管理。
RootServer管理集群中的所有MergeServer、ChunkServer以及UpdateServer。每個(gè)集群內(nèi)部同一時(shí)刻只允許一個(gè)UpdateServer提供寫服務(wù),這個(gè)UpdateServer成為主UpdateServer。這種方式通過犧牲一定的可用性獲取了強(qiáng)一致性。RootServer通過租約(Lease)機(jī)制選擇唯一的主UpdateServer,當(dāng)原先的主UpdateServer發(fā)生故障后,RootServer能夠在原先的租約失效后選擇一臺(tái)新的UpdateServer作為主UpdateServer。另外,RootServer與MergeServer&ChunkServer之間保持心跳(heartbeat),從而能夠感知到在線和已經(jīng)下線的MergeServer&ChunkServer機(jī)器列表。
OceanBase內(nèi)部使用主鍵對(duì)表格中的數(shù)據(jù)進(jìn)行排序和存儲(chǔ),主鍵由若干列組成并且具有唯一性。在OceanBase內(nèi)部,基線數(shù)據(jù)按照主鍵排序并且劃分為數(shù)據(jù)量大致相等的數(shù)據(jù)范圍,稱為子表(tablet)。每個(gè)子表的默認(rèn)大小是256MB(可配置)。OceanBase的數(shù)據(jù)分布方式與Bigtable一樣采用順序分布,不同的是,OceanBase沒有采用根表(RootTable)+元數(shù)據(jù)表(MetaTable)兩級(jí)索引結(jié)構(gòu),而是采用根表一級(jí)索引結(jié)構(gòu)。
如圖所示,主鍵值在[1,100]之間的表格被劃分為四個(gè)子表:1~25,26~50,51~80以及81~100。RootServer中的根表記錄了每個(gè)子表所在的ChunkServer位置信息,每個(gè)子表包含多個(gè)副本(一般為三個(gè)副本,可配置),分布在多臺(tái)ChunkServer中。當(dāng)其中某臺(tái)ChunkServer發(fā)生故障時(shí),RootServer能夠檢測(cè)到,并且觸發(fā)對(duì)這臺(tái)ChunkServer上的子表增加副本的操作;另外,RootServer也會(huì)定期執(zhí)行負(fù)載均衡,選擇某些子表從負(fù)載較高的機(jī)器遷移到負(fù)載較低的機(jī)器上。
RootServer采用一主一備的結(jié)構(gòu),主備之間數(shù)據(jù)強(qiáng)同步,并通過Linux HA(http://www.linux-ha.org)軟件實(shí)現(xiàn)高可用性。主備RootServer之間共享VIP,當(dāng)主RootServer發(fā)生故障后,VIP能夠自動(dòng)漂移到備RootServer所在的機(jī)器,備RootServer檢測(cè)到以后切換為主RootServer提供服務(wù)。
MergeServer
MergeServer的功能主要包括:協(xié)議解析、SQL解析、請(qǐng)求轉(zhuǎn)發(fā)、結(jié)果合并、多表操作等。
OceanBase客戶端與MergeServer之間的協(xié)議為MySQL協(xié)議。MergeServer首先解析MySQL協(xié)議,從中提取出用戶發(fā)送的SQL語句,接著進(jìn)行詞法分析和語法分析,生成SQL語句的邏輯查詢計(jì)劃和物理查詢計(jì)劃,最后根據(jù)物理查詢計(jì)劃調(diào)用OceanBase內(nèi)部的各種操作符。
MergeServer緩存了子表分布信息,根據(jù)請(qǐng)求涉及的子表將請(qǐng)求轉(zhuǎn)發(fā)給該子表所在的ChunkServer。如果是寫操作,還會(huì)轉(zhuǎn)發(fā)給UpdateServer。某些請(qǐng)求需要跨多個(gè)子表,此時(shí)MergeServer會(huì)將請(qǐng)求拆分后發(fā)送給多臺(tái)ChunkServer,并合并這些ChunkServer返回的結(jié)果。如果請(qǐng)求涉及多個(gè)表格,MergeServer需要首先從ChunkServer獲取每個(gè)表格的數(shù)據(jù),接著再執(zhí)行多表關(guān)聯(lián)或者嵌套查詢等操作。
MergeServer支持并發(fā)請(qǐng)求多臺(tái)ChunkServer,即將多個(gè)請(qǐng)求發(fā)給多臺(tái)ChunkServer,再一次性等待所有請(qǐng)求的應(yīng)答。另外,在SQL執(zhí)行過程中,如果某個(gè)子表所在的ChunkServer出現(xiàn)故障,MergeServer會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給該子表的其他副本所在的ChunkServer。這樣,ChunkServer故障是不會(huì)影響用戶查詢的。
MergeServer本身是沒有狀態(tài)的,因此,MergeServer宕機(jī)不會(huì)對(duì)使用者產(chǎn)生影響,客戶端會(huì)自動(dòng)將發(fā)生故障的MergeServer屏蔽掉。
ChunkServer
ChunkServer的功能包括:存儲(chǔ)多個(gè)子表,提供讀取服務(wù),執(zhí)行定期合并以及數(shù)據(jù)分發(fā)。
OceanBase將大表劃分為大小約為256MB的子表,每個(gè)子表由一個(gè)或者多個(gè)SSTable組成(一般為一個(gè)),每個(gè)SSTable由多個(gè)塊(Block,大小為4KB~64KB之間,可配置)組成,數(shù)據(jù)在SSTable中按照主鍵有序存儲(chǔ)。查找某一行數(shù)據(jù)時(shí),需要首先定位這一行所屬的子表,接著在相應(yīng)的SSTable中執(zhí)行二分查找。SSTable支持兩種緩存模式,塊緩存(Block Cache)以及行緩存(Row Cache)。塊緩存以塊為單位緩存最近讀取的數(shù)據(jù),行緩存以行為單位緩存最近讀取的數(shù)據(jù)。
MergeServer將每個(gè)子表的讀取請(qǐng)求發(fā)送到子表所在的ChunkServer,ChunkServer首先讀取SSTable中包含的基線數(shù)據(jù),接著請(qǐng)求UpdateServer獲取相應(yīng)的增量更新數(shù)據(jù),并將基線數(shù)據(jù)與增量更新融合后得到最終結(jié)果。
由于每次讀取都需要從UpdateServer中獲取最新的增量更新,為了保證讀取性能,需要限制UpdateServer中增量更新的數(shù)據(jù)量,最好能夠全部存放在內(nèi)存中。OceanBase內(nèi)部會(huì)定期觸發(fā)合并或者數(shù)據(jù)分發(fā)操作,在這個(gè)過程中,ChunkServer將從UpdateServer獲取一段時(shí)間之前的更新操作。通常情況下,OceanBase集群會(huì)在每天的服務(wù)低峰期(凌晨1:00開始,可配置)執(zhí)行一次合并操作。這個(gè)合并操作往往也稱為每日合并。
UpdateServer
UpdateServer是集群中唯一能夠接受寫入的模塊,每個(gè)集群中只有一個(gè)主Update-Server。UpdateServer中的更新操作首先寫入到內(nèi)存表,當(dāng)內(nèi)存表的數(shù)據(jù)量超過一定值時(shí),可以生成快照文件并轉(zhuǎn)儲(chǔ)到SSD中。快照文件的組織方式與ChunkServer中的SSTable類似,因此,這些快照文件也稱為SSTable。另外,由于數(shù)據(jù)行的某些列被更新,某些列沒被更新,SSTable中存儲(chǔ)的數(shù)據(jù)行是稀疏的,稱為稀疏型SSTable。
為了保證可靠性,主UpdateServer更新內(nèi)存表之前需要首先寫操作日志,并同步到備UpdateServer。當(dāng)主UpdateServer發(fā)生故障時(shí),RootServer上維護(hù)的租約將失效,此時(shí),RootServer將從備UpdateServer列表中選擇一臺(tái)最新的備UpdateServer切換為主UpdateServer繼續(xù)提供寫服務(wù)。UpdateServer宕機(jī)重啟后需要首先加載轉(zhuǎn)儲(chǔ)的快照文件(SSTable文件),接著回放快照點(diǎn)之后的操作日志。
由于集群中只有一臺(tái)主UpdateServer提供寫服務(wù),因此,OceanBase很容易地實(shí)現(xiàn)了跨行跨表事務(wù),而不需要采用傳統(tǒng)的兩階段提交協(xié)議。當(dāng)然,這樣也帶來了一系列的問題。由于整個(gè)集群所有的讀寫操作都必須經(jīng)過UpdateServer,UpdateServer的性能至關(guān)重要。OceanBase集群通過定期合并和數(shù)據(jù)分發(fā)這兩種機(jī)制將UpdateServer一段時(shí)間之前的增量更新源源不斷地分散到ChunkServer,而UpdateServer只需要服務(wù)最新一小段時(shí)間新增的數(shù)據(jù),這些數(shù)據(jù)往往可以全部存放在內(nèi)存中。另外,系統(tǒng)實(shí)現(xiàn)時(shí)也需要對(duì)UpdateServer的內(nèi)存操作、網(wǎng)絡(luò)框架、磁盤操作做大量的優(yōu)化。
定期合并&數(shù)據(jù)分發(fā)
定期合并和數(shù)據(jù)分發(fā)都是將UpdateServer中的增量更新分發(fā)到ChunkServer中的手段,二者的整體流程比較類似:
1)UpdateServer凍結(jié)當(dāng)前的活躍內(nèi)存表(Active MemTable),生成凍結(jié)內(nèi)存表,并開啟新的活躍內(nèi)存表,后續(xù)的更新操作都寫入新的活躍內(nèi)存表。
2)UpdateServer通知RootServer數(shù)據(jù)版本發(fā)生了變化,之后RootServer通過心跳消息通知ChunkServer。
3)每臺(tái)ChunkServer啟動(dòng)定期合并或者數(shù)據(jù)分發(fā)操作,從UpdateServer獲取每個(gè)子表對(duì)應(yīng)的增量更新數(shù)據(jù)。
定期合并與數(shù)據(jù)分發(fā)兩者之間的不同點(diǎn)在于,數(shù)據(jù)分發(fā)過程中ChunkServer只是將UpdateServer中凍結(jié)內(nèi)存表中的增量更新數(shù)據(jù)緩存到本地,而定期合并過程中ChunkServer需要將本地SSTable中的基線數(shù)據(jù)與凍結(jié)內(nèi)存表的增量更新數(shù)據(jù)執(zhí)行一次多路歸并,融合后生成新的基線數(shù)據(jù)并存放到新的SSTable中。定期合并對(duì)系統(tǒng)服務(wù)能力影響很大,往往安排在每天服務(wù)低峰期執(zhí)行(例如凌晨1點(diǎn)開始),而數(shù)據(jù)分發(fā)可以不受限制。
?
轉(zhuǎn)載于:https://www.cnblogs.com/YDDMAX/p/6110096.html
總結(jié)
以上是生活随笔為你收集整理的OceanBase架构浅析(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Cocoapods快速创建自己的po
- 下一篇: 关于mount在unix系统上