Bigtable_2 (MIT 6.824: Lec 3: Reading)

  • 2020 年 12 月 15 日
  • AI

從本篇文章開始,專欄將以《MIT 6.824:Distributes Systems》的課程邏輯出發,逐步更新課程內的全部內容,敬請關注,謝謝。

如果想要跟方便的查看課程的更新內容,也歡迎關注微信公眾號:《油麻酥愛學習愛健身》,微訊號:youmasu

除了MIT分散式課程的學習以外,公眾號還會不定期分享自己的健身經驗,包括,家庭自重健身,健身房增肌減脂,日常飲食營養等健身內容,再次謝謝大家。

一、性能測試

在執行性能測試時,我們定義Bigtable集群內,擁有N台tablet servers。每一次評估,N是可變的。每台tablet server都是1GB記憶體,都會往一個1786台機器組成的GFS里寫數據,每台GFS機器擁有2塊400GB的IDE硬碟。同時,我們使用與tablet server相同數量的client來模擬負載,確保client不會成為性能瓶頸。

物理機層面,每台物理機使用雙核Opteron 2GHz,足夠大的物理記憶體運行所有進程,一個千兆網卡。所有物理機配置在一個兩層樹狀的交換機網路中,匯聚交換機可用頻寬在100-200Gbps之間。同時,所有物理機處在同一個IDC環境,確保任意2台機器間的round-trip在1ms內。Tablet servers、master、test client和GFS都部署在上述的物理機上。每台物理機上都會部署一個GFS server。其他進程混合部署在任意機器上。

R是性能測試中Bigtable row keys的數量。通過對R的調節,保證在每個benchmark測試間,每個tablet server的讀寫數據都在1GB左右。

Sequential write的benchmark使用R個row keys,分別命名為[0, (R-1)]。整個row keys的空間被劃分至10N個相同大小的range。每個range的row key都通過中心調度器分配給N個client。一旦某個client完成了當前的range,將馬上處理下一個range。這個動態的任務分配是為了防止運行在client機器上的其他進程對當前性能測試的干擾。每個key都會被分配一個獨立、隨機、未壓縮的字元串作為value寫入。Random write的benchmark方法類似。除了在寫入前會將row key哈希後與R取模,可以在整個性能測試期間平分整個row space產生的寫入負載。

Sequential read的benchmark中,row key的生成方式和sequential read相同。但它主要是讀取row key上先前被寫入的字元串。Random read操作上也類似。

Scan的benchmark與Sequential read類似。但它主要使用Bigtable原生支援的API來遍歷一個row range上的全部value。主要為了減少整個benchmark上的RPC調用。

Random read(mem)的benchmark與random read類似。區別是所有要讀取的locality group一定都來自記憶體而不是GFS。因此,為了匹配機器的記憶體大小,從每台tablet server中讀取的數據量也從1GB調整至100MB。

下圖展示了所有benchmark在讀寫1000個位元組的value時,Bigtable的2個性能視角。表格展示了每台tablet server在每秒的性能。曲線展示了所有tablet server在每秒的性能。

1、單台tablet server的性能

即使每一次random read都只需要1KB的數據,都需要將一個64KB的SSTable block從GFS經由網路傳輸到tablet server的過程,所以它的性能最低,每秒只有1200次random read能力,這也對應Bigtable可以從GFS讀取75MB/s數據的能力。這個讀取能力可以打滿tablet的CPU和網卡。因此,大多數Bigtable應用會將SSTable block調小至8KB。

Sequential read的性能就好很多,因為從GFS讀取的64KB數據會被快取起來,滿足接下來63次sequential read的要求。

Random read(mem)就起飛了,畢竟每次讀取1KB的數據全部在記憶體中返回,完全不用從GFS中載入。

Random和Sequential write比random read就快多了,並且兩者的性能也大致相當。因為每個tablet server會先在一個commit log中的尾部寫入所有的write操作,接著再以流的形式分組提交至GFS。

Scan的效率也非常高,主要是因為一次client RPC調用就能返回大量的value。

2、擴容tablet server的性能

當我們將tablet server數從1擴容至500時,所有tablet server匯總的性能快速上升。比如,random read(mem)的性能就增加了300倍,整個性能測試的瓶頸主要在CPU上。

從圖表中也看到,性能的提升並非線性的。對大多數benchmark來說,當tablet server擴容至50時,單台的性能就出現跳水。這主要是因為不同的機器配置,導致在測試期間的負載不均衡,這通常來源於在同一台機器上混合部署的其他進程佔用的CPU和網路頻寬。Bigtable的負載均衡演算法也嘗試緩解,但不能徹底解決這個情況。主要是2個原因:一是rebalance會加劇tablet server不可用的隱患(每當一個tablet被移動時,都會有短暫地小於1秒的不可用狀態);二是基準測試本身的負載也會隨時間變化。

Random read展示了最差的擴容後性能。因為每當讀取1KB的數據就要從GFS中載入64KBd額數據,當機器擴容時,網路頻寬最先被打滿。

二、應用場景

截至到2006年8月,生產環境中總計有24500台tablet servers組成388個Bigtable集群。一部分是面向用戶產品使用,一部分是內部產學研的批處理使用,下圖展示了部分集群的部分參數。包括,Google分析、Google地球和個性化搜索。

三、經驗總結

在設計、實現、維護和支援Bigtable的過程中,有不少值得分享的實戰經驗。

1、經驗一

大型分散式系統對各種錯誤天然有種脆弱性。包括分散式協議中涉及的網路分區錯誤和失敗-停止錯誤在內,還存在各式各樣的錯誤情況。比如,記憶體或網路損壞,機器時鐘偏差,機器掛起,第三方系統bug(Chubby),GFS資源超限,計劃或非計劃的硬體維護等等。當這些錯誤發生次數越來越多,我們只能嘗試優化通訊協議以解決它們,比如在RPC通訊時使用checksumming。或者,拒絕相信三方系統做出的任何保證,比如Chubby操作只會返回一個給定錯誤集中的錯誤碼。

