BigTable讀書筆記

一、概述

     BigTable是一個分佈式的結構化的存儲系統,是一個分佈式的NoSQL數據庫,本質上就是一個分佈式的B+樹索引。適於存儲結構化半結構化的海量數據(通常是分佈在數千臺服務器上的PB級數據)。

二、數據模型

     BigTable是一個稀疏的、分佈式的、持久化存儲的多維度排序Map
          稀疏:各個row可以包含不同的column key,不需要保持一致
          分佈式:基於range的數據分佈
          持久化存儲:持久化到磁盤
          多維度:每個row可以包含多個column
     Map的key是行關鍵字、列關鍵字以及時間戳,value是byte數組:
          (row:string, column:string, time:int64) -> string

     行:BigTable通過行關鍵字的字典順序組織數據。按照行關鍵字的範圍(range)對數據進行劃分,每個range稱作Tablet。Tablet是數據分佈和負載均衡調整的最小單位,在BigTable運行過程中,Tablet會分裂或者合併。

     行存儲的位置相關性:row key前綴相同的行會相鄰存儲,所以range scan可以搜索到相同前綴的所有行。

     列族:是訪問控制的基本單位,由所有列關鍵字組成的集合表示。存放在同一列族下的所有數據通常屬於同一個類型(壓縮比例高)。列族必須事前創建,然後可以存放任意的列關鍵字。
     列族不能創建的太多,最多幾百個。通常,每個列族會對應一個SSTable。
     列關鍵字:列族:限定詞
     
     時間戳:表的每一項可以包含同一份數據的不同版本,不同版本通過時間戳索引。數據項中不同版本的數據按照時間戳倒序排列。
     列族具有兩個參數,BigTable通過這兩個參數(保持最後n個版本或者是最近一段時間)對廢棄版本的數據自動進行垃圾收集。

三、Building Block

     1. 使用GFS存儲日誌文件和數據文件
     2. 使用SSTable文件持久化存儲數據
          SSTable是一個持久化的排序的不可更改的Map結構
          支持操作:(1) get key (2) key range scan
          文件格式:有一系列數據塊(通常塊大小64KB,可配)組成;由塊索引(通常處於文件最後)定位數據塊。
          在打開SSTable文件時,塊索引被加載到內存,每次查找可以通過一次磁盤搜索完成:首先二分查找在內存中的塊索引找數據塊的位置,然後再從硬盤讀取相應的數據塊。
     3. 分佈式協調(鎖)服務Chubby(高可用)
          Chubby提供類似文件目錄樹的名稱空間,每個目錄或文件可以當成一把鎖,讀寫文件的操作是原子的。
          BigTable使用Chubby完成以下功能:(存儲元數據、分佈式鎖、服務器上下線)
               (1)Master選擇
               (2)存儲BigTable數據的自引導指令的位置(Root Table位置)
               (3)查找Tablet服務器,以及在Tablet服務器失效時進行善後
               (4)存儲BigTable的模式信息以及訪問控制列表

五、實現

     BigTable包括三個主要的組件:鏈接到客戶程序的lib、一個Master服務器和多個Tablet服務器
     1. Master服務器負責:
          (1)爲Tablet服務器分配Tablet
          (2)檢測新加入或者過期失效的Tablet服務器
          (3)對Tablet服務器進行負載均衡
          (4)對保存在GFS上的文件進行垃圾收集
          (5)處理模式信息的修改(新建表、列族及訪問控制信息)

     2. Tablet服務器負責管理一個Tablet集合(通常每個服務器有大約數十個至上千個Tablet)。Tablet服務器負責處理它所加載的Tablet的讀寫操作,以及分裂和合並。

     3. Tablet Location 
          BigTable使用類似B+樹的結構存儲Tablet的位置信息。
          第一層是Chubby中的自引導信息,指向Root Tablet。
          第二層是Root Tablet,其中的每一個Row指向一個MetaData Tablet。
          第三層是MetaData Tablet,其中每一個Row指向一個存放數據的Tablet,Row key由該Tablet所在的表名和該Tablet最後一行組成。MetaData的每一行數據大小大約是1KB。
          其中MetaData和Tablet可以自動分裂,Root Table永遠不會被分裂,保證索引信息永遠不超過三層。

          客戶端會緩存Tablet的位置信息,當緩存爲空時,需要三次網絡通信。當緩存過期時,最多需要六次網絡通信。
          
      4. Table分配
          任何時刻、一個Tablet只能分配給一個Tablet服務器。Master服務器跟蹤記錄當前活躍的Tablet服務器,Tablet的分配狀態以及未分配的Tablet。在需要時,進行Tablet的分配。
          當啓動一個Master服務器時,需要執行以下步驟獲取系統當前狀態信息,爲Tablet分配作準備:
               (1)從Chubby獲取Master鎖,阻止創建其他的Master實例
               (2)掃描Chubby服務器文件鎖存儲目錄,獲取當前正在運行的Tablet服務器列表
               (3)和所有正在運行的Tablet服務器通信,獲取每個Tablet服務器上的Tablet分配信息
               (4)掃描MetaData表獲取所有的Tablet集合,若發現未分配的Tablet,則將其加入未分配Tablet集合,等待合適的機會分配
     
     5. Tablet服務
          Tablet的持久化信息(redo log和SSTable)存儲在GFS上。
          BigTable通過Redo Log進行故障恢復,當執行一個更新操作時,首先會先寫Redo Log,成功後,再修改內存數據結構memtable。當memtable大小達到某個閾值後,爲了減少內存消耗,會進行compaction操作,將memtable轉換成SSTable,同時記錄下Redo Point。
          當恢復一個Table時,Tablet服務器首先從MetaData表中讀取元數據(SSTable文件列表,Redo Log以及一系列Redo Point)。Table服務器把SSTable的塊索引加載到內存,然後從Redo Point之後對Redo Log進行replay,從而構建memtable。
          進行讀寫操作時會先進行權限驗證,一個讀操作需要讀取所有的SSTable的memtable的結果進行合併。

     6. Compaction
          minor compaction:memtable -> SSTable
          major compaction:memtable + SSTable -> SSTable
          minor compaction主要是兩個目的:減少Tablet使用的內存,減少Tablet恢復時讀取的log量。
          major compaction可以減少文件佔用的空間,同時可以回收已經刪除的數據佔用的資源。

