分布式數(shù)據(jù)庫(kù)架構(gòu)
本篇將從分布式的概念出發(fā)篡九,闡述筆者理解的分布式數(shù)據(jù)庫(kù)三個(gè)發(fā)展階段抗碰,并分別介紹每個(gè)階段的代表性的數(shù)據(jù)庫(kù)及其架構(gòu)
筆者水平有限价脾,如有錯(cuò)誤懇請(qǐng)指正匾荆。文中的部分圖片獲取自網(wǎng)絡(luò),侵刪粒督。
分布式數(shù)據(jù)庫(kù)發(fā)展梗概
分布式是面向業(yè)務(wù)擴(kuò)展而出現(xiàn)的一個(gè)概念陪竿,而分布式數(shù)據(jù)庫(kù)禽翼,就是為了解決存儲(chǔ)可擴(kuò)展性的一類數(shù)據(jù)庫(kù)屠橄。筆者認(rèn)為除了最初的分庫(kù)分表方案,分布式數(shù)據(jù)庫(kù)經(jīng)歷了三個(gè)主要發(fā)展階段闰挡。第一代是分布式中間件的形式锐墙,大多數(shù)是基于MySQL數(shù)據(jù)庫(kù)做Data Sharding和水平擴(kuò)展;第二代是以Cassandra长酗、MongoDB為代表的NoSQL溪北;第三代是以AWS Aurora和Google Spanner為代表的云數(shù)據(jù)庫(kù),或者稱作NewSQL。
這三個(gè)階段在分布式這個(gè)概念上沒有本質(zhì)上的區(qū)別之拨,但是在具體的實(shí)現(xiàn)上有不同的側(cè)重點(diǎn)茉继,比如NoSQL就不支持跨分片的ACID事務(wù)。大家要注意并不是越新的概念的就越先進(jìn)蚀乔,實(shí)際上烁竭,現(xiàn)在市面上主流的分布式數(shù)據(jù)庫(kù),大多是分布式中間件的形式吉挣。
關(guān)于數(shù)據(jù)庫(kù)文件系統(tǒng)
在具體介紹各類分布式數(shù)據(jù)庫(kù)之前派撕,我們先來了解一下在數(shù)據(jù)庫(kù)中實(shí)際存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)庫(kù)文件系統(tǒng)。
目前主流的數(shù)據(jù)庫(kù)文件系統(tǒng)有兩類睬魂,一類是關(guān)系型數(shù)據(jù)庫(kù)(如MySQL)使用的B+Tree终吼,另一類是多用于鍵值存儲(chǔ)數(shù)據(jù)庫(kù)(如NoSQL)的LSM-Tree數(shù)據(jù)結(jié)構(gòu)。分布式數(shù)據(jù)庫(kù)建立在分布式文件系統(tǒng)之上氯哮,在底層實(shí)現(xiàn)上也是依賴于這兩類數(shù)據(jù)結(jié)構(gòu)的际跪。
了解一下LSM-Tree
相信大家對(duì)B+Tree都有一定程度的了解,但對(duì)LSM-Tree可能就沒那么熟悉了蛙粘,這里我們簡(jiǎn)單介紹一下LSM-Tree垫卤。
LSM-Tree,全稱Log Structured Merge Tree出牧,是一種寫入操作不做原地更新穴肘,而是以追加的方式寫入內(nèi)存,每次寫到一定程度舔痕,即凍結(jié)為一層评抚,然后寫入持久化存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)。
我們可以簡(jiǎn)單描述一下一條數(shù)據(jù)在LSM-Tree中的寫入過程:寫入Log -> 寫入memtable -> flush入持久化存儲(chǔ) -> 經(jīng)compaction操作進(jìn)入持久化存儲(chǔ)的更新層 -> 同一key的新數(shù)據(jù)到來時(shí)丟棄伯复。
下面是一張LSM-Tree的結(jié)構(gòu)圖慨代。
B+Tree VS LSM-Tree
我們來比較一下這兩類數(shù)據(jù)結(jié)構(gòu),明確它們的特性和適用場(chǎng)景啸如。
B+Tree將數(shù)據(jù)拆分為固定大小的Block或Page侍匙,Page是讀寫的最小單位。B+Tree可以做到原地更新和刪除叮雳,因此對(duì)數(shù)據(jù)庫(kù)事務(wù)的支持更加友好想暗,因?yàn)橐粋€(gè)key只會(huì)出現(xiàn)一個(gè)Page頁(yè)里面。
而LSM-Tree的設(shè)計(jì)思路是將數(shù)據(jù)拆分為幾百M(fèi)大小的Segment帘不,并順序?qū)懭胨的SM-Tree只能追加寫,并且在L0層key的range會(huì)重疊寞焙,所以對(duì)事務(wù)支持較弱储狭,只能在Segment Compaction的時(shí)候真正地更新和刪除互婿。
B+Tree的優(yōu)點(diǎn)是支持高效的讀(穩(wěn)定的O(logN)的復(fù)雜度),但對(duì)大規(guī)模的寫請(qǐng)求的效率就比較低(O(logN)復(fù)雜度)辽狈,這是因?yàn)樵诖笠?guī)模寫的情況下慈参,為了維護(hù)B+Tree的結(jié)構(gòu),B+Tree的節(jié)點(diǎn)就會(huì)不斷分裂刮萌,操作磁盤的隨機(jī)讀寫概率會(huì)變大懂牧,從而導(dǎo)致寫性能降低。
LSM-Tree則相反尊勿,支持高吞吐量的寫(O(1))僧凤,但普通LSM-Tree讀取的復(fù)雜度是O(n),在使用索引或者緩存優(yōu)化后可以達(dá)到O(logN)元扔。
我們可以粗略的認(rèn)為未優(yōu)化的LSM-Tree的寫比B+Tree快一個(gè)數(shù)量級(jí)躯保,未優(yōu)化的LSM-Tree的讀比B+Tree慢一個(gè)數(shù)量級(jí)。
第一代分布式數(shù)據(jù)庫(kù)——分庫(kù)分表及分布式中間件
最初面對(duì)存儲(chǔ)擴(kuò)展問題澎语,一個(gè)比較直接的思路就是分庫(kù)分表——一個(gè)庫(kù)裝不下途事,我就用多個(gè)庫(kù)裝。
假設(shè)一開始我們有一個(gè)單點(diǎn)的MySQL數(shù)據(jù)庫(kù)擅羞,隨著業(yè)務(wù)增長(zhǎng)尸变,達(dá)到了單庫(kù)的存儲(chǔ)性能瓶頸,準(zhǔn)備使用三到五個(gè)MySQL來重新安排存儲(chǔ)减俏。在最理想的情況下召烂,我們可以在擁有原來三到五倍存儲(chǔ)空間的情況下,也能有三到五倍的并發(fā)來提升存儲(chǔ)性能娃承。
但這有兩個(gè)很明顯的問題:第一個(gè)是我要對(duì)業(yè)務(wù)進(jìn)行大量的改造奏夫,找到一個(gè)合適的維度打散業(yè)務(wù)進(jìn)入多個(gè)庫(kù)(而且這種完美的方案還不一定存在),而且跨庫(kù)的業(yè)務(wù)也要重新寫業(yè)務(wù)邏輯历筝。第二個(gè)是一旦庫(kù)又滿了酗昼,我想再做一次擴(kuò)容的工作,我就又要把這部分的工作再做一次——包括重寫業(yè)務(wù)梳猪。
上面兩個(gè)問題的代價(jià)顯然是不可承受的麻削,這時(shí)候就有分布式數(shù)據(jù)庫(kù)廠家來說了:我們來做整合并管理多個(gè)庫(kù)的工作,你們應(yīng)用只要把多個(gè)數(shù)據(jù)庫(kù)當(dāng)作原來的一個(gè)庫(kù)使用即可春弥。
這就誕生了分布式中間件的概念呛哟,或者稱作分布式關(guān)系型數(shù)據(jù)庫(kù)。分布式中間件惕稻,是從關(guān)系型數(shù)據(jù)庫(kù)出發(fā)竖共,加入分布式技術(shù)蝙叛,實(shí)現(xiàn)分布式的高可用性和高擴(kuò)展性等特性俺祠。本文把此類數(shù)據(jù)庫(kù)稱為分布式中間件,不代表它們就沒有對(duì)底層數(shù)據(jù)庫(kù)(通常是MySQL)做任何改動(dòng)。實(shí)際上蜘渣,目前市面上的分布式關(guān)系型數(shù)據(jù)庫(kù)幾乎都對(duì)底層數(shù)據(jù)庫(kù)有自己的修改淌铐,甚至有阿里的OceanBase那樣自己實(shí)現(xiàn)一個(gè)關(guān)系型底層的情況。
但是蔫缸,分布式中間件 有根本解決上面的兩個(gè)問題嗎腿准?顯然并沒有。分布式中間件沒有把數(shù)據(jù)自動(dòng)分片的能力拾碌,應(yīng)用也不能真真正正的把分布式數(shù)據(jù)庫(kù)當(dāng)作一個(gè)單庫(kù)來使用——除非你完全不在乎跨片的性能損耗。
但分布式中間件也確確實(shí)實(shí)有很大的作用,它極大的減少了業(yè)務(wù)的改造量缩擂,也保證了了分布式事務(wù)的ACID特性曲饱。在各類分布式中間件迭代發(fā)展的過程中,這一技術(shù)路線也在逐漸進(jìn)步:廠家開始探索對(duì)底層數(shù)據(jù)庫(kù)的改造防症,以使其更適應(yīng)分布式特性孟辑;中間件層也吸收了后面NewSQL的一些技術(shù)思路,在全局事務(wù)管理蔫敲、數(shù)據(jù)增量寫入等方面做了很多優(yōu)化饲嗽。
普通分布式中間件
大部分分布式中間件的架構(gòu)一般有以下三個(gè)部分:
客戶端:通常為MySQL5.7或8.0版本的客戶端,支持JDBC訪問奈嘿。
存儲(chǔ)層:由多個(gè)MySQL實(shí)例組成貌虾,引擎為InnoDB。
計(jì)算層(中間件層):組織并管理存儲(chǔ)層的MySQL實(shí)例裙犹,接受并解析客戶端傳來的SQL請(qǐng)求酝惧。計(jì)算層通常用片的概念把存儲(chǔ)層的MySQL分割,然后以片為單位進(jìn)行多副本來實(shí)現(xiàn)高可用伯诬。計(jì)算層顯式或隱式的有一個(gè)事務(wù)管理組件晚唇,負(fù)責(zé)給事務(wù)賦一個(gè)全局唯一的ID,這個(gè)組件是實(shí)現(xiàn)分布式事務(wù)一致性的一種重要的解決方案盗似。計(jì)算層對(duì)客戶端屏蔽多副本和事務(wù)ID哩陕,會(huì)對(duì)客戶端發(fā)來的普通SQL進(jìn)行拆分和改造,并生成分布式的執(zhí)行計(jì)劃赫舒,然后下發(fā)到存儲(chǔ)層的MySQL實(shí)例執(zhí)行悍及。
阿里OceanBase數(shù)據(jù)庫(kù)
OceanBase的總體架構(gòu)如下圖。
可以看到OceanBase主要由五部分組成:
客戶端:用戶使用OceanBase的方式和MySQL數(shù)據(jù)庫(kù)完全相同接癌,支持JDBC心赶、C客戶端訪問等。
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ǔ)法分析、查詢優(yōu)化等一系列操作后轉(zhuǎn)發(fā)給響應(yīng)的ChunkServer或者UpdateServer癣籽。如果請(qǐng)求的數(shù)據(jù)分布在多臺(tái)ChunkServer上挽唉,MergeServer還需要對(duì)多臺(tái)ChunkServer返回的結(jié)果進(jìn)行合并。
OceanBase借鑒了BigTable的做法筷狼,相比于普通的分布式中間件引入了UpdateServer這種增量更新機(jī)制瓶籽,在不需要使用兩階段提交的情況下實(shí)現(xiàn)了分布式事務(wù),這點(diǎn)下一篇分布式事務(wù)部分會(huì)詳細(xì)展開埂材。
第二代分布式數(shù)據(jù)庫(kù)——NoSQL
在早期分庫(kù)分表方案發(fā)展過程中塑顺,好多公司都面臨了因擴(kuò)容而無限次改造業(yè)務(wù)的痛苦。他們?cè)俅斡^察業(yè)務(wù)俏险,發(fā)現(xiàn)業(yè)務(wù)并不復(fù)雜——至少?zèng)]復(fù)雜到需要使用高級(jí)SQL的地步严拒。這樣NoSQL干脆就拋棄了高級(jí)SQL(分布式ACID特性),從而換來對(duì)業(yè)務(wù)透明的特性和強(qiáng)水平擴(kuò)展的能力竖独。
這樣做的好處顯而易見——只要你能忍受不用高級(jí)SQL這一點(diǎn)裤唠,那么你只要進(jìn)行一次到NoSQL的改造,后面就可以近乎無限的擴(kuò)容莹痢,無需任何業(yè)務(wù)的適配种蘸。
各種NoSQL,如HBase,Cassandra,Leveldb,RocksDB底層的數(shù)據(jù)結(jié)構(gòu)竞膳,都是LSM-Tree航瞭。
因?yàn)镹oSQL不支持分布式ACID特性,和其他分布式數(shù)據(jù)庫(kù)差別較大坦辟,所以不列入后面對(duì)事務(wù)的討論刊侯。
第三代分布式數(shù)據(jù)庫(kù)——NewSQL
上面的分庫(kù)分表、分布式中間件和NoSQL都不可避免的由一個(gè)業(yè)務(wù)侵入性的問題锉走,有些前沿廠家就產(chǎn)生了把二者結(jié)合起來滨彻,設(shè)計(jì)一個(gè)兼具分布式事務(wù)一致性和強(qiáng)可擴(kuò)展性的數(shù)據(jù)庫(kù)的想法——這就是NewSQL的誕生藕届。
在NewSQL領(lǐng)域,有兩個(gè)流派疮绷,分別是Amazon的Aurora和Google的Spanner。這兩者之前的區(qū)別實(shí)際上是非常大的嚣潜,所以我們?cè)诤笪闹幸舶阉麄兛醋鲀煞N完全不同的數(shù)據(jù)庫(kù)冬骚。
Aurora流派
Aurora流派也被稱作Shared Everything,目前這個(gè)流派懂算,多是被部署到虛擬計(jì)算環(huán)境中的云數(shù)據(jù)庫(kù)只冻,本文涉及的云數(shù)據(jù)庫(kù)有阿里的PolarDB,Amazon的Aurora以及華為云數(shù)據(jù)庫(kù)Taurus计技。
知乎上有個(gè)很有意思的問題:為什么AWS云計(jì)算服務(wù)是亞馬遜先做出來喜德,而不是Google?
這個(gè)問題的回答也都很專業(yè)垮媒,這里簡(jiǎn)單總結(jié)一下舍悯。Amazon的核心業(yè)務(wù)電子商務(wù)有太強(qiáng)的季節(jié)性,可以理解成睡雇,Amazon要維持的服務(wù)器數(shù)量是根據(jù)每年黑五的需求決定的萌衬,而一年的其他時(shí)間完全不需要這么多服務(wù)器。于是就誕生了AWS的想法它抱,也成為后來“云”這一概念的雛形秕豫。
另外還有一點(diǎn)就是兩者商業(yè)哲學(xué)的不同。Amazon更傾向于提供近似于水電的基礎(chǔ)設(shè)置服務(wù)观蓄,成本應(yīng)該越低越好混移,價(jià)格也應(yīng)該越低越好;而Google零幾年的時(shí)候主營(yíng)的業(yè)務(wù)廣告利潤(rùn)非常之高侮穿,并且Google一向只喜歡提供終端的服務(wù)歌径,既沒有壓力也沒有動(dòng)力去做云。
Aurora流派最重要的一個(gè)概念就是Log is Database亲茅。這個(gè)概念是把log寫到存儲(chǔ)層沮脖,由存儲(chǔ)層負(fù)責(zé)重放log、回寫page并盡量減少寫放大芯急。
下面一個(gè)表格列出了Aurora一系列數(shù)據(jù)庫(kù)的特性對(duì)比.
需要專門說明的一點(diǎn)是Aurora和PolarDB理念上的區(qū)分勺届。Aurora認(rèn)為網(wǎng)絡(luò)會(huì)成為云數(shù)據(jù)庫(kù)的瓶頸;PolarDB則認(rèn)為網(wǎng)絡(luò)傳輸速度會(huì)快速發(fā)展娶耍,后續(xù)軟件代碼(CPU)才是性能的瓶頸免姿。
這兩種思路的區(qū)別導(dǎo)向了兩種架構(gòu)。Aurora的設(shè)計(jì)是日志即數(shù)據(jù)榕酒,在保證日志落盤的前提下胚膊,盡量減少磁盤IO故俐,所以整個(gè)Aurora只寫一份Redo log到底層存儲(chǔ),由底層存儲(chǔ)來實(shí)現(xiàn)把rodo log‘恢復(fù)’成數(shù)據(jù)頁(yè)的行為紊婉;PolarDB則把數(shù)據(jù)頁(yè)和rodo log都寫入底層存儲(chǔ)药版,PolarDB的底層存儲(chǔ)PolarStore更像一個(gè)通用的高可用存儲(chǔ),不需要進(jìn)行類似Aurora一樣把Redo日志恢復(fù)出數(shù)據(jù)文件的操作喻犁。
從同行的表現(xiàn)來看槽片,后面一系列的云原生數(shù)據(jù)庫(kù)基本都跟進(jìn)了Aurora的架構(gòu),看起來還是Log is Database架構(gòu)更合理肢础。不過还栓,也有一種說法是PolarDB在早期沒有過分考慮技術(shù)的長(zhǎng)遠(yuǎn)性,而是直接選擇一種易實(shí)現(xiàn)的架構(gòu)來?yè)屨际袌?chǎng)传轰。從這種角度看剩盒,PolarDB是成功的。
華為云Taurus數(shù)據(jù)庫(kù)
我們這里以2020年六月份華為云Taurus在Sigmod上發(fā)表的論文來看一下Aurora流派的結(jié)構(gòu)慨蛙。下圖是Taurus的結(jié)構(gòu)圖辽聊。
可以看到Taurus主要由四部分組成:
客戶端:目前是一個(gè)改版的MySQL8.0;
SAL:全稱Storage Abstraciton Layer期贫,可以理解為存儲(chǔ)層的前端和存儲(chǔ)數(shù)據(jù)分布式管理組件身隐,負(fù)責(zé)DB引擎與存儲(chǔ)的Log Store/Page Store交互,同時(shí)也負(fù)責(zé)創(chuàng)建唯灵、管理贾铝、刪除Page Store的Slices以及管理page在Slices上的映射關(guān)系;
Log Store:負(fù)責(zé)持久化log以及為只讀實(shí)例提供log內(nèi)容埠帕;
Page Store:存儲(chǔ)真正的數(shù)據(jù)并為SQL前端提供page讀取服務(wù)垢揩,向SAL提供4個(gè)API:WriteLogs,ReadPage敛瓷,SetRecycleLSN叁巨,GetPersistentLSN。
阿里雙十一存儲(chǔ)引擎X-Engine
X-Engine是阿里專為雙十一設(shè)計(jì)的存儲(chǔ)引擎呐籽,因?yàn)槠涮厥庑苑嫔祝覀冞@里也簡(jiǎn)單介紹以下它的架構(gòu)。我們可以從2019年阿里發(fā)布的論文《X-Engine:An Optimized Storage Engine for Large-scale E_commerce Transaction Processing》中看到其具體的設(shè)計(jì)狡蝶。
X-Engine主要是為了解決雙十一面臨的三個(gè)問題而研發(fā)的庶橱,這三個(gè)問題是:
海嘯問題,活動(dòng)開始時(shí)每秒交易量(TPS)激增贪惹;
泄洪問題苏章,緩存很快被大量數(shù)據(jù)填滿;
訪問熱點(diǎn)急速變化問題,隨著促銷活動(dòng)的改變枫绅,數(shù)據(jù)的冷熱會(huì)發(fā)生迅速的切換泉孩。
這種特殊的場(chǎng)景使X-Engine相比于其他的分布式數(shù)據(jù)庫(kù)更加重視insert和update性能,從而使用了具有杰出寫入性能的LSM-Tree這種數(shù)據(jù)結(jié)構(gòu)并淋。
X-Engine的架構(gòu)見下圖寓搬。(大家可以對(duì)照上文普通LSM-Tree的結(jié)構(gòu)圖)
基于LSM-Tree分層存儲(chǔ)能夠做到寫的高吞吐,帶來的副作用是整個(gè)系統(tǒng)必須頻繁的進(jìn)行compaction县耽,寫入量越大句喷,Compaction操作越頻繁。而Compaction操作非常消耗CPU和IO酬诀,在高吞吐的情況下脏嚷,大量的Compaction操作占用大量系統(tǒng)資源骆撇,必然帶來整個(gè)系統(tǒng)性能斷崖式下跌瞒御,對(duì)應(yīng)用系統(tǒng)產(chǎn)生巨大影響。
X-Engine為了優(yōu)化這個(gè)問題神郊,引入了異構(gòu)硬件設(shè)備FPGA來代替CPU完成compaction操作肴裙,使系統(tǒng)整體性能維持在高水位并避免抖動(dòng),是存儲(chǔ)引擎得以服務(wù)業(yè)務(wù)苛刻要求的關(guān)鍵涌乳。
Spanner流派
Spanner流派也稱作Shared Nothing蜻懦。與分布式中間件不同的是,它是從分布式系統(tǒng)出發(fā)夕晓,再來做存儲(chǔ)宛乃,做查詢,利用天然的擴(kuò)展能力和列存的性能優(yōu)勢(shì)蒸辆,實(shí)現(xiàn)基于KV存儲(chǔ)的支持關(guān)系型查詢的數(shù)據(jù)庫(kù)征炼。如TiDB,就是一個(gè)NewSQL的商業(yè)化的實(shí)現(xiàn)躬贡。
我們對(duì)Spanner的所有了解都來自Google于2012年發(fā)表的論文《Spanner: Google’s Globally-Distributed Database》谆奥。
Spanner論文中有兩個(gè)點(diǎn)需要十分重視:一個(gè)是TrueTime API的實(shí)現(xiàn),給Spanner提供了全局的時(shí)鐘接口拂玻,在此基礎(chǔ)上Spanner才能實(shí)現(xiàn)強(qiáng)的全局一致性保證酸些;另一個(gè)是論文中對(duì)Spanner的分布式事務(wù)實(shí)現(xiàn)細(xì)節(jié)進(jìn)行了詳細(xì)的描述。第一點(diǎn)在本文中會(huì)有詳細(xì)的闡述檐蚜,第二點(diǎn)詳見下一篇分布式事務(wù)部分魄懂。
Spanner的總體(全球)架構(gòu)見下圖。
universe是Spanner的全球部署實(shí)例闯第,并被分成多個(gè)zone逢渔,zone是Spanner管理部署和物理隔離的單元。
一個(gè)zone包含一個(gè)zonemaster乡括,若干個(gè)location proxy肃廓,和一百至幾千個(gè)spanserver智厌。zonemaster把數(shù)據(jù)分配給spanserver,spanserver把數(shù)據(jù)提供給客戶端盲赊∠撑簦客戶端使用每個(gè)zone上面的location proxy來定位可以為自己提供數(shù)據(jù)的spanserver。
spanserver的架構(gòu)見下圖哀蘑。
每個(gè)spanserver負(fù)載管理了100到1000個(gè)tablet(BigTable提出的一種數(shù)據(jù)結(jié)構(gòu))诚卸,tablet實(shí)現(xiàn)了下面的映射:
(key:string,timestamp:int64) -> string
為了支持復(fù)制,每個(gè)spanserver會(huì)在每個(gè)tablet上面實(shí)現(xiàn)一個(gè)單個(gè)的Paxos狀態(tài)機(jī)绘迁。Paxos協(xié)議會(huì)選舉出一個(gè)領(lǐng)導(dǎo)者(上圖中中間的那個(gè)replica)合溺,寫操作必須在領(lǐng)導(dǎo)者上初始化Paxos協(xié)議,讀操作可以直接從底層任何副本的tablet中訪問狀態(tài)信息缀台,只要這個(gè)副本足夠新棠赛。副本的集合稱為一個(gè)Paxos group。
此外膛腐,Spanner實(shí)現(xiàn)分布式事務(wù)一致性是靠?jī)呻A段提交睛约,所以一個(gè)分布式事務(wù)還會(huì)選舉出一個(gè)participant leader。transaction manager就是用來實(shí)現(xiàn)participant leader的哲身。
lock table則用來實(shí)現(xiàn)并發(fā)控制辩涝,這個(gè)鎖表包含了兩階段鎖機(jī)制的狀態(tài):它把鍵的值域映射到鎖狀態(tài)上面。
下圖是Spanner TrueTime的三個(gè)API勘天。
TrueTime會(huì)顯式地把時(shí)間表達(dá)成TTinterval怔揩,這是一個(gè)時(shí)間區(qū)間,具有有界限的時(shí)間不確定性脯丝。
TT.now()返回的結(jié)果是當(dāng)前時(shí)間的一個(gè)閉區(qū)間[earliest,latest]商膊。用函數(shù)tabs(e)表示一個(gè)事件e的絕對(duì)事件,那么對(duì)于一個(gè)調(diào)用tt=TT.now()巾钉,TrueTime可以保證tt.earliest <= tabs(e) <= tt.latest翘狱。
底層上,TrueTime使用GPS和原子鐘兩種方式來獲取時(shí)間砰苍,增加可靠性潦匈。在Google的線上應(yīng)用環(huán)境中,TrueTime的誤差邊界是一個(gè)關(guān)于時(shí)間的鋸齒形函數(shù)赚导,在1到7ms之間變化茬缩,其中1ms來自網(wǎng)絡(luò)通訊延遲。