圖2-24是Megastore的基本架構(gòu),最底層的數(shù)據(jù)是存儲在Bigtable中的。不同類型的副本存儲不同的數(shù)據(jù)。在Megastore中巧有三種副本,分別是完整副本(Full Replica)、 見證者副本(Witness Replica)和只讀副本(Read-only Replica)。圖2-24中出現(xiàn)了兩種副本,分別是完整副本A和B,以及見證者副本C。對于完整副本,Bigtable中存儲完整的日志和數(shù)據(jù)。見證者副本的作用是在Paxos算法執(zhí)行過程中無法產(chǎn)生一個(gè)決議時(shí)參與投票,因此對于這種副本,Bigtable只存儲其日志而不存儲具體數(shù)據(jù)。最后一種只讀副本和見證者副本恰恰相反,它們無法參與投票。它們的作用只是讀取到最近過去某一個(gè)時(shí)間點(diǎn)的一致性數(shù)據(jù)。如果讀操作能夠容忍這些過期數(shù)據(jù),只讀副本能夠在不加劇寫延遲的情況下將數(shù)據(jù)在較大的地理空間上進(jìn)行傳輸。

Megastore的部署需要通過一個(gè)客戶端函數(shù)庫和若干的服務(wù)器。應(yīng)用程序連接到這個(gè)客戶端函數(shù)庫,這個(gè)函數(shù)庫執(zhí)行Paxos算法。圖2-24中還有一個(gè)稱為協(xié)調(diào)者的服務(wù),要想理解這個(gè)服務(wù)的作用,首先來了解下Megastore中提供的快速讀(Fast Reads)和快速寫 (FastWrites)機(jī)制。
1.快速讀
如果讀操作不需要副本之間進(jìn)行通信即可完成,那么讀取的效率必然相對較高。由于寫操作基本上能在所有的副本上成功,一旦成功認(rèn)為該副本上的數(shù)據(jù)都是相同的且是最新的,就能利用本地讀取(Local Reads)實(shí)現(xiàn)快速讀,能夠帶來更好的用戶體驗(yàn)及更 低的延遲。確保快速讀成功的關(guān)鍵是保證選擇的副本上數(shù)據(jù)是最新的。為了達(dá)到這一目標(biāo),設(shè)計(jì)團(tuán)隊(duì)引入了協(xié)調(diào)者的概念。協(xié)調(diào)者是一個(gè)服務(wù),該服務(wù)分布在每個(gè)副本的數(shù)據(jù)中心里面。它的主要作用就是跟蹤一個(gè)實(shí)體組集合,集合中的實(shí)體組需要具備的條件就 是它們的副本已經(jīng)觀察到了所有的Paxos寫。只要出現(xiàn)在這個(gè)集合中的實(shí)體組,它們的副本就都能夠進(jìn)行本地讀取,也就是說能夠?qū)崿F(xiàn)快速讀。協(xié)調(diào)者的狀態(tài)是由寫算法來保證。
2.快速寫
為了達(dá)到快速的單次交互的寫操作,Megastore釆用了一種在主/從式系統(tǒng)中常用的優(yōu)化方法。如果一次寫成功,那么下一次寫的時(shí)候就跳過準(zhǔn)備過程,直接進(jìn)入接受階段。因?yàn)橐淮纬晒Φ膶懸馕吨矞?zhǔn)確地獲知了下一個(gè)日志的位置,所以不再需要準(zhǔn)備階段。 Megastore沒有使用專門的主服務(wù)器,而是使用leaders。系統(tǒng)在每一個(gè)日志位置都運(yùn)行一個(gè)Paxos算法實(shí)例。leader主要是來裁決哪個(gè)寫入的值可以獲取0號提議。第一個(gè)將值提交給leader的可以獲得一個(gè)向所有副本請求接收這個(gè)值作為0號提議最終值的機(jī)會。其他的值就需要重新使用Paxos算法。
由于寫入者在提交值給其他副本之前必須要和leader通信,為了盡可能地減少延遲, Megastore做了一個(gè)簡單的優(yōu)化,即在提交值最多的位置附近選擇一個(gè)副本作為leader。
客戶端、網(wǎng)絡(luò)及Bigtable的故障都會導(dǎo)致一個(gè)寫操作處于不確定的狀態(tài)。圖2-24中的復(fù)制服務(wù)器會定期掃描未完成的寫入并且通過Paxos算法提議沒有操作的值(No-op Values)來讓寫入完成。