日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高阶数据结构:SSTable

發布時間:2025/4/16 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高阶数据结构:SSTable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 前言

最近在組會上面通過小組討論論文時,發現了SSTable這個數據結構。課后為了深入分析和學習這個數據結構,我做了一些資料查閱。在查詢相關分布式的書籍后,找到了SSTable的數據結構,現將其作為筆記記錄下來。之前整理的BigTable論文里面提及到了SStable,但是當時并沒有引起我的注意。現在將深入理解這個數據結構——SSTable。

2. SSTable的定義

Google SSTable文件格式在內部用于存儲Bigtable數據。 它的格式為文件本身就是一個排序的、不可變的、持久的Key/Value對Map,其中Key和value都可以是任意的byte字符串。提供操作以查找與指定鍵相關聯的值,并遍歷指定鍵范圍內的所有鍵/值對。使用Key來查找Value,或通過給定Key范圍遍歷所有的Key/Value對。每個SSTable包含一系列的Block(一般Block大小為64KB,但是它是可配置的),在SSTable的末尾是Block索引,用于定位Block,這些索引在SSTable打開時被加載到內存中,在查找時首先從內存中的索引二分查找找到Block,然后一次磁盤尋道即可讀取到相應的Block。還有一種方案是將這個SSTable加載到內存中,從而在查找和掃描中不需要讀取磁盤。

3. BigTable的架構

BigTalbe構建在GFS之上,為文件系統增加了一層分布式索引層。另外,BigTable依賴Google的Chubby(即分布式鎖)進行服務器選舉以及維護全局信息維護。

如圖,Bigtable將大表劃分為大小在100M~200M的子表(tablet),每個子表對應一個連續的數據范圍。Bigtable主要由三個部分組成:客戶端程序庫(client)、一共主控服務器(Master)和多個子表服務器(tablet server)。

  • 客戶端程序庫(Client):提供Bigtable到應用程序的接口,應用程序通過客戶端程序庫對表格的數據的單元進行增、刪、改、查等操作。客戶端通過Chubby鎖服務器獲取一些控制信息,但所有表格的數據內容都在客戶端與子表服務器之間進行傳輸。
  • 主控服務器(Master):管理所有的子表服務器,包括分配子表給子表服務器,指導子表服務器實現子表的合并,接收來自子表服務器的分裂信息,監控子表服務器,在子表服務器之間進行負載均衡并實現子表服務器的故障恢復。
  • 子表服務器(tablet server):實現子表的裝載/卸出、表格內容的讀和寫,子表的合并和分裂。Tablet Server服務的數據包括操作日志以及每個子表上的sstable數據,這些數據都存儲在底層的GFS中。

4. BigTable中的存儲引擎

Bigtable采用Merge-dump存儲引擎。數據寫入時需要先寫操作日志,成功后應用到內存中的MemTable中,寫操作日志是往磁盤中的日志文件追加數據,很好地利用了磁盤設備順序讀寫的特性。當內存中的MemTable達到一定大小,需要將MemTable轉儲(Dump)到磁盤中生成SSTable文件。由于數據同時存在MemTable和可能多個SSTable中,讀取操作需要按從舊到新的時間順序合并SSTable和內存中的MemTable數據。數據在SSTable中連續存放,因此可以同時滿足隨機讀取和順序讀取兩種需求。為了防止磁盤中的SSTable文件過多,需要定時將多個SSTable通過Compaction過程合并成一個SSTable,從而減少后續讀操作需要讀取的文件個數。一般情況下,如果寫操作比較少,我們總是能夠使得對每一份數據同時只存在一個SSTable和一個MemTable,也就是說,隨機讀取和順序讀取都只需要訪問一次磁盤。插入、刪除、更新、增加等操作在Merge-dump引擎中都看成一回事,除了最早生成的SSTable外,SSTable中記錄的只是操作,而不是最終的結果,需要等到讀取時才合并到最終結果。

Bigtable中包含三種Compaction策略:Minor Compaction、Merging Compaction和Major Compaction。其中,Minor Compaction把內存中的MemTable轉儲到GFS中,Merging Compaction和Major Compaction合并GFS中的多個SSTable文件生成一個更大的SSTable。Minor Compaction主要是為了防止內存占用過多,Merging和Major Compaction則是為了防止讀取文件個數過多。Merging Compaction和Major Compaction的區別在于Major Compaction會合并所有的SSTable文件和內存中的MemTable,生成最終結果;而Merging Compaction生成的SSTable文件可能包含一些操作,比如刪除、增加等。

5. SSTable的數據結構

