姓名:郭金? ? 學(xué)號:17101223407
轉(zhuǎn)載自:https://www.cnblogs.com/LiJianBlog/p/4779934.html
【嵌牛導(dǎo)讀】:雙11阿里的成交額又創(chuàng)新高盹廷,1682億,支付峰值為25.6萬筆/秒抒和。
? ? ? 從阿里的公布各種宣傳稿來看分苇,有一個(gè)細(xì)節(jié),首次公布了數(shù)據(jù)庫處理峰值為4200萬次/秒梢褐。
? ? ? 螞蟻金服首席技術(shù)架構(gòu)師旺遮、副總裁胡喜介紹,支付寶之所以在今年首次公布“數(shù)據(jù)庫處理峰值”盈咳,是因?yàn)榻衲觌p11耿眉,支付寶首次把包括賬務(wù)庫在內(nèi)的所有核心數(shù)據(jù)鏈,全部搬到了螞蟻金服自主研發(fā)的數(shù)據(jù)庫OceanBase上鱼响。
【嵌牛鼻子】:OceanBase 鸣剪、 MergeServer
【嵌牛提問】: 為什么OceanBase特別適合雙十一?修改增量在內(nèi)存丈积,大概需要多大的內(nèi)存筐骇?
【嵌牛正文】:
? ? ? OceanBase吹了好多年了,終于用到核心庫里面去了桶癣,說明內(nèi)部覺得足夠成熟了拥褂,可喜可賀。
? ? 網(wǎng)上收集了下OceanBase的資料牙寞,分享給大家饺鹃。
1為什么OceanBase特別適合雙十一
(以下內(nèi)容來源網(wǎng)上阿里正詳?shù)慕獯穑?/p>
? ? ? 其實(shí),雖然不是刻意設(shè)計(jì)的间雀,但OceanBase確實(shí)比傳統(tǒng)數(shù)據(jù)庫更適合像雙十一悔详、聚劃算、秒殺以及銀行國庫券銷售等短時(shí)間突發(fā)大流量的場景:
·短時(shí)間內(nèi)大量用戶涌入
·短時(shí)間內(nèi)業(yè)務(wù)流量非常大惹挟,數(shù)據(jù)庫系統(tǒng)壓力非常大
·一段時(shí)間(幾秒鐘茄螃、幾分鐘、或半個(gè)小時(shí)等)后業(yè)務(wù)流量迅速或明顯回落
雖然2010年設(shè)計(jì)OceanBase架構(gòu)時(shí)连锯,其實(shí)并沒有特別考慮到這個(gè)突發(fā)大流量的因素归苍。讓我們從OceanBase的架構(gòu)說起用狱。
OceanBase是“基線數(shù)據(jù)(硬盤)”+“修改增量(內(nèi)存)”的架構(gòu),如下圖所示:
即整個(gè)數(shù)據(jù)庫以硬盤(通常是SSD)為載體拼弃,新近的增夏伊、刪、改數(shù)據(jù)(“修改增量”)在內(nèi)存吻氧,而基線數(shù)據(jù)在保存在硬盤上溺忧,因此OceanBase可以看成一個(gè)準(zhǔn)內(nèi)存數(shù)據(jù)庫。這樣的好處是:
·寫事務(wù)在內(nèi)存(除事務(wù)日志必須落盤外)盯孙,性能大大提升
·沒有隨機(jī)寫硬盤鲁森,硬盤隨機(jī)讀不受干擾,高峰期系統(tǒng)性能提升明顯振惰;對于傳統(tǒng)數(shù)據(jù)庫歌溉,業(yè)務(wù)高峰期通常也是大量隨機(jī)寫盤(刷臟頁)的高峰期,大量隨機(jī)寫盤消耗了大量的IO报账,特別是考慮到SSD的寫入放大研底,對于讀寫性能都有較大的影響
·基線數(shù)據(jù)只讀埠偿,緩存(cache)簡單且效果提升
·線上OceanBase的內(nèi)存配置是支撐平常兩天的修改增量(從OceanBase 1.0開始透罢,每臺OceanBase都可以寫入,都承載著部分的修改增量)冠蒋,因此即使突發(fā)大流量為平日的10-20倍羽圃,也可支撐1~2個(gè)小時(shí)以上。
一個(gè)問題是:修改增量在內(nèi)存抖剿,大概需要多大的內(nèi)存朽寞?即使按雙11全天的支付筆數(shù)10.5億筆,假設(shè)每筆1KB斩郎,總共需要的內(nèi)存大約是1TB脑融,平均到10臺服務(wù)器,100GB/臺缩宜。
另一個(gè)問題是:在類似雙十一這種流量特別大的場景中肘迎,就像前面說到的,OceanBase內(nèi)存能夠支持峰值業(yè)務(wù)寫入1~2個(gè)小時(shí)以上锻煌,之后OceanBase必須把內(nèi)存中的增刪改數(shù)據(jù)(“修改增量”)盡快整合到硬盤并釋放內(nèi)存妓布,以便業(yè)務(wù)的持續(xù)寫入。整合內(nèi)存中的修改增量到硬盤宋梧,OceanBase稱為每日合并匣沼,必然涉及到大量的硬盤讀寫(IO),因此可能對業(yè)務(wù)的吞吐量和事務(wù)響應(yīng)時(shí)間(RT)產(chǎn)生影響捂龄。如何避免每日合并對業(yè)務(wù)的影響呢释涛?OceanBase通過“輪轉(zhuǎn)合并”解決了這個(gè)問題加叁。
眾所周知,出于高可用的考慮唇撬,OceanBase是三機(jī)群(zone)部署:
根據(jù)配置和部署的不同殉农,業(yè)務(wù)高峰時(shí)可以一個(gè)機(jī)群(zone)、兩個(gè)機(jī)群(zone)或者三個(gè)機(jī)群(zone)提供讀寫服務(wù)局荚。OceanBase的輪轉(zhuǎn)合并就是對每個(gè)機(jī)群(zone)輪轉(zhuǎn)地進(jìn)行每日合并超凳,在對一個(gè)機(jī)群(zone)進(jìn)行每日合并之前,先把該機(jī)群(zone)上的業(yè)務(wù)讀寫流量切換到另外的一個(gè)或兩個(gè)機(jī)群(zone)耀态,然后對該機(jī)群(zone)進(jìn)行全速的每日合并轮傍。因此在每日合并期間,合并進(jìn)行中的機(jī)群(zone)沒有業(yè)務(wù)流量首装,僅僅接收事務(wù)日志并且參與Paxos投票创夜,業(yè)務(wù)訪問OceanBase的事務(wù)響應(yīng)時(shí)間完全不受每日合并的影響,僅僅是OceanBase的總吞吐量有所下降:如果先前是三個(gè)機(jī)群(zone)都提供服務(wù)則總吞吐量下降1/3仙逻,如果先前只有一個(gè)或兩個(gè)機(jī)群(zone)提供服務(wù)則總吞吐量沒有變化驰吓。
輪轉(zhuǎn)合并使得OceanBase對SSD十分友好,避免了大量隨機(jī)寫盤對SSD壽命的影響系奉,因此OceanBase可以使用相對廉價(jià)的“讀密集型”SSD來代替?zhèn)鹘y(tǒng)數(shù)據(jù)庫使用的相對昂貴的“讀寫型”SSD檬贰,而不影響性能。此外由于輪轉(zhuǎn)合并對服務(wù)器的CPU使用缺亮、硬盤IO使用以及耗時(shí)長短都不敏感(高峰期的傳統(tǒng)數(shù)據(jù)庫在刷臟頁的同時(shí)還要優(yōu)先保證業(yè)務(wù)訪問的吞吐量和事務(wù)響應(yīng)時(shí)間翁涤,刷臟頁的CPU及IO資源都非常受限),因此OceanBase在每日合并時(shí)可以采用更加高效的壓縮或者編碼算法(比如壓縮或編碼速度略慢萌踱,但壓縮率較高葵礼、解壓縮很快的算法),從而進(jìn)一步降低存儲成本并提升性能并鸵。
2OceanBase設(shè)計(jì)思路
OceanBase的目標(biāo)是支持?jǐn)?shù)百TB的數(shù)據(jù)量以及數(shù)十萬TPS鸳粉、數(shù)百萬QPS的訪問量,無論是數(shù)據(jù)量還是訪問量园担,即使采用非常昂貴的小型機(jī)甚至是大型機(jī)届谈,單臺關(guān)系數(shù)據(jù)庫系統(tǒng)都無法承受。
一種常見的做法是根據(jù)業(yè)務(wù)特點(diǎn)對數(shù)據(jù)庫進(jìn)行水平拆分粉铐,通常的做法是根據(jù)某個(gè)業(yè)務(wù)字段(通常取用戶編號疼约,user_id)哈希后取模,根據(jù)取模的結(jié)果將數(shù)據(jù)分布到不同的數(shù)據(jù)庫服務(wù)器上蝙泼,客戶端請求通過數(shù)據(jù)庫中間層路由到不同的分區(qū)程剥。這種方式目前還存在一定的弊端,如下所示:
數(shù)據(jù)和負(fù)載增加后添加機(jī)器的操作比較復(fù)雜,往往需要人工介入织鲸;
有些范圍查詢需要訪問幾乎所有的分區(qū)舔腾,例如,按照user_id分區(qū)搂擦,查詢收藏了一個(gè)商品的所有用戶需要訪問所有的分區(qū)稳诚;
目前廣泛使用的關(guān)系數(shù)據(jù)庫存儲引擎都是針對機(jī)械硬盤的特點(diǎn)設(shè)計(jì)的,不能夠完全發(fā)揮新硬件(SSD)的能力瀑踢。
另外一種做法是參考分布式表格系統(tǒng)的做法扳还,例如Google Bigtable系統(tǒng),將大表劃分為幾萬橱夭、幾十萬甚至幾百萬個(gè)子表氨距,子表之間按照主鍵有序,如果某臺服務(wù)器發(fā)生故障棘劣,它上面服務(wù)的數(shù)據(jù)能夠在很短的時(shí)間內(nèi)自動遷移到集群中所有的其他服務(wù)器俏让。這種方式解決了可擴(kuò)展性的問題,少量突發(fā)的服務(wù)器故障或者增加服務(wù)器對使用者基本是透明的茬暇,能夠輕松應(yīng)對促銷或者熱點(diǎn)事件等突發(fā)流量增長首昔。另外,由于子表是按照主鍵有序分布的糙俗,很好地解決了范圍查詢的問題勒奇。
萬事有其利必有一弊,分布式表格系統(tǒng)雖然解決了可擴(kuò)展性問題臼节,但往往無法支持事務(wù)撬陵,例如Bigtable只支持單行事務(wù),針對同一個(gè)user_id下的多條記錄的操作都無法保證原子性网缝。而OceanBase希望能夠支持跨行跨表事務(wù),這樣使用起來會比較方便蟋定。
最直接的做法是在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)也不夠成熟屠凶,單臺服務(wù)器能夠支持的數(shù)據(jù)量有限,單個(gè)請求的最大響應(yīng)時(shí)間很難得到保證肆资,機(jī)器故障等異常處理機(jī)制也有很多比較嚴(yán)重的問題矗愧。總體上看郑原,這種做法的工作量和難度超出了項(xiàng)目組的承受能力唉韭,因此夜涕,我們需要根據(jù)業(yè)務(wù)特點(diǎn)做一些定制。
通過分析属愤,我們發(fā)現(xiàn)女器,雖然在線業(yè)務(wù)的數(shù)據(jù)量十分龐大,例如幾十億條住诸、上百億條甚至更多記錄驾胆,但最近一段時(shí)間(例如一天)的修改量往往并不多,通常不超過幾千萬條到幾億條贱呐,因此俏拱,OceanBase決定采用單臺更新服務(wù)器來記錄最近一段時(shí)間的修改增量,而以前的數(shù)據(jù)保持不變吼句,以前的數(shù)據(jù)稱為基線數(shù)據(jù)锅必。基線數(shù)據(jù)以類似分布式文件系統(tǒng)的方式存儲于多臺基線數(shù)據(jù)服務(wù)器中惕艳,每次查詢都需要把基線數(shù)據(jù)和增量數(shù)據(jù)融合后返回給客戶端搞隐。這樣,寫事務(wù)都集中在單臺更新服務(wù)器上远搪,避免了復(fù)雜的分布式事務(wù)劣纲,高效地實(shí)現(xiàn)了跨行跨表事務(wù);另外谁鳍,更新服務(wù)器上的修改增量能夠定期分發(fā)到多臺基線數(shù)據(jù)服務(wù)器中癞季,避免成為瓶頸,實(shí)現(xiàn)了良好的擴(kuò)展性倘潜。
當(dāng)然绷柒,單臺更新服務(wù)器的處理能力總是有一定的限制。因此涮因,更新服務(wù)器的硬件配置相對較好废睦,如內(nèi)存較大、網(wǎng)卡及CPU較好养泡;另外嗜湃,最近一段時(shí)間的更新操作往往總是能夠存放在內(nèi)存中,在軟件層面也針對這種場景做了大量的優(yōu)化澜掩。
3OceanBase系統(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:存儲OceanBase系統(tǒng)的增量更新數(shù)據(jù)。UpdateServer一般為一主一備贮懈,主備之間可以配置不同的同步模式匀泊。部署時(shí),UpdateServer進(jìn)程和RootServer進(jìn)程往往共用物理服務(wù)器朵你。
ChunkServer:存儲OceanBase系統(tǒng)的基線數(shù)據(jù)各聘。基線數(shù)據(jù)一般存儲兩份或者三份抡医,可配置躲因。
MergeServer:接收并解析用戶的SQL請求,經(jīng)過詞法分析忌傻、語法分析大脉、查詢優(yōu)化等一系列操作后轉(zhuǎn)發(fā)給相應(yīng)的ChunkServer或者UpdateServer。如果請求的數(shù)據(jù)分布在多臺ChunkServer上水孩,MergeServer還需要對多臺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)請求RootServer獲取集群中MergeServer的地址列表铁追。
2)按照一定的策略選擇某臺MergeServer發(fā)送讀寫請求季蚂。客戶端與MergeServer之間的通信協(xié)議兼容原生的MySQL協(xié)議,因此扭屁,只需要調(diào)用MySQL JDBC Driver或者M(jìn)ySQL C客戶端這樣的標(biāo)準(zhǔn)庫即可算谈。客戶端支持的策略主要有兩種:隨機(jī)以及一致性哈希料滥。一致性哈希的主要目的是將相同的SQL請求發(fā)送到同一臺MergeServer然眼,方便MergeServer對查詢結(jié)果進(jìn)行緩存。
3)如果請求MergeServer失敗葵腹,則從MergeServer列表中重新選擇一臺MergeServer重試高每;如果請求某臺MergeServer失敗超過一定的次數(shù),將這臺MergeServer加入黑名單并從MergeServer列表中刪除践宴。另外鲸匿,客戶端會定期請求RootServer更新MergeServer地址列表。
如果OceanBase部署多個(gè)集群阻肩,客戶端還需要處理多個(gè)集群的流量分配問題带欢。使用者可以設(shè)置多個(gè)集群之間的流量分配比例,客戶端獲取到流量分配比例后烤惊,按照這個(gè)比例將請求發(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能夠在原先的租約失效后選擇一臺新的UpdateServer作為主UpdateServer。另外防楷,RootServer與MergeServer&ChunkServer之間保持心跳(heartbeat)牺丙,從而能夠感知到在線和已經(jīng)下線的MergeServer&ChunkServer機(jī)器列表。
OceanBase內(nèi)部使用主鍵對表格中的數(shù)據(jù)進(jìn)行排序和存儲复局,主鍵由若干列組成并且具有唯一性冲簿。在OceanBase內(nèi)部,基線數(shù)據(jù)按照主鍵排序并且劃分為數(shù)據(jù)量大致相等的數(shù)據(jù)范圍亿昏,稱為子表(tablet)峦剔。每個(gè)子表的默認(rèn)大小是256MB(可配置)。OceanBase的數(shù)據(jù)分布方式與Bigtable一樣采用順序分布角钩,不同的是吝沫,OceanBase沒有采用根表(RootTable)+元數(shù)據(jù)表(MetaTable)兩級索引結(jié)構(gòu)呻澜,而是采用根表一級索引結(jié)構(gòu)。
如圖所示惨险,主鍵值在[1羹幸,100]之間的表格被劃分為四個(gè)子表:1~25,26~50辫愉,51~80以及81~100栅受。RootServer中的根表記錄了每個(gè)子表所在的ChunkServer位置信息,每個(gè)子表包含多個(gè)副本(一般為三個(gè)副本一屋,可配置)窘疮,分布在多臺ChunkServer中。當(dāng)其中某臺ChunkServer發(fā)生故障時(shí)冀墨,RootServer能夠檢測到闸衫,并且觸發(fā)對這臺ChunkServer上的子表增加副本的操作;另外诽嘉,RootServer也會定期執(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能夠自動漂移到備RootServer所在的機(jī)器,備RootServer檢測到以后切換為主RootServer提供服務(wù)盒蟆。
MergeServer
MergeServer的功能主要包括:協(xié)議解析踏烙、SQL解析、請求轉(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ù)請求涉及的子表將請求轉(zhuǎn)發(fā)給該子表所在的ChunkServer鸳君。如果是寫操作,還會轉(zhuǎn)發(fā)給UpdateServer患蹂。某些請求需要跨多個(gè)子表或颊,此時(shí)MergeServer會將請求拆分后發(fā)送給多臺ChunkServer,并合并這些ChunkServer返回的結(jié)果传于。如果請求涉及多個(gè)表格囱挑,MergeServer需要首先從ChunkServer獲取每個(gè)表格的數(shù)據(jù),接著再執(zhí)行多表關(guān)聯(lián)或者嵌套查詢等操作沼溜。
MergeServer支持并發(fā)請求多臺ChunkServer平挑,即將多個(gè)請求發(fā)給多臺ChunkServer,再一次性等待所有請求的應(yīng)答系草。另外通熄,在SQL執(zhí)行過程中,如果某個(gè)子表所在的ChunkServer出現(xiàn)故障找都,MergeServer會將請求轉(zhuǎn)發(fā)給該子表的其他副本所在的ChunkServer唇辨。這樣,ChunkServer故障是不會影響用戶查詢的能耻。
MergeServer本身是沒有狀態(tài)的赏枚,因此,MergeServer宕機(jī)不會對使用者產(chǎn)生影響晓猛,客戶端會自動將發(fā)生故障的MergeServer屏蔽掉饿幅。
ChunkServer
ChunkServer的功能包括:存儲多個(gè)子表,提供讀取服務(wù)戒职,執(zhí)行定期合并以及數(shù)據(jù)分發(fā)栗恩。
OceanBase將大表劃分為大小約為256MB的子表,每個(gè)子表由一個(gè)或者多個(gè)SSTable組成(一般為一個(gè))洪燥,每個(gè)SSTable由多個(gè)塊(Block磕秤,大小為4KB~64KB之間,可配置)組成蚓曼,數(shù)據(jù)在SSTable中按照主鍵有序存儲亲澡。查找某一行數(shù)據(jù)時(shí),需要首先定位這一行所屬的子表纫版,接著在相應(yīng)的SSTable中執(zhí)行二分查找床绪。SSTable支持兩種緩存模式,塊緩存(Block Cache)以及行緩存(Row Cache)其弊。塊緩存以塊為單位緩存最近讀取的數(shù)據(jù)癞己,行緩存以行為單位緩存最近讀取的數(shù)據(jù)。
MergeServer將每個(gè)子表的讀取請求發(fā)送到子表所在的ChunkServer,ChunkServer首先讀取SSTable中包含的基線數(shù)據(jù)梭伐,接著請求UpdateServer獲取相應(yīng)的增量更新數(shù)據(jù)痹雅,并將基線數(shù)據(jù)與增量更新融合后得到最終結(jié)果。
由于每次讀取都需要從UpdateServer中獲取最新的增量更新糊识,為了保證讀取性能绩社,需要限制UpdateServer中增量更新的數(shù)據(jù)量摔蓝,最好能夠全部存放在內(nèi)存中。OceanBase內(nèi)部會定期觸發(fā)合并或者數(shù)據(jù)分發(fā)操作愉耙,在這個(gè)過程中贮尉,ChunkServer將從UpdateServer獲取一段時(shí)間之前的更新操作。通常情況下朴沿,OceanBase集群會在每天的服務(wù)低峰期(凌晨1:00開始猜谚,可配置)執(zhí)行一次合并操作。這個(gè)合并操作往往也稱為每日合并赌渣。
UpdateServer
UpdateServer是集群中唯一能夠接受寫入的模塊魏铅,每個(gè)集群中只有一個(gè)主Update-Server。UpdateServer中的更新操作首先寫入到內(nèi)存表坚芜,當(dāng)內(nèi)存表的數(shù)據(jù)量超過一定值時(shí)览芳,可以生成快照文件并轉(zhuǎn)儲到SSD中』趿耄快照文件的組織方式與ChunkServer中的SSTable類似路操,因此,這些快照文件也稱為SSTable千贯。另外屯仗,由于數(shù)據(jù)行的某些列被更新,某些列沒被更新搔谴,SSTable中存儲的數(shù)據(jù)行是稀疏的魁袜,稱為稀疏型SSTable。
為了保證可靠性敦第,主UpdateServer更新內(nèi)存表之前需要首先寫操作日志峰弹,并同步到備UpdateServer。當(dāng)主UpdateServer發(fā)生故障時(shí)芜果,RootServer上維護(hù)的租約將失效鞠呈,此時(shí),RootServer將從備UpdateServer列表中選擇一臺最新的備UpdateServer切換為主UpdateServer繼續(xù)提供寫服務(wù)右钾。UpdateServer宕機(jī)重啟后需要首先加載轉(zhuǎn)儲的快照文件(SSTable文件)蚁吝,接著回放快照點(diǎn)之后的操作日志。
由于集群中只有一臺主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í)也需要對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)每臺ChunkServer啟動定期合并或者數(shù)據(jù)分發(fā)操作咙边,從UpdateServer獲取每個(gè)子表對應(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中。定期合并對系統(tǒng)服務(wù)能力影響很大市殷,往往安排在每天服務(wù)低峰期執(zhí)行(例如凌晨1點(diǎn)開始)愕撰,而數(shù)據(jù)分發(fā)可以不受限制。
單點(diǎn)性能
OceanBase架構(gòu)的優(yōu)勢在于既支持跨行跨表事務(wù)醋寝,又支持存儲服務(wù)器線性擴(kuò)展搞挣。當(dāng)然,這個(gè)架構(gòu)也有一個(gè)明顯的缺陷:UpdateServer單點(diǎn)音羞,這個(gè)問題限制了OceanBase集群的整體讀寫性能囱桨。下面從內(nèi)存容量、網(wǎng)絡(luò)嗅绰、磁盤等幾個(gè)方面分析UpdateServer的讀寫性能舍肠。其實(shí)大部分?jǐn)?shù)據(jù)庫每天的修改次數(shù)相當(dāng)有限,只有少數(shù)修改比較頻繁的數(shù)據(jù)庫才有每天幾億次的修改次數(shù)办陷。另外貌夕,數(shù)據(jù)庫平均每次修改涉及的數(shù)據(jù)量很少,很多時(shí)候只有幾十個(gè)字節(jié)到幾百個(gè)字節(jié)民镜。假設(shè)數(shù)據(jù)庫每天更新1億次啡专,平均每次需要消耗100字節(jié),每天插入1000萬次制圈,平均每次需要消耗1000字節(jié)们童,那么畔况,一天的修改量為:1億×100+1000萬×1000=20GB,如果內(nèi)存數(shù)據(jù)結(jié)構(gòu)膨脹2倍慧库,占用內(nèi)存只有40GB跷跪。而當(dāng)前主流的服務(wù)器都可以配置96GB內(nèi)存,一些高檔的服務(wù)器甚至可以配置192GB齐板、384GB乃至更多內(nèi)存吵瞻。
從上面的分析可以看出,UpdateServer的內(nèi)存容量一般不會成為瓶頸甘磨。然而橡羞,服務(wù)器的內(nèi)存畢竟有限,實(shí)際應(yīng)用中仍然可能出現(xiàn)修改量超出內(nèi)存的情況济舆。例如卿泽,淘寶雙11網(wǎng)購節(jié)數(shù)據(jù)庫修改量暴漲,某些特殊應(yīng)用每天的修改次數(shù)特別多或者每次修改的數(shù)據(jù)量特別大滋觉,DBA數(shù)據(jù)訂正時(shí)一次性寫入大量數(shù)據(jù)签夭。為此,UpdateServer設(shè)計(jì)實(shí)現(xiàn)了幾種方式解決內(nèi)存容量問題椎侠,UpdateServer的內(nèi)存表達(dá)到一定大小時(shí)第租,可自動或者手工凍結(jié)并轉(zhuǎn)儲到SSD中,另外肺蔚,OceanBase支持通過定期合并或者數(shù)據(jù)分發(fā)的方式將UpdateServer的數(shù)據(jù)分散到集群中所有的ChunkServer機(jī)器中煌妈,這樣不僅避免了UpdateServer單機(jī)數(shù)據(jù)容量問題,還能夠使得讀取操作往往只需要訪問UpdateServer內(nèi)存中的數(shù)據(jù)宣羊,避免訪問SSD磁盤璧诵,提高了讀取性能。
從網(wǎng)絡(luò)角度看仇冯,假設(shè)每秒的讀取次數(shù)為20萬次之宿,每次需要從UpdateServer中獲取100字節(jié),那么苛坚,讀取操作占用的UpdateServer出口帶寬為:20萬×100=20MB比被,遠(yuǎn)遠(yuǎn)沒有達(dá)到千兆網(wǎng)卡帶寬上限。另外泼舱,UpdateServer還可以配置多塊千兆網(wǎng)卡或者萬兆網(wǎng)卡等缀,例如,OceanBase線上集群一般給UpdateServer配置4塊千兆網(wǎng)卡娇昙。當(dāng)然尺迂,如果軟件層面沒有做好,硬件特性將得不到充分發(fā)揮。針對UpdateServer全內(nèi)存噪裕、收發(fā)的網(wǎng)絡(luò)包一般比較小的特點(diǎn)蹲盘,開發(fā)團(tuán)隊(duì)對UpdateServer的網(wǎng)絡(luò)框架做了專門的優(yōu)化,大大提高了每秒收發(fā)網(wǎng)絡(luò)包的個(gè)數(shù)膳音,使得網(wǎng)絡(luò)不會成為瓶頸召衔。
從磁盤的角度看,數(shù)據(jù)庫事務(wù)需要首先將操作日志寫入磁盤祭陷。如果每次寫入都需要將數(shù)據(jù)刷入磁盤苍凛,而一塊SAS磁盤每秒支持的IOPS很難超過300待侵,磁盤將很快成為瓶頸而昨。為了解決這個(gè)問題,UpdateServer在硬件上會配置一塊帶有緩存模塊的RAID卡驾诈,UpdateServer寫操作日志只需要寫入到RAID卡的緩存模塊即可毒姨,延時(shí)可以控制在1毫秒之內(nèi)。RAID卡帶電池钉寝,如果UpdateServer發(fā)生故障弧呐,比如機(jī)器突然停電,RAID卡能夠確保將緩存中的數(shù)據(jù)刷入磁盤嵌纲,不會出現(xiàn)丟數(shù)據(jù)的情況俘枫。另外,UpdateServer還實(shí)現(xiàn)了寫事務(wù)的成組提交機(jī)制逮走,將多個(gè)用戶寫操作湊成一批一次性提交鸠蚪,進(jìn)一步減少磁盤IO次數(shù)。
磁盤隨機(jī)IO是存儲系統(tǒng)性能的決定因素师溅,傳統(tǒng)的SAS盤能夠提供的IOPS不超過300茅信。關(guān)系數(shù)據(jù)庫一般采用高速緩存(Buffer Cache)[注釋]的方式緩解這個(gè)問題,讀取操作將磁盤中的頁面緩存到高速緩存中墓臭,并通過LRU或者類似的方式淘汰不經(jīng)常訪問的頁面蘸鲸;同樣,寫入操作也是將數(shù)據(jù)寫入到高速緩存中窿锉,由高速緩存按照一定的策略將內(nèi)存中頁面的內(nèi)容刷入磁盤酌摇。這種方式面臨一些問題,例如嗡载,Cache冷啟動問題窑多,即數(shù)據(jù)庫剛啟動時(shí)性能很差,需要將讀取流量逐步切入洼滚。另外埂息,這種方式不適合寫入特別多的場景。
最近幾年,SSD磁盤取得了很大的進(jìn)展耿芹,它不僅提供了非常好的隨機(jī)讀取性能崭篡,功耗也非常低,大有取代傳統(tǒng)機(jī)械磁盤之勢吧秕。一塊普通的SSD磁盤可以提供35000 IOPS甚至更高,并提供300MB/s或以上的讀出帶寬砸彬。然而颠毙,SSD盤的隨機(jī)寫性能并不理想。這是因?yàn)楸樱M管SSD的讀和寫以頁(page幕侠,例如4KB,8KB等)為單位碍彭,但SSD寫入前需要首先擦除已有內(nèi)容晤硕,而擦除以塊(block)為單位,一個(gè)塊由若干個(gè)連續(xù)的頁組成庇忌,大小通常在512KB~2MB舞箍。假如寫入的頁有內(nèi)容,即使只寫入一個(gè)字節(jié)漆枚,SSD也需要擦除整個(gè)512KB~2MB大小的塊创译,然后再寫入整個(gè)頁的內(nèi)容,這就是SSD的寫入放大效應(yīng)墙基。雖然SSD硬件廠商都針對這個(gè)問題做了一些優(yōu)化软族,但整體上看,隨機(jī)寫入不能發(fā)揮SSD的優(yōu)勢残制。
OceanBase設(shè)計(jì)之初就認(rèn)為SSD為大勢所趨立砸,整個(gè)系統(tǒng)設(shè)計(jì)時(shí)完全摒棄了隨機(jī)寫,除了操作日志總是順序追加寫入到普通SAS盤上初茶,剩下的寫請求都是對響應(yīng)時(shí)間要求不是很高的批量順序?qū)懣抛#琒SD盤可以輕松應(yīng)對,而大量查詢請求的隨機(jī)讀,則發(fā)揮了SSD良好的隨機(jī)讀的特性螺戳。摒棄隨機(jī)寫搁宾,采用批量的順序?qū)懀彩沟霉虘B(tài)盤的使用壽命不再成為問題倔幼,主流SSD盤使用MLC SSD芯片盖腿,而MLC號稱可以擦寫1萬次(SLC可以擦寫10萬次,但因成本高而較少使用)损同,即使按最保守的2500次擦寫次數(shù)計(jì)算翩腐,而且每天全部擦寫一遍,其使用壽命為2500/365=6.8年膏燃。
數(shù)據(jù)正確性
數(shù)據(jù)丟失或者數(shù)據(jù)錯(cuò)誤對于存儲系統(tǒng)來說是一種災(zāi)難茂卦。OceanBase設(shè)計(jì)為強(qiáng)一致性系統(tǒng),設(shè)計(jì)方案上保證不丟數(shù)據(jù)组哩。然而等龙,TCP協(xié)議傳輸、磁盤讀寫都可能出現(xiàn)數(shù)據(jù)錯(cuò)誤伶贰,程序Bug則更為常見而咆。為了防止各種因素導(dǎo)致的數(shù)據(jù)損毀,OceanBase采取了以下數(shù)據(jù)校驗(yàn)措施:
? ? 數(shù)據(jù)存儲校驗(yàn)幕袱。每個(gè)存儲記錄(通常是幾KB到幾十KB)同時(shí)保存64位CRC校驗(yàn)碼,數(shù)據(jù)被訪問時(shí)悠瞬,重新計(jì)算和比對校驗(yàn)碼们豌。
? ? 數(shù)據(jù)傳輸校驗(yàn)。每個(gè)傳輸記錄同時(shí)傳輸64位CRC校驗(yàn)碼浅妆,數(shù)據(jù)被接收后望迎,重新計(jì)算和比對校驗(yàn)碼。
? ? 數(shù)據(jù)鏡像校驗(yàn)凌外。UpdateServer在機(jī)群內(nèi)有主UpdateServer和備UpdateServer辩尊,集群間有主集群和備集群,這些UpdateServer的內(nèi)存表(MemTable)必須保持一致康辑。為此摄欲,UpdateServer為MemTable生成一個(gè)校驗(yàn)碼,MemTable每次更新時(shí)疮薇,校驗(yàn)碼同步更新并記錄在對應(yīng)的操作日志中胸墙。備UpdateServer收到操作日志并重放到MemTable時(shí),也同步更新MemTable校驗(yàn)碼并與接收到的校驗(yàn)碼對照按咒。UpdateServer重新啟動后重放日志恢復(fù)MemTable時(shí)也同步更新MemTable校驗(yàn)碼并與保存在每條操作日志中的校驗(yàn)碼對照迟隅。
? ? 數(shù)據(jù)副本校驗(yàn)。定期合并時(shí),新的子表由各個(gè)ChunkServer獨(dú)立地融合舊的子表中的SSTable與凍結(jié)的MemTable而生成智袭,如果發(fā)生任何異潮疾或者錯(cuò)誤(比如程序bug),同一子表的多個(gè)副本可能不一致吼野,則這種不一致可能隨著定期合并而逐步累積或擴(kuò)散且很難被發(fā)現(xiàn)校哎,即使被察覺,也可能因?yàn)樾枰匪葺^長時(shí)間而難以定位到源頭箫锤。為了防止這種情況出現(xiàn)贬蛙,ChunkServer在定期合并生成新的子表時(shí),也同時(shí)為每個(gè)子表生成一個(gè)校驗(yàn)碼谚攒,并隨新子表匯報(bào)給RootServer阳准,以便RootServer核對同一子表不同副本的校驗(yàn)碼。