導讀:本文根據Google最新Megastore論文翻譯而來,原作者為Google團隊,團隊人員包括:Jason Baker,Chris Bond,James C.Corbett,JJ Furman,Andrey Khorlin,James Larson,Jean-Michel Léon,Yawei Li,Alexander Lloyd,Vadim Yushprakh。翻譯者為國內知名IT人士。
在上個月舉行的創(chuàng)新數據系統研討會上(CIDR),Google公開了其Megastore分布式存儲技術的白皮書。
Megastore是谷歌一個內部的存儲系統,它的底層數據存儲依賴Bigtable,也就是基于NoSql實現的,但是和傳統的NoSql不同的 是,它實現了類似RDBMS的數據模型(便捷性),同時提供數據的強一致性解決方案(同一個datacenter,基于MVCC的事務實現),并且將數據 進行細顆粒度的分區(qū)(這里的分區(qū)是指在同一個datacenter,所有datacenter都有相同的分區(qū)數據),然后將數據更新在機房間進行同步復制 (這個保證所有datacenter中的數據一致)。
Megastore的數據復制是通過paxos進行同步復制的,也就是如果更新一個數據,所有機房都會進行同步更新,因為使用paxos進行復制, 所以不同機房針對同一條數據的更新復制到所有機房的更新順序都是一致的,同步復制保證數據的實時可見性,采用paxos算法則保證了所有機房更新的一致 性,所以個人認為megastore的更新可能會比較慢,而所有讀都是實時讀(對于不同機房是一致的),因為部署有多個機房,并且數據總是最新。
為了達到高可用性,megastore實現了一個同步的,容錯的,適合長距離連接的日志同步器
為了達到高可擴展性,megastore將數據分區(qū)成一個個小的數據庫,每一個數據庫都有它們自己的日志,這些日志存儲在NoSql中
Megastore將數據分區(qū)為一個Entity Groups的集合,這里的Entity Groups相當于一個按id切分的分庫,這個Entity Groups里面有多個Entity Group(相當于分庫里面的表),而一個Entity Group有多個Entity(相當于表中的記錄)
在同一個Entity Group中(相當于單庫)的多個Entity的更新事務采用single-phase ACID事務,而跨Entity Group(相當于跨庫)的Entity更新事務采用two-phase ACID事務(2段提交),但更多使用Megastore提供的高效異步消息實現。需要說明的一點是,這些事務都是在同一個機房的,機房之間的數據交互都 是通過數據復制來實現的。
傳統關系型數據庫使用join來滿足用戶的需求,對于Megastore來說,這種模型(也就是完全依賴join的模型)是不合適的。原因包括
1.高負載交互性型應用能夠從可預期的性能提升得到的好處多于使用一種代價高昂的查詢語言所帶來的好處。
2.Megastore目標應用是讀遠遠多于寫的,所以更好的方案是將讀操作所需要做的工作轉移到寫操作上面(比如通過具體值代替外鍵以消除join)
3.因為megastore底層存儲是采用BigTable,而類似BigTable的key-value存儲對于存取級聯數據是直接的
所以基于以上幾個原因,Megastore設計了一種數據模型和模式語言來提供基于物理地點的細顆粒度控制,級聯布局,以及申明式的不正規(guī)數據存儲來幫助消除大部分joins。查詢時只要指定特定表和索引即可。
當然可能有時候不得不使用到join,Megastore提供了一種合并連接算法實現,具體算法這里我還是沒弄清楚,原文是[the user provides multiple queries that return primary keys for the same table in the same order; we then return the intersection of keys for all the provided queries.]
使用Megastore的應用通過并行查詢實現了outer joins。通常先進行一個初始的查詢,然后利用這個查詢結果進行并行索引查詢,這個過程我理解的是,初始查詢查出一條數據,就馬上根據這個結果進行并行 查詢,這個時候初始查詢繼續(xù)取出下一條數據,再根據這個結果并行查詢(可能前面那個外鍵查詢還在繼續(xù),使用不同的線程)。這種方法在初始查詢數據量較小并 且外鍵查詢使用并行方式的情況下,是一種有效的并且具有sql風格的joins。
Megastore的數據結構介于傳統的RDBMS和NoSql之間的,前者主要體現在他的schema表示上,而后者體現在具體的數據存儲上 (BigTable)。和RDBMS一樣,Megastore的數據模型是定義schema中并且是強類型的。每一個schema有一個表集合,每個表包 含一個實體集合(相當于record),每個實體有一系列的屬性(相當于列屬性),屬性是命名的,并且指定類型,這些類型包括字符串,各種數字類型,或者google的protocol buffer。這些屬性可以被設置成必需的,可選的,或者可重復的(一個屬性上可以具有多個值)。一個或者多個屬性可以組成一個主鍵。
在上圖中,User和Photo共享了一個公共屬性user_id,IN TABLE User這個標記直接將Photo和User這兩張表組織到了同一個BigTable中,并且鍵的順序(PRIMARY KEY(user_id,photo_id)?是這個還是schema中定義的順序?)保證Photo的實體存儲在對應的User實體鄰接位置上。這個機 制可以遞歸的應用,加速任意深度的join查詢速度。這樣,用戶能夠通過操作鍵的順序強行改變數據級聯的布局。其他標簽請參考原文。