數據在SSTable中按照主鍵有序存儲,每個SSTable由若干個大小相近的數據塊(Block)組成,每個數據塊包含若干行。數據塊的大小一般在8~64KB之間,允許用戶配置。Tablet Server的緩存包括兩種:塊緩存(Block Cache)和行緩存(Row Cache)。其中,塊緩存的單位為SSTable中的數據塊,行緩存的單位為一行記錄。隨機讀取時,首先查找行緩存;如果行緩存不命中,接著再查找塊緩存。另外,Bigtable還支持布隆過濾器(Bloom Filter),如果讀取的數據行在SSTable中不存在,可以通過布隆過濾器(Bloom Filter)發現,從而避免一次讀取GFS文件操作。注:布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率和刪除困難。

SSTable中的數據按主鍵排序后存放在連續的數據塊(Block)中,塊之間也有序。接著,存放數據塊索引,由每個Block最后一行的主鍵組成,由于數據查詢中的Block定位。接著,存放布隆過濾器和表格的Schema信息。最后,存放固定大小的Trailer以及Trailer的偏移位置。

SSTable數據存儲結構

  • Data Block:存放連續的數據塊
  • Block Index:存放連續的塊索引。描述一個data block,存儲著對應data block的最大Key值,以及data block在文件中的偏移量和大小
  • Bloom Filter:布隆過濾器(Bloom Filter),用于判斷讀取的數據是否在當前SSTable上。
  • Table Schema: 當前SSTable的表格Schema信息
  • Fixed Trailer:當前SSTable的Block Index的塊索引大小
  • Trailer Offset:當前SSTable的Block Index的塊索引在文件存儲下的偏移量

查找SSTable時,首先從子表的索引信息中讀取SSTable Trailer的偏移位置,接著獲取Trailer信息。根據Trailer中記錄的信息,可以獲取塊索引的大小和偏移,從而將整個塊索引加載到內存中。根據塊索引記錄的每個Block的最后一行的主鍵,可以通過二分查找定位到查找的Block。最后將Block加載到內存中,通過二分查找Block中記錄的行索引查找到相應的偏移量,然后查找到具體某一行Row X。本質上看,SSTable是一個兩級索引結構:塊索引以及行索引;而整個ChunkServer是一個三級索引結構:子表索引、塊索引以及行索引。

SSTable分為兩種格式:稀疏格式和稠密格式。

  • 稀疏格式:某些列可能存在,也可能不存在,因此,每一行只存儲包含實際值的列,每一列存儲的內容為:<列ID,列值>(<Column ID, Column Value>);
  • 稠密格式:每一行都需要存儲所有列,每一列只需要存儲列值,不需要存儲列ID,這是因為列ID可以從表格Schema中獲取。

5.1 舉例說明

假設有一張表格包含10列,列ID為1~10,表格中有一行的數據內容為:

那么,采用稀疏格式存儲,內容為:<2, 20>,??, 30>,<5, 50>,<7, 70>,<8, 80>;如果采用稠密格式存儲,內容為:null,20,30,null,50,null,70,80,null,null。

ChunkServer中的SSTable為稠密格式,而UpdateServer中的SSTable為稀疏格式,且存儲了多張表格的數據。另外,SSTable支持列組Cloumn Group,將同一個列組下的多個列的內容存儲在一起。列組是一種行列混合存儲模式,將每一行的所有列分成多個組(稱為列組),每個列組內部按行存儲。

當一個SSTable中包含多個表格/列組時,數據按照[表格ID,列組ID,行主鍵]([table_id, column group id, row_key])的形式有序存儲。

6. SSTable在BigTable中的相應操作

6.1 Tablet Serving

在新數據寫入時,這個操作首先提交到日志中作為redo紀錄,最近的數據存儲在內存的排序緩存memtable中;舊的數據存儲在一系列的SSTable 中。在recover中,tablet server從METADATA表中讀取metadata,metadata包含了組成Tablet的所有SSTable(紀錄了這些SSTable的元 數據信息,如SSTable的位置、StartKey、EndKey等)以及一系列日志中的redo點。Tablet Server讀取SSTable的索引到內存,并replay這些redo點之后的更新來重構memtable。

當寫操作到達tablet server時,tablet server將檢查其格式是否正確,以及發送方是否有權限執行該寫操作。通過從Chubby文件中讀取允許寫操作的權限列表來執行授權(這在Chubby客戶端緩存中幾乎總是命中)。有效的變動將寫入提交日志。Group Commit通過提交多個寫操作用于提高吞吐量[13,16]。提交寫入后,其內容將插入到memtable中。

在讀操作時時,完成格式、授權等檢查后,讀會同時讀取SSTable、memtable(HBase中還包含了BlockCache中的數據)并合并他們的結果,由于SSTable和memtable都是字典序排列,因而合并操作可以很高效完成。

6.2 Compaction