六、優化

     1. Locality groups
          客戶端可以將多個列族組合成Locality group,在每個Tablet服務器上Locality group會使用一個獨立的SSTable。
          可以將經常一起讀取的列族組合成Locality group,而不需要同時訪問的列族使用不同的Locality group,提高讀取效率。

          可以爲Locality group設置調優參數,比如,可以把一個Locality group全部存儲在內存中


     2. Compression

          客戶端可以控制一個Locality group對應的SSTable是否需要壓縮。如果壓縮,需要指定壓縮算法,將SSTable中的每個塊單獨壓縮。


     3. Caching
          爲提高性能,Tablet服務器使用二級緩存策略。Scan Cache是第一級,緩存從SSTable接口返回的K-V對。Block Cache是第二級,緩存從GFS讀取的Block。
          對於重複使用相同數據的應用,Scan Cache很有用。

          Block Cache對於數據局部性更有用(比如,順序掃描)


     4. Bloom filter

          Bloom filter用於確定集合是否存在某個元素。在執行讀操作時,需要讀取所有SSTable中的數據,如果SSTable不在內存,則需要多次訪問磁盤。通過引入Bloom filter減少磁盤訪問次數。使用Bloom filter查詢SSTable中是否包含指定行和列的數據,如果不存在則不需要讀磁盤。


     5. Commit log的實現
          BigTable爲減少GFS併發寫,以及ChunkServer上的disk seek,爲每個Tablet服務器上所有的Tablet維護一個commit log,將對所有Tablet的修改操作順序追加到同一個log。
          使用這種方式可以提高普通操作性能,但是恢復工作變複雜了。如果一個Tablet服務器宕機了,那麼其上的所有Tablet會被分配到其他多個Tablet服務器,這些服務器爲了恢復,需要將commit log讀多次,同時因爲包含了很多冗餘信息,也浪費了讀效率。

          爲避免多次讀取日誌文件,BigTable首先會把log按照關鍵字(table, row name, log seq num)排序,使得相同table的log相鄰排列,保證對同一tablet的修改連續存放在一起。在恢復時,只需一次seek操作,然後順序讀即可。爲了加快排序,排序會並行進行。


     6. Speeding up tablet recovery
          當master觸發table遷移時,如不進行優化,目的Tablet服務器需要進行commit log的replay,導致遷移時間很長。爲了避免這種情況,源Tablet服務器會進行兩次minor compaction,消除所有的commit log。
          第一次minor compaction大量減少commit log,執行期間讀寫操作繼續。完畢之後,會停止讀寫操作,執行第二次minor compaction,此次的commit log量很少,所以暫停時間很短。

          兩次minor compaction大幅減少暫停時間


     7. 利用不變性
          除了SSTable cache(memtable)外,其他的SSTable都是不變的,所以並行讀操作不需加鎖。
          memtable使用Copy on Write,減少讀寫競爭。
          SSTable的不變性是的Tablet分裂非常便捷,只需讓分裂的Tablet共享原有的SSTable集合即可。
發佈了119 篇原創文章 · 獲贊 69 · 訪問量 126萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章