2、經驗二

對大型分散式系統而言,加入任何新特性前,一定要將其使用的場景考慮清楚。比如,一開始Bigtable計劃在API設計中加入通用的分散式事務機制,但經過業務方的仔細調研,發現絕大多數業務只需要Bigtable能保證單行事務即可。同時,對那些需要分散式事務的應用來說,他們最重要的需求是用Bigtable來維護二級索引,我們就設計了一種特殊的機制來滿足他們的要求。新的機制雖然沒有實現通用分散式事務,但它在滿足業務需求的同時,複雜性更低,效率更高,並且和優化過的跨數據中心replication的schema有更好的交互。

3、經驗三

實際使用中,對Bigtable本身和其client的「系統級監控「非常重要。比如,對RPC調用中的重要操作進行取樣,追蹤調用情況的詳細資訊。這能幫助我們解決tablet 數據結構中的鎖阻塞,向GFS提交Bigtable mutation的慢寫入,當METADATA tablet不可用時的訪問掛起。監控的另一個好處是可以跟蹤所有在Chubby中註冊的Bigtable集群。觀察它們的大小,查看它們的版本,監控它們的讀寫流量,是否存在非預期的大延時。

4、經驗四

最重要的經驗是,保持系統設計的簡單性。整個Bigtable的邏輯和錯誤處理程式碼加起來大致10萬行左右,這使得程式碼的維護和調試非常簡單。比如,在系統membership協議上,Bigtable的最初設計是:master周期性的向tablet server發布租約,tablet server在租約到期時kill掉自己。但這個協議在網路有問題時會嚴重降低可用性,同時對master的恢復時間非常敏感。因此,我們重新設計,並反覆修改了幾次協議才解決問題。但此時協議的複雜性非常高,並嚴重依賴Chubby的一個為人所不知且很少經過驗證的特性。我們花了大量的時間在驗證那些極其隱晦的corner case上,既要測試Bigtable還要測試Chubby,讓人暈頭轉向。最後,我們放棄了這個實現,轉而實現了一個更簡單的協議,該協議僅依賴一項Chubby中一個眾所周知的特性。

四、相關成果

Boxwood project提供了一系列的分散式協議,鎖和分散式chunk存儲,B-tree存儲,所以它在功能上和Chubby,GFS和Bigtable都有諸多重疊。但Boxwood的目標是提供一份構建分散式文件系統或資料庫的底層套件,但Google service則直接提供服務,可以供那些想存儲數據的客戶端直接使用。

當前已經有很多分散式存儲,比如CAN,Chord,Tapestry和Pastry,來解決廣域網中的各種網路問題,比如多變的頻寬,不可信的成員和經常性的重新配置,但這並不是Bigtable要擔心的問題。同時,去中心化的控制和拜占庭容錯也不是Bigtable的目標。

並且,使用B-tree和hash表構建的Key-Value數據存儲模型受限頗多。Key-Value pairs不應當僅僅被當做building block提供給開發者,Bigtable還支援稀疏的semi-structured數據。同時,它還可以使用非常簡單有效的flat-file表示,並通過類似locality group的方式允許用戶微調整個系統,而不用關注Bigtable本身。

一些資料庫提供商也開發了並行資料庫以支援並行存儲大數據,比如,Orable的Real Application Cluster使用共享磁碟(Bigtable使用GFS)和分散式鎖管理器(Bigtable使用Chubby)來存儲數據。IBM基於shared-nothing架構開發了DB2 Parallel Edition。跟Bigtable的tablet server一樣,每一個DB2 server僅對一個存儲在本地關係型資料庫表中的某些列負責。這2款產品都支援完整的關係型資料庫事務。

Bigtable使用locality groups實現了列式存儲資料庫,比如C-Store和Sybas IQ,SenSage,KDB+和MonetDB/X100中的壓縮演算法,以提高磁碟的讀性能。AT&T的Daytona資料庫則通過將垂直和水平數據拆分至flat files以實現較高的壓縮比。Locality groups並不支援CPU-cahce級別的優化,但這一點被Ailamaki做到了。

Bigtable使用memtable和SSTable來存儲tablet的更新,也與Log-Structured Merge Tree將更新存儲索引數據的方法類似。這2個資料庫都會將排序後的數據優先放在記憶體中,之後才寫入磁碟,同時,任何讀數據操作都要將記憶體和硬碟上的數據合併後返回。

C_Store和Bigtable有很多相似的特點:使用shared-nothing架構;有2種不同的數據結構:一種用做recent write,一種用來存儲long-lived數據;存在將數據在不同form間移動的機制。但它們的API有非常大的不同:C-Store的API更像一個「經過了讀優化的關係型資料庫「,而Bigtable則提供更底層的讀寫介面,並在設計上支援每台tablet server達到數千級別的TPS,適用於讀寫均敏感的業務。

相比前面介紹的其他DB,Bigtable的負載均衡器更簡單:不用考慮同一份數據多份copy的可能性;讓client告訴Bigtable,它需要的數據在磁碟還是記憶體中;沒有複雜的quey需要去執行或優化。

五、最後結論

Bigtable的介面設計是如此與眾不同,讓很多習慣了傳統的,擁有完整事務的關係型資料庫的業務很難適應。但事實是,已經有大量的Google應用開始使用Bigtable也足以說明Bigtable設計的合理性。尤其是那些追求高性能和高可用的業務來說,只需要增加機器,平行擴容即可滿足需求。

六、參考文章

鏈接:static.googleusercontent.com