Bigtable中包含三種Compaction策略:Minor Compaction、Merging Compaction和Major Compaction。

  • Minor Compaction:隨著memtable大小增加到一個閥值,這個memtable會被凍住而創建一個新的memtable以供使用,而舊的memtable會轉換成一個SSTable而寫入到底層存儲GFS中,這個過程叫做minor compaction。這個minor compaction可以減少內存使用量,并可以減少日志大小,因為持久化后的數據可以從日志中刪除。在minor compaction過程中,可以繼續處理讀寫請求。

  • Merge Compaction:每次minor compaction會生成新的SSTable文件,如果SSTable文件數量增加,則會影響讀的性能,因而每次讀都需要讀取所有SSTable文件,然后合并結果,因而對SSTable文件個數需要有上限,并且時不時的需要在后臺做merging compaction,這個merging compaction讀取一些SSTable文件和memtable的內容,并將他們合并寫入一個新的SSTable中。當這個過程完成后,這些源SSTable和memtable就可以被刪除了。

  • Merge Compaction:如果一個merging compaction是合并所有SSTable到一個SSTable,則這個過程稱做major compaction。一次major compaction會將mark成刪除的信息、數據刪除,而其他兩次compaction則會保留這些信息、數據(mark的形式)。Bigtable會時不時的掃描所有的Tablet,并對它們做major compaction。這個major compaction可以將需要刪除的數據真正的刪除從而節省空間,并保持系統一致性。

6.3 SSTable的locality和In Memory

在Bigtable中,它的本地性是由Locality group來定義的,即多個column family可以組合到一個locality group中,在同一個Tablet中,使用單獨的SSTable存儲這些在同一個locality group的column family。HBase把這個模型簡化了,即每個column family在每個HRegion都使用單獨的HFile存儲,HFile沒有locality group的概念,或者一個column family就是一個locality group。

在Bigtable中,還可以支持在locality group級別設置是否將所有這個locality group的數據加載到內存中,在HBase中通過column family定義時設置。這個內存加載采用延時加載,主要應用于一些小的column family,并且經常被用到的,從而提升讀的性能,因而這樣就不需要再從磁盤中讀取了。

6.4 SSTable壓縮

客戶端可以控制是否壓縮locality group的SSTable,以及如果壓縮,則使用哪種壓縮格式。 用戶指定的壓縮格式將應用于每個SSTable塊(其大小可通過特定于位置組的調整參數來控制)。 盡管我們通過分別壓縮每個塊而損失了一些空間,但我們的好處是,可以讀取SSTable的一小部分而無需解壓縮整個文件。 許多客戶端使用兩遍自定義壓縮方案。 第一遍使用Bentley和McIlroy的方案[6],該方案在一個大窗口中壓縮長的公共字符串。 第二遍使用快速壓縮算法,該算法在一個小的16 KB數據窗口中查找重復項。 兩種壓縮過程都非常快-在現代機器上,它們的編碼速度為100-200 MB / s,解碼速度為400-1000 MB / s。

6.5 SSTable的讀緩存

為了提升讀的性能,Bigtable采用兩層緩存機制:

  • Scan Cache:Scan Cache是一個更高級別的緩存,它將SSTable接口返回的Key/Value緩存到tablet server code。
  • Block Cache:Block Cache對于傾向于讀取與其最近讀取的數據接近的數據的應用程序很有用(例如,順序讀取或對熱點行內同一locality group中不同列隨機讀取)

Block Cache是較低級的緩存,它緩存從GFS讀取的SSTables塊。 Scan Cache對于傾向于重復讀取相同數據的應用程序最有用。

6.6 Bloom Filter

前文有提到Bigtable采用合并讀,即需要讀取每個SSTable中的相關數據,并合并成一個結果返回,然而每次讀都需要讀取所有SSTable,自然會耗費性能,因而引入了Bloom Filter,它可以很快速的找到一個RowKey不在某個SSTable中的事實(注:反過來則不成立)。

7. SSTable設計成Immutable的好處

在SSTable定義中就有提到SSTable是一個Immutable的order map,這個Immutable的設計可以讓系統簡單很多:

關于Immutable的優點有以下幾點:

  • 在讀SSTable是不需要同步。讀寫同步只需要在memtable中處理,為了減少memtable的讀寫競爭,Bigtable將memtable的row設計成copy-on-write,從而讀寫可以同時進行。
  • 永久的移除數據轉變為SSTable的Garbage Collect。每個Tablet中的SSTable在METADATA表中有注冊,master使用mark-and-sweep算法將SSTable在GC過程中移除。
  • 可以讓Tablet Split過程變的高效,我們不需要為每個子Tablet創建新的SSTable,而是可以共享父Tablet的SSTable。
  • 總結

    以上是生活随笔為你收集整理的高阶数据结构:SSTable的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。