hdfs本身是不支持文件隨機插入數據。那麼hbase中隨機寫入記錄,在hdfs中是怎麼實現的呢?
01-16
可能說得不清楚,更明確的情況是修改數據。hdfs是不支持對文件中部分數據進行修改的。但hbase需要對記錄進行增刪改查操作,那麼hbase需要修改某個記錄的某個欄位時,需要對hdfs中相應的數據存儲文件進行什麼樣的操作呢?
其實HBase/LevelDB等系統,背後都應用了Log-structured merge tree。HBase的寫操作有兩個步驟:1) 寫入HLog(防止宕機丟失數據), 2) 寫入對應的Memstore(內存)。當Memstore寫滿時,其中的數據被flush到HDFS,形成一個新的數據文件(HFile)。簡單的講,HBase的update/delete操作並不影響先前寫入的欄位,update只是對同一個key增加了一條記錄,而delete只是將某個key標記為刪除。由於HBase的數據文件是按key/column/timestamp有序的,所以讀取時只要按照某種策略,可能只需要讀取少數的數據文件(HFile)就能讀取到對應key的最新狀態。而系統提供了major comaction操作,該操作用於將對應列族的所有HFile合併為一個HFile,並刪除TTL過期的數據,多餘的版本,以及刪除的數據。總之,LSM在某種程度上將隨機寫轉化為順序寫,這也是HBase寫性能及其優秀的原因。
搜一下LSMtree的論文,hbase/leveldb都是基於log structrued merge tree的數據結構,類似log方式,單個文件內只有追加寫,定期把不同數據塊merge為新文件。
hbase 底層的存儲是採用了一個keyvalue的文件結構,稱作hfile來實現的;hbase的隨機寫入並不是立刻寫入hdfs;而是先寫入內存memstore,當memstore達到一定的閥值後才會寫入hdfs;而且hbase的後台還有compaction 運行;compaction將memstore刷到hdfs的小文件合併成大文件;其實關於這些信息網上有很多,可以搜索關鍵字hbase結構,hbase compaction 有很詳細的解答
在HBase中修改某個欄位的值:這個值對應在HBase中是存在一個叫cell的小格子,每個cell都有自己的版本,你可以在HBase配置文件中指定可以保留幾個版本的值。我們如果修改這個cell的值,只需重新put就可以了,意思就是又生成了一個新的版本的值。下次查的時候他會把最新的版本號的值返回來了,但其實他還保留著這個cell的舊版本的值。
lsm
LSM,數據先寫內存,達到閾值刷盤,刷盤即HFile,HFile是不可變,內部有序的。讀的時候 多個HFile以及Memstore和BlockCache最小堆讀取!
這裡要提到HFile的存儲格式,每一個單元格或者KeyValue在HFile中的格式如下:row length + row key + family length + column family + column qualifier + timestamp + key type對於更新操作來說,會重新插入一條新的數據而不是在原來數據上修改。新的數據的timestamp會大於老的數據,這樣讀取的時候,判斷時間戳就可以取出最新的數據了。對於刪除操作來說,會插入一條新的數據,但是key type會標記成Delete狀態。同樣,讀取的時候如果取到了是Delete,而且時間是最新的,那麼這條記錄肯定是被刪掉了。所以這種設計模式也是合併操作產生的原因。但是需要注意的是,只有大合併操作才會drop掉臟數據(老數據)
helpful
hbase的添加修改刪除操作本質都是添加操作,而hbase的數據模型是多維排序的結構,數據put或者delete得時候會自動添加時間戳,先存儲的記錄會刷寫到region下生成一個hfile文件,而後存儲的數據,修改或者刪除的操作又會刷寫生成新的hfile文件,查詢請求的時候,會讀取兩個文件然後根據數據的時間戳返回最新的記錄
問題很不錯,長知識了
不需要立即寫入hdfs,先寫內存,內存滿了再寫hdfs。這樣一方面可以提高寫的性能,另一方便可以進行排序。寫入到hdfs上的數據是需要按照rowkey進行排序的
推薦閱讀:
※region HFile DataNode 三者的區別與關係?
※hbase 基於rowkey 模糊查詢 如何做效率高?
※mongodb,redis,hbase 三者都是nosql資料庫,他們的最大區別和不同定位是什麼?
※為什麼說HBase是列式資料庫?
※HBase讀性能怎麼樣?