HBase,全稱Hadoop資料庫,是乙個分布式、可擴充套件、面向列集群的資料庫,是一種分布式資料庫解決方案,通過大量廉價的機器解決海量資料的高速儲存和讀取問題。 這篇文章會像剝洋蔥一樣,一層一層地剝開她的心。
首先,我們來看看HBase的特點:
效能。 基於LSM樹的資料結構設計,保證了順序寫入,並通過Bloom濾波、Compaction等內部優化方法優化了讀取效能,使HBase具有較高的讀寫效能。
可靠性高。 HBase在寫入資料之前寫入WAL預寫日誌,以防止計算機宕機時記憶體中的資料丟失。
易於擴充套件。 底層依賴HDFS,當磁碟空間不足時,可直接水平擴容。
稀疏。 稀疏性是HBase的乙個突出特點,在其他資料庫中,null值一般都是用null填充的,而對於百萬列的表,通常有大量的null值,如果採用填充null的策略,必然會造成大量的空間浪費。 對於 HBase 空值,不需要填充,因此稀疏性是 HBase 列可無限擴充套件的重要條件。
列群集儲存。 使用集群儲存,使用者可以自由選擇將哪些列放入同一集群中。
多個版本。 HBase支援多版本儲存資料,支援按時間戳排序。 使用者可以根據需要選擇最新版本或歷史版本。
如前所述,HBase 符合列群集儲存。 為了儲存資料,我們首先比較一下基於行的儲存、列式儲存和列集群儲存之間的區別。
行儲存
傳統的關聯式資料庫是按行儲存的,這意味著每一行資料都儲存在一起。
列式儲存
資料儲存在列中,即每列資料儲存在一起。 基於列的儲存有哪些優勢?
1.您可以節省儲存空間並僅儲存有用的內容,這些內容需要作為 null 值進行處理,以便進行行儲存,但不能作為列儲存的 null 值進行處理。
2.每列型別一致,當資料落到磁碟時,可以獲得更好的資料壓縮效率。
3.大多數情況下,我們再次查詢時不需要查詢整個表的所有列,只會使用部分列,但是由於是基於行的儲存方式,每次都必須查詢出所有字段,才能過濾出我們需要的字段。 但按列儲存就不一樣了,就好比吃自助餐,按需查詢,只查詢需要的東西,明顯減少了磁碟io。
列群集儲存。
那麼什麼是列集群儲存呢?對於欄位較多的表,如果為查詢設計的列數過大,必然會造成磁碟IO過大,從而影響查詢效能。 列簇儲存是指乙個列簇下可以儲存多個列,每個列簇可以儲存在乙個檔案中,這樣可以減少一些磁碟IO,提高查詢效能。
每個列簇的資料都儲存在一起,每個列簇可以自由選擇要儲存的列。 因此,列集群儲存實際上為使用者提供了乙個自由選擇,如果將所有列都放到乙個列集群中,實際上相當於按行儲存,每個查詢都需要找出所有列,如果每個列單獨儲存乙個列集群,則類似於按列儲存。
在目前的系統中,不建議設定過多的列簇,後面會提到,因為重新整理時 memstore 的最小單位不是 memstore,而是整個區域,所以設定過多的列簇會非常耗能,但這種架構會演變成 htap(混合事務和分析)系統,為系統提供了最核心的基礎。
HBase 架構分為三個部分:Zookeepper 集群、hmaster 和區域伺服器。 架構圖看起來很複雜,但核心是區域伺服器,然後會從區域伺服器 -> region ->store ->hfile-> 資料塊中移除。
ZooKeeper是一種分布式的無中心元資料儲存服務,用於檢測和記錄HBase集群中伺服器的狀態資訊。
客戶端會先訪問 zk,查詢 hbase:meta 表資訊,並將 hbase:meta 表資訊快取在客戶端上,以提高查詢效能。
HBaster是HBase的佼佼者,不參與具體表資料的管理,只負責巨集控,主要有兩大任務,一是管理區域伺服器,二是執行一些高風險操作,如DDL(建表、刪除表等)。
HBase Master的特點:
監控所有區域伺服器的狀態,並在集群處於資料恢復狀態或動態調整負載時將區域分配給區域伺服器。
提供DDL相關介面,支援建立、刪除、更新表結構。
區域伺服器是整個 Habse 架構的核心模組,負責讀取和寫入實際資料,當訪問資料時,客戶端直接與 HBase 區域伺服器通訊。
HBase 的表根據行鍵區域劃分為多個區域,乙個區域包含該區域中的所有資料。 乙個區域伺服器負責管理多個區域,並負責區域伺服器上所有區域的讀寫操作,乙個區域伺服器最多可以管理1000個區域。
如果伺服器既是區域伺服器又是 HDFS 資料節點,則每個區域伺服器在 HDFS 中儲存自己的資料然後,區域伺服器的資料將儲存在本地 HDFS 中,以加快訪問速度。
但是,如果是新遷移的區域伺服器,則沒有區域伺服器資料的本地副本。 在 HBase 執行壓縮之前,副本將遷移到本地資料節點。
RegionServer 主要用於響應使用者 IO 請求,是 HBase 的核心模組,由 WAL(hlog)、blockcache 和多個區域組成。
hlog 實際上是乙個 WAL(write-ahead-log)預寫日誌,在寫入 memstore 之前先寫入 hlog 進行資料備份,hlog 儲存在磁碟上以保證高可靠性。 hlog 位於區域伺服器級別,這意味著整個區域伺服器共享乙個 hlog。
hlog 在 HBase 中有兩個函式:
當區域伺服器宕機時,仍在記憶體中且未寫入磁碟的資料不會丟失,仍可以通過 hlog 恢復。
用於實現HBase集群之間的主從複製,通過播放Master集群推送的hlog日誌來實現主從複製。
hlog 的日誌檔案存放在 HDFS 中,HBase 集群預設會在 HDFS 上建立乙個 HBase 資料夾,該資料夾下有乙個 WAL 目錄,用於存放所有相關的 hlog,並且 hlog 不會永久存在,整個 HBase 的總 hlog 會經過以下過程:
1.發生寫入操作時,首先構建 hlog。
2.因為 hlog 會不斷追加,整個檔案會越來越大,所以需要支援滾動日誌檔案儲存,所以 hbase 後台每隔一段時間(預設一小時)就會生成乙個新的 hlog 檔案,歷史 hlog 會被標記為歷史檔案。
3.一旦資料進入磁碟並形成 hfile,hlog 中的資料就不需要存在了,因為 hfile 儲存在 hdfs 中,而 hdfs 檔案系統保證了它的可靠性,所以當 hlog 中的資料登陸磁碟時,hlog 就會失效,對應的操作就是將檔案從 wal 移動到 oldwal 目錄下, 並且該檔案此時仍然存在,不會被刪除。
4.HBase 有乙個後台程序,預設每分鐘預設一次失效日誌檔案,如果沒有引用操作,該檔案將從物理體中完全刪除。
HBase 將從 hfile 查詢到的資料快取到 BlockCache,以便將來直接從記憶體中讀取,從而減少磁碟 IO。
BlockCache 是區域級的,每個區域只有乙個 blockcache。
HBase的資料只獨立存在於MEMSTORE和HBown中,BlockCache只快取HBfile中的一些熱資料。
每個地域由乙個或多個儲存組成,該地域是集群負載均衡的基本單元,也是memstore重新整理的基本單元。 整個區域實際上是乙個 LSM 樹,MEMSTORE 對應 C0 樹,作為寫快取儲存在記憶體中,hfile 對應 CN 樹,儲存在磁碟上。 通過保證順序寫入,在犧牲部分讀取效能的前提下,大大提公升了寫入效能,並通過內部優化如布隆濾波器、壓縮等方式補償讀取效能,從而實現較高的讀寫效能。
每個 store 由乙個 memstore 和多個 storefile 組成,storefile 的底層其實就是 hfile,storefile 是 hbase 對 hfile 的封裝。 每個列簇都儲存在乙個儲存中,所以如果有多個列簇,就會有多個儲存,如果列簇太多,就會有太多的記憶體,這會占用太多的記憶體,而且在重新整理時,也會造成更大的能耗。
3.4.1.1 memstore
Memstore 是 HBase 的寫快取,當 hlog 寫入成功後,會先寫入 Memstore,按照 rowkey 字典順序進行排序,當達到一定閾值時,資料會重新整理到 HDFS 中,形成乙個 hfile 檔案。 HBase 的 Memstore 使用了跳轉表的資料結構,所以這裡就不多介紹了。
memstore的作用:
寫入快取:批量累加資料,批量放置磁碟儲存,減少磁碟IO,提高效能。
排序:按照行鍵的字典順序保留資料。
Memstore 在讀寫方面起著很大的作用,最大的耗能操作是在 flush 操作中,下面我們將詳細介紹。
Memstore 重新整理觸發條件。
我們已經知道,當 memstore 的大小達到某個閾值時,資料會被重新整理到 HDFS 中,形成乙個 hfile 檔案,但需要注意的是,memstore 重新整理的最小操作單元不是 memstore,而是整個 hregion。 也就是說,如果有乙個 memstore 需要重新整理,整個 hregion 都會受到影響,所以如果乙個 hregion 中的 memstore 太多,每次重新整理的開銷必然會很大,所以每個表不應該設定太多的列簇。 觸發重新整理操作的具體條件如下:
1.什麼時候區域中的記憶體儲存高達 HBasehregion.memstore.flush.size(預設值為 128MB)會觸發該區域中的所有 Memstore 重新整理,並且不會阻止寫入操作。
2.什麼時候乙個區域中的所有記憶體儲存大小之和達到 HBasehregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size(預設值 2 * 128 = 256 MB),則會觸發該區域的所有 memstore 重新整理,從而阻止該區域的寫入操作。
3.什麼時候當區域準備好離線時memstore 大小的總和達到 HBasehregion.preclose.flush.size(預設值為 5MB),則觸發該區域內的所有 memstore 重新整理,然後可以禁用該區域。
4.什麼時候regionserver 中的所有記憶體儲存大小之和達到 HBaseregionserver.global.memstore.大小 * HBase HeapSize (預設值 0..)4 * Heap size),從memstore最大的區域開始觸發regionserver中所有區域的重新整理,並阻塞整個regionserver的寫入操作。直到 memstore 大小回退到 HBase 的上乙個引數值regionserver.global.memstore.size.lower.limit(預設值為 0。95) 次,然後才解除堵塞物。
5.什麼時候區域伺服器中的 WAL(即 hlog)到 HBaseregionserver.maxlogs(預設值 32),HBase 會為 Memstore Flush 選擇最早的 WAL 對應的區域,同時也會阻塞對應區域的寫入操作。
6.RegionServer 將定期重新整理記憶體儲存,週期為 HBaseregionserver.OptionalCacheFlushInterval(預設值為 1 小時)。 為了避免同時重新整理所有區域,定期重新整理將具有隨機延遲。
7.使用者可以通過執行 flush [table] 或 flush [region] 命令來執行此操作手動沖洗區域中的表或記憶體儲存。
3.4.1.2 hfile
hfile 是 HBase 儲存資料的檔案組織形式,它通過參考 Bigtable 的 Sstable 和 Hadoop 的 Tfile 來實現。 下圖是hfile的物理結構示意圖,如圖所示,hfile會被分成多個大小相等的塊,hfile的內部結構還是比較複雜的,感興趣的同學可以看一下(在這篇文章中,我們主要看一下儲存實際資料的資料塊。
3.4.1.2.1 datablock
資料塊是 HBase 中最小的資料儲存單元。 datablock 主要儲存使用者的 keyvalue 資料(keyvalue 後面通常跟乙個時間戳,圖中不標註),keyvalue 結構是 HBase 儲存的核心,每個資料都以 keyvalue 結構儲存在 HBase 中。 鍵值結構可以表示如下:
每個鍵值由 4 個部分組成,即鍵長度、值長度、鍵和值。 其中 key length 和 value length 是兩個固定長度的數值,而 key 是乙個複雜的結構,首先是 rowkey 的長度,然後是 rowkey,然後是 columnfamily 的長度,然後是 columnfamily,然後是 columnqualifier,最後是 timestamp 和 keytype(keytype 有四種型別,分別是 put、delete、deleteColumn 和 deletefamily),value 沒有那麼複雜,它是純二進位資料的字串。
3.4.1.2.2 基本概念。
從上圖可以看出,有些長度是固定值,所以稍微簡化一下鍵,然後重點放在這些內容的具體含義上。 鍵由 rowkey + columnfamily + column qualifier + timestamp + keytype 組成,值為實際值。
rowkey:每行資料的主鍵是HBase的唯一查詢條件,因此行鍵的設計至關重要。
column family:列簇,每個列簇的資料儲存在一起,每個列簇使用者可以自由選擇儲存哪些列,同一列簇的所有成員都有相同的列簇字首,通常相同型別的列簇下都儲存在乙個列簇下,但注意不要設定太多的列簇, 稍後將討論。
qualifier:列,即以列簇為字首的特定列,格式為 column family:qualifier。
timestamp:Timestamp,插入單元格時的時間戳,預設用作單元格的版本號。 不同版本的資料按相反的時間順序排序,即最新的資料排在第一位。 當資料需要更新時,不會像MySQL那樣直接更新到源資料,而是會新增一條新的資料,並且新資料的時間戳會更大,因此會排在第一位。 您可以根據時間戳和儲存的版本數設定 TTL。
type:資料型別,用於區分是否為刪除資料,刪除資料與更新資料相同,不會直接刪除資料的物理資料,會插入一條新的資料,但該資料的型別會標記為刪除,在查詢中會預設過濾。 僅在執行中major compaction僅在操作期間清除刪除資料。
cell:cell,在 HBa 中,該值將儲存為單元格中的單元格。 要定位單元格,需要滿足“rowkey + column family + qualifier + timestamp + keytype”這五個要素。 每個單元格都包含相同資料的多個版本。 單元格中沒有資料型別,它完全是位元組儲存。
在介紹讀寫過程之前,我們先介紹一下元表,為什麼我們要先介紹一下,因為它是唯一的讀寫方式,而且是rowkey的指南。
元表儲存了所有的區域資訊,元表儲存在 zk 中,當第一次讀寫訪問或區域失敗時,客戶端會先訪問 zk,然後客戶端會根據 rowkey 訪問對應的區域伺服器,然後客戶端會訪問對應區域伺服器進行相應的讀寫操作。
1.客戶端首先訪問ZooKeeper,獲取元表所在的地域伺服器。
2.訪問對應的地域伺服器,獲取元表表,查詢目標資料所在的地域在哪個地域伺服器。 表的區域資訊和元表的位置資訊快取在客戶端的元快取中,方便下次訪問。
3.客戶端直接與目標區域伺服器通訊。
4.資料按順序寫入(附加)到 hlog (wal) 中,以防止機器停機和記憶體中的資料丟失。
5.將資料寫入對應的 memstore,資料會在 memstore 中排序。
6.向客戶端傳送 ACK。
7.達到 memstore 的觸發條件後,資料會重新整理到 hfile。
1.客戶端首先訪問ZooKeeper,獲取元表所在的地域伺服器。
2.訪問對應的地域伺服器,獲取元表表,查詢目標資料所在的地域在哪個地域伺服器。 表的區域資訊和元表的位置資訊快取在客戶端的元快取中,方便下次訪問。
3.客戶端直接與目標區域伺服器通訊。
4.分別在它尚未放置在記憶體中memstore 和它已掉落到磁碟上(對於 hfile 資料優先從記憶體中的 blockcache 快取快取中讀取,讀取快取不從 hfile 載入)並且所有找到的資料都會被合併。 需要注意的是,HBase的資料只獨立存在於記憶體和磁碟中,即MEMSTORE和HFILE中的資料一定是全量資料,而BlockCache(讀快取)只是HFILE快取在記憶體中的熱資料的一部分,而BLOCKcache的功能是直接從記憶體中讀取HFILE的資料, 減少磁碟 IO 的數量。
5.將從檔案 hfile 查詢到的塊(hfile 資料儲存單元,預設大小為 64kb)快取到塊快取中。
6.然後,合併的最終結果將包含最新資料返回給客戶端。
閱讀該過程的詳細說明。
HBase的寫入操作非常方便,更新其實只是資料的乙個新時間戳,而資料的刪除只是乙個刪除標記,只是再次major compaction在物理刪除之前。 而且因為 hbase 中的同乙個 rowkey 是儲存多個版本的資料,以及不同的 keytype 資料,所以同乙個 rowkey 會對應多條資料,所以這裡並不像我們想象的那樣,如果 rowkey 命中 blockcache 或者 memstore,就會直接返回,遠沒有想象中那麼簡單, 所以沒有先從 BlockCache 或者 Memstore 讀取的概念,這本身就不對。
讀取資料時,必須讀取記憶體 memstore 和磁碟 hfile 中的資料,會建立兩種型別的掃瞄器(storefilescanner 和 memstorescanner)來分別探索 hfile 和 memstore 中的資料,然後會根據使用者選擇的時間範圍和行鍵範圍過濾掉一些掃瞄器,最後會先為 hfile 資料找到對應的塊, 並且 blockcache 在查詢區塊時會優先搜尋,找不到後再從 hfile 載入。memstorescanner 會從 memstore 中查詢資料,最後將記憶體和磁碟中的資料合併,將最新的資料返回給客戶端。 簡化流程如下:
1.構建掃瞄程式
每個 storescanner 都會為當前 store 中的每個 hfile 構造乙個 storefilescanner,用於檢索相應的檔案。 同時,為對應的 memstore 構建 memstorescanner,用於對儲存中的 memstore 進行資料檢索。
1.篩選掃瞄器
根據“時間範圍”和“行鍵範圍”篩選 StoreFilesCanner 和 MemstoresCanner,以消除絕對沒有要檢索的結果的掃瞄程式。
1.seek rowkey
所有 storefilescanner 都開始準備並找到負責的 hfile 中滿足條件的起始行。 Seek過程(這裡省略了Lazy Seek優化)也是乙個非常核心的步驟,它由以下三個步驟組成:
定位塊偏移量:讀取 BlockCache 中 hfile 的索引樹結構,根據索引樹獲取對應行鍵所在的塊偏移量和塊大小
載入塊:首先根據 blockoffset 在 blockcache 中找到資料塊,如果不在快取中,則將其載入到 hfile 中。
查詢鍵:在資料塊內使用二進位搜尋方法查詢特定的行鍵。
當達到觸發條件時,HBase 的 MEMSTORE 會將 MEMSTORE 中的資料重新整理到 HDFS,每次都會形成乙個新的 HBase 檔案,所以隨著時間的不斷積累,同一儲存下的 HBase 檔案會越來越多,這會降低 HBase 查詢的效能,這主要體現在查詢資料的 IO 數量增加上。 為了優化查詢效能,HBase 合併了較小的 HFLifer 以減少檔案數量,這種合併 HBase 操作稱為壓縮。
minor compaction:將合併多個相鄰的 hfile,並在合併過程中清理 TTL 資料,但不會清理已刪除的資料。 小壓縮消耗資源少,IO量小,檔案數量少,提高讀操作效能,適合高頻執行。
major compaction:乙個 store 下的所有 hfile 都會被合併,過期和刪除的資料會被清理乾淨,也就是說,所有需要刪除的資料都會在 major 壓縮中被刪除。 一般來說,主要的壓縮時間會持續很長時間,整個過程會消耗大量的系統資源,對上層業務的影響會很大。 因此,在生產環境中,大壓實的自動觸發通常被禁用,並在非高峰時段手動觸發。
資料型別:沒有資料型別,都是位元組陣列(有乙個實用程式類位元組將 j**a 物件序列化為位元組陣列),而傳統的關係型資料庫具有豐富的資料型別。
資料操作:HBase只有插入、查詢、刪除等非常基礎的操作,表之間沒有關係,而傳統資料庫一般功能很多,相互關聯。
儲存模式:HBase基於列集群儲存,傳統關係型資料庫基於行儲存。
資料更新:在資料更新的情況下,Habse 不會像傳統資料庫那樣直接修改記錄,而是在 DELETE 狀態下插入一條新資料,旨在保證順序寫入,提高資料 I/O 效率,提高效能。 並且舊資料不會立即刪除,只會在壓縮過程中刪除。
時間版本:當HBase資料寫入單元時,會附加乙個時間戳,預設為regionserver寫入資料的時間,但也可以指定不同的時間。 資料可以有多個版本,可以設定 TTL,也可以設定要保留的版本數。
索引:MySQL支援多種型別的索引,而HBase只有乙個行鍵
易於擴充套件。 從事過MySQL庫表分片的同學一定體會過它的魅力,很麻煩,但是HBase可以動態、水平擴充套件,非常方便。
只有 3 種方法可以訪問 HBase。
1.通過單個行鍵進行訪問。
2.通過 rowkey 進行範圍
3.全表掃瞄。
長度原則。 RowKey是乙個二進位程式碼流,可以是任意字串,最大長度為64KB,在實際應用中一般為10-100bytes。 建議越短越好,不超過 16 個位元組。
唯一的原則。 行鍵的唯一性必須通過設計來保證。 由於 HBase 中的資料儲存是鍵值的形式,因此如果將相同的行鍵資料插入到 HBase 中的同乙個表中,則現有資料將被新資料覆蓋。
排序原則。 HBase 的行鍵按 ASCII 排序。
雜湊原理。 行鍵應均勻分布在 HBase 節點上,防止熱資料導致資料傾斜。
reversing
顧名思義,直接反轉的意思。 比如使用者ID、手機號等,rowkey 的頭部沒有隨機性,但尾部的隨機性很好,那麼我們可以直接翻轉rowkey。 反轉可以有效地使行鍵隨機分布,但會犧牲行鍵的有序性。 它適用於獲取操作,但不適用於掃瞄操作,因為原始行鍵上資料的自然順序已被打亂。
salting
加鹽的原理是在原始行鍵前面新增乙個固定長度的隨機數,以確保資料在所有區域之間進行負載均衡。
hashing
雜湊與加鹽類似,只是雜湊要求字首不能是隨機的,需要使用一些雜湊演算法,以便客戶端在雜湊後可以重構行鍵。
推薦程式:
在大多數情況下,可以選擇服務主鍵的最後三位數字,將 HBase 分割槽的其餘部分作為加鹽字首,然後使用服務主鍵作為串聯的行鍵。
資料分析能力弱:資料分析是HBase的弱點,如聚合操作、多維複雜查詢、多表關聯查詢等。 因此,我們一般在HBase之上構建Phoenix或Spark等元件,以增強HBase的資料分析和處理能力。
二級索引本身不支援:HBase 預設只索引單列行鍵,因此正常情況下查詢非行鍵列較慢。 因此,我們一般選擇HBase二級索引方案,目前比較成熟的方案是Phoenix,也可以選擇Elasticsearch Solr等搜尋引擎自行設計和實現。
不支援原生 SQL:SQL 查詢也是 HBase 的乙個弱點,但幸運的是,這可以通過引入 Phoenix 來解決,這是乙個為 HBase 設計的 SQL 層。
HBase 本身不支援全球跨行交易,僅支援單行交易模型。 同樣,Phoenix 提供的全域性事務模型元件可以用來彌補 HBase 的這一缺點。
故障恢復時間長。
1.在設計表結構時,一定不要設定太多的列簇,不要超過三個,最好只有乙個。
2.rowkey的設計一定要注意加鹽或雜湊,避免資料熱的問題。
3.預設情況下,需要關閉 Major Compaction,因為它會消耗資源並影響寫入,因此您可以在非高峰時段手動執行。
4.如果觸發了 memstore 的重新整理,需要注意 region server 下的所有 memstore 是否都達到閾值,因為這會影響整個 region 伺服器的寫入。
5.BlockCache 不能有偏差,HBase 中的資料要麼在寫快取 memstore 中沒有寫入磁碟,要麼是已經寫入磁碟的資料,這兩個部分必須包含所有資料,blockcache 只是 hfile 快取在記憶體中的熱資料的一部分。
1.人們常說HBase資料讀取memstore、hfile和blockcache,為什麼只有storefilescanner和memstorescanner兩種型別的掃瞄器?沒有blockcachescanner?
HBase 中的資料只獨立存在於 memstore 和 storefile 中,blockcache 中的資料只是 storefile 中資料的一部分(熱資料),也就是說,blockcache 中的所有資料都必須存在於 storefile 中。 因此,MemStoresCanner 和 StoreFilesCanner 可以覆蓋所有資料。 當 storefilescanner 通過索引定位到要查詢的鍵所在的塊時,它首先檢查該塊是否存在於塊快取中,如果存在則直接檢索,如果不存在,則在對應的 storefile 中讀取。
2.資料更新操作在將資料放入磁碟之前將資料寫入記憶體儲存。 下單後需要在BlockCache中更新對應的KV嗎?如果我不更新,我會讀取髒資料嗎?
如果你理解了第乙個問題,相信很容易得出這個答案:不需要在blockcache中更新對應的kv,髒資料也不會被讀取。 寫入 memstore 的資料將形成乙個新檔案,該檔案獨立於 blockcache 中的資料,並且存在多個版本。
作者:京東物流於建飛.
*:京東雲開發者社群自猿齊說技術**請註明**。