首頁 > 軟體

「技術分享」BAT大資料面試常問面試題之資料查詢篇

2021-05-18 01:00:54

1. HBase 特點是什麼?

1)大:一個表可以有數十億行,上百萬列;

2)無模式:每行都有一個可排序的主鍵和任意多的列,列可以根據需要動態的增加,同一張表中不同的行可以有截然不同的列;

3)面向列:面向列(族)的儲存和許可權控制,列(族)獨立檢索;

4)稀疏:空(null)列並不佔用儲存空間,表可以設計的非常稀疏;

5)資料多版本:每個單元中的資料可以有多個版本,預設情況下版本號自動分配,是單元格插入時的時間戳;

6)資料類型單一:Hbase 中的資料都是字元串,沒有類型。

2. HBase 適用於怎樣的情景?

① 半結構化或非結構化資料:對於資料結構欄位不夠確定或雜亂無章很難按一個概念去進行抽取的資料適合用 HBase。以上面的例子為例,當業務發展需要儲存 author 的 email,phone, address 資訊時 RDBMS 需要停機維護,而 HBase 支援動態增加。

② 記錄非常稀疏RDBMS的行有多少列是固定的,為 null 的列浪費了儲存空間。而如上文提到的,HBase 為 null 的 Column 不會被儲存,這樣既節省了空間又提高了讀效能。

③ 多版本資料:如上文提到的根據 Row key 和 Column key 定位到的 Value 可以有任意數量的版本值,因此對於需要儲存變動歷史記錄的資料,用 HBase 就非常方便了。比如上例中的 author 的 Address 是會變動的,業務上一般只需要最新的值,但有時可能需要查詢到歷史值。

④ 超大資料量:當資料量越來越大,RDBMS 資料庫撐不住了,就出現了讀寫分離策略,通過一個 Master 專門負責寫操作,多個 Slave 負責讀操作,伺服器成本倍增。 隨著壓力增加,Master 撐不住了,這時就要分庫了,把關聯不大的資料分開部署,一些 join 查詢不能用了,需要藉助中間層。隨著資料量的進一步增加, 一個表的記錄越來越大,查詢就變得很慢,於是又得搞分表,比如按 ID 取模分成多個表以減少單個表的記錄數。經歷過這些事的人都知道過程是多麼的折騰。 採用HBase 就簡單了,只需要加機器即可,HBase 會自動水平切分擴展,跟Hadoop 的無縫整合保障了其資料可靠性(HDFS)和海量資料分析的高效能(MapReduce)。

3. 描述 HBase 的 rowKey 的設計原則?

(1)Rowkey 長度原則

Rowkey 是一個二進位制碼流,Rowkey 的長度被很多開發者建議說設計在10~100 個位元組,不過建議是越短越好,不要超過 16 個位元組。

原因如下:

① 資料的持久化檔案 HFile 中是按照 KeyValue 儲存的,如果 Rowkey 過長比如 100 個位元組,1000 萬列資料光 Rowkey 就要佔用 100*1000 萬=10 億個位元組, 將近 1G 資料,這會極大影響 HFile 的儲存效率;

② MemStore 將快取部分資料到記憶體,如果 Rowkey 欄位過長記憶體的有效利用率會降低,系統將無法快取更多的資料,這會降低檢索效率。 因此 Rowkey的位元組長度越短越好。

③ 目前作業系統是都是 64 位系統,記憶體 8 位元組對齊。控制在 16 個位元組,8位元組的整數倍利用作業系統的最佳特性。

(2)Rowkey 雜湊原則

如果 Rowkey 是按時間戳的方式遞增,不要將時間放在二進位制碼的前面,建議將 Rowkey 的高位作為雜湊欄位,由程式迴圈生成,低位放時間欄位, 這樣將提高資料均衡分佈在每個 Regionserver 實現負載均衡的機率。如果沒有雜湊欄位,首欄位直接是時間資訊將產生所有新資料都在一個 RegionServer 上堆積的 熱點現象,這樣在做資料檢索的時候負載將會集中在個別RegionServer,降低查詢效率。

(3)Rowkey 唯一原則

必須在設計上保證其唯一性。

4. 描述 HBase 中 scan 和 get 的功能以及實現的異同?

HBase 的查詢實現只提供兩種方式:

1)按指定 RowKey 獲取唯一一條記錄,get 方法(org.apache.hadoop.hbase.client.Get) Get 的方法處理分兩種 : 設定了ClosestRowBefore 和 沒有設定 ClosestRowBefore 的 rowlock。主要是用來保證行的事務性,即每個 get 是以一個 row 來標記的。一個 row 中可以有很多 family 和 column。

2)按指定的條件獲取一批記錄,scan 方法(org.apache.Hadoop.hbase.client.Scan)實現條件查詢功能使用的就是 scan方式。

(1)scan 可以通過 setCaching 與 setBatch 方法提高速度(以空間換時間);

(2)scan 可以通過 setStartRow 與 setEndRow 來限定範圍([start,end)start 是閉區間,end 是開區間)。範圍越小,效能越高。

(3)scan 可以通過 setFilter 方法新增過濾器,這也是分頁、多條件查詢的基礎。

5. 請詳細描述 HBase 中一個 cell 的結構?

HBase 中通過 row 和 columns 確定的為一個存貯單元稱為 cell。Cell:由{row key, column(= + ), version}唯一確定的單元。cell 中的資料是沒有類型的,全部是位元組碼形式存貯。

6. 簡述 HBase 中 compact 用途是什麼?

什麼時候觸發,分為哪兩種,有什麼區別,有哪些相關配置參數?

在 hbase 中每當有 memstore 資料 flush 到磁碟之後,就形成一個 storefile,當 storeFile 的數量達到一定程度後,就需要將 storefile 檔案來 進行compaction 操作。

Compact 的作用:

① 合併檔案

② 清除過期,多餘版本的資料

③ 提高讀寫資料的效率HBase 中實現了兩種 compaction 的方式:minor and major. 這兩種

compaction 方式的區別是:

1)Minor 操作只用來做部分檔案的合併操作以及包括 minVersion=0 並且設定 ttl 的過期版本清理,不做任何刪除資料、多版本資料的清理工作。

2)Major 操作是對 Region 下的 HStore 下的所有 StoreFile 執行合併操作,最終的結果是整理合並出一個檔案。

7. 每天百億資料存入 HBase,如何保證資料的儲存正確

和在規定的時間裡全部錄入完畢,不殘留資料?

需求分析:

1)百億資料:證明資料量非常大;

2)存入 HBase:證明是跟 HBase 的寫入資料有關;

3)保證資料的正確:要設計正確的資料結構保證正確性;

4)在規定時間內完成:對存入速度是有要求的。

解決思路:

1)資料量百億條,什麼概念呢?假設一整天 60x60x24 = 86400 秒都在寫入資料,那麼每秒的寫入條數高達 100 萬條,HBase 當然是支援不了每秒百萬條資料的, 所以這百億條資料可能不是通過實時地寫入,而是批量地匯入。批量匯入推薦使用 BulkLoad 方式(推薦閱讀:Spark 之讀寫 HBase),效能是普通寫入方式幾倍以上;

2)存入 HBase:普通寫入是用 JavaAPI put 來實現,批量匯入推薦使用BulkLoad;

3)保證資料的正確:這裡需要考慮 RowKey 的設計、預建分區和列族設計等問題;

4)在規定時間內完成也就是存入速度不能過慢,並且當然是越快越好,使用BulkLoad。

8. 請列舉幾個 HBase 優化方法?

1)減少調整

減少調整這個如何理解呢?HBase 中有幾個內容會動態調整,如 region(分區)、HFile,所以通過一些方法來減少這些會帶來 I/O 開銷的調整。

① Region:如果沒有預建分區的話,那麼隨著 region 中條數的增加,region 會進行分裂,這將增加 I/O 開銷,所以解決方法就是根據你的 RowKey 設計來進行預建分區, 減少 region 的動態分裂。

② HFile:HFile 是資料底層儲存檔案,在每個 memstore 進行重新整理時會生成一個HFile,當 HFile 增加到一定程度時,會將屬於一個 region 的 HFile 進行合併,這個步驟會帶來開銷但不可避免,但是合併後 HFile 大小如果大於設定的值,那麼 HFile 會重新分裂。為了減少這樣的無謂的 I/O 開銷,建議估計項目資料量大小, 給 HFile 設定一個合適的值。

2)減少啟停

資料庫事務機制就是為了更好地實現批量寫入,較少資料庫的開啟關閉帶來的開銷,那麼 HBase 中也存在頻繁開啟關閉帶來的問題。

① 關閉 Compaction,在閒時進行手動 Compaction。因為 HBase 中存在 Minor Compaction 和 Major Compaction,也就是對HFile 進行合併,所謂合併就是 I/O 讀寫,大量的 HFile 進行肯定會帶來 I/O開銷, 甚至是 I/O 風暴,所以為了避免這種不受控制的意外發生,建議關閉自動 Compaction,在閒時進行 compaction。

② 批量資料寫入時採用 BulkLoad。如果通過 HBase-Shell 或者 JavaAPI 的 put 來實現大量資料的寫入,那麼效能差是肯定並且還可能帶來一些意想不到的問題,所以當需要寫入大量離線資料時 建議使用 BulkLoad。

3)減少資料量

雖然我們是在進行大資料開發,但是如果可以通過某些方式在保證資料準確性同時減少資料量,何樂而不為呢?

① 開啟過濾,提高查詢速度,開啟 BloomFilter,BloomFilter 是列族級別的過濾,在生成一個 StoreFile同時會生成一個 MetaBlock,用於查詢時過濾資料

② 使用壓縮 一般推薦使用 Snappy 和 LZO 壓縮

4)合理設計

在一張 HBase 表格中 RowKey 和 ColumnFamily 的設計是非常重要,好的設計能夠提高效能和保證資料的準確性

① RowKey 設計:應該具備以下幾個屬性

雜湊性:雜湊效能夠保證相同相似的 rowkey 聚合,相異的 rowkey 分散,有利於查詢。

簡短性:rowkey 作為 key 的一部分儲存在 HFile 中,如果為了可讀性將rowKey 設計得過長,那麼將會增加儲存壓力。

唯一性:rowKey 必須具備明顯的區別性。

業務性:舉例來說:

假如我的查詢條件比較多,而且不是針對列的條件,那麼 rowKey 的設計就應該支援多條件查詢。

如果我的查詢要求是最近插入的資料優先,那麼 rowKey 則可以採用叫上Long.Max-時間戳的方式,這樣 rowKey 就是遞減排列。

② 列族的設計:列族的設計需要看應用場景

優勢:HBase 中資料時按列進行儲存的,那麼查詢某一列族的某一列時就不需要全盤掃描,只需要掃描某一列族,減少了讀 I/O; 其實多列族設計對減少的作用不是很明顯,適用於讀多寫少的場景

劣勢:降低了寫的 I/O 效能。原因如下:資料寫到 store 以後是先快取在memstore 中,同一個 region 中存在多個列族則存在多個 store, 每個 store 都一個 memstore,當其實 memstore 進行 flush 時,屬於同一個 region 的store 中的 memstore 都會進行 flush,增加 I/O 開銷。

9. Region 如何預建分區?

預分區的目的主要是在創建表的時候指定分區數,提前規劃表有多個分區,以及每個分區的區間範圍,這樣在儲存的時候 rowkey 按照分區的區間儲存,可以避免 region 熱點問題。

通常有兩種方案:

方案 1:shell 方法

create 'tb_splits', {NAME => 'cf',VERSIONS=> 3},{SPLITS =>['10','20','30']}

方案 2:JAVA 程式控制

① 取樣,先隨機生成一定數量的 rowkey,將取樣資料按升序排序放到一個集合裡;

② 根據預分區的 region 個數,對整個集合平均分割,即是相關的 splitKeys;

③ HBaseAdmin.createTable(HTableDescriptor tableDescriptor,bytesplitkeys)可以指定預分區的 splitKey, 即是指定region 間的 rowkey 臨界值。

10.HRegionServer 宕機如何處理?

1)ZooKeeper 會監控 HRegionServer 的上下線情況,當 ZK 發現某個HRegionServer 宕機之後會通知 HMaster 進行失效備援;

2)該 HRegionServer 會停止對外提供服務,就是它所負責的 region 暫時停止對外提供服務;

3)HMaster 會將該 HRegionServer 所負責的 region 轉移到其他HRegionServer 上,並且會對 HRegionServer 上存在 memstore 中還未持久化到磁碟中的資料進行恢復;

4)這個恢復的工作是由 WAL 重播來完成,這個過程如下:

① wal 實際上就是一個檔案,存在/hbase/WAL/對應 RegionServer 路徑下。

② 宕機發生時,讀取該 RegionServer 所對應的路徑下的 wal 檔案,然後根據不同的 region 切分成不同的臨時檔案 recover.edits。

③ 當 region 被分配到新的 RegionServer 中,RegionServer 讀取 region時會進行是否存在 recover.edits,如果有則進行恢復。

11.HBase 讀寫流程?

讀:

① HRegionServer 儲存著 meta 表以及表資料,要訪問表資料,首先 Client先去訪問 zookeeper,從 zookeeper 裡面獲取 meta 表所在的位置資訊, 即找到這個 meta 表在哪個 HRegionServer 上儲存著。

② 接著 Client 通過剛才獲取到的 HRegionServer 的 IP 來訪問 Meta 表所在的 HRegionServer,從而讀取到 Meta,進而獲取到 Meta 表中存放的元資料。

③ Client 通過元資料中儲存的資訊,訪問對應的 HRegionServer,然後掃描所在 HRegionServer 的 Memstore 和 Storefile 來查詢資料。

④ 最後 HRegionServer 把查詢到的資料響應給 Client。

寫:

① Client 先訪問 zookeeper,找到 Meta 表,並獲取 Meta 表元資料。

② 確定當前將要寫入的資料所對應的 HRegion 和 HRegionServer 伺服器。

③ Client 向該 HRegionServer 伺服器發起寫入資料請求,然後HRegionServer 收到請求並響應。

④ Client 先把資料寫入到 HLog,以防止資料丟失。

⑤ 然後將資料寫入到 Memstore。

⑥ 如果 HLog 和 Memstore 均寫入成功,則這條資料寫入成功。

⑦ 如果 Memstore 達到閾值,會把 Memstore 中的資料 flush 到 Storefile中。

⑧ 當 Storefile 越來越多,會觸發 Compact 合併操作,把過多的 Storefile合併成一個大的 Storefile。

⑨ 當 Storefile 越來越大,Region 也會越來越大,達到閾值後,會觸發 Split操作,將 Region 一分為二。

12.HBase 內部機制是什麼?

Hbase 是一個能適應聯機業務的資料庫系統

物理儲存:hbase 的持久化資料是將資料儲存在 HDFS 上。

儲存管理:一個表是劃分為很多 region 的,這些 region 分散式地存放在很多 regionserver 上 Region 內部還可以劃分為 store, store 內部有memstore 和 storefile。

版本管理:hbase 中的資料更新本質上是不斷追加新的版本,通過 compact操作來做版本間的檔案合併 Region 的 split。

叢集管理:ZooKeeper + HMaster + HRegionServer。

13.Hbase 中的 memstore 是用來做什麼的?

hbase 為了保證隨機讀取的效能,所以 hfile 裡面的 rowkey 是有序的。當客戶端的請求在到達 regionserver 之後,為了保證寫入 rowkey 的有序性, 所以不能將資料立刻寫入到 hfile 中,而是將每個變更操作儲存在記憶體中,也就是memstore 中。memstore 能夠很方便的支援操作的隨機插入, 並保證所有的操作在記憶體中是有序的。當 memstore 達到一定的量之後,會將 memstore裡面的資料 flush 到 hfile 中,這樣能充分利用 hadoop 寫入大檔案的效能優勢, 提高寫入效能。

由於 memstore 是存放在記憶體中,如果 regionserver 因為某種原因死了,會導致記憶體中資料丟失。所有為了保證資料不丟失, hbase 將更新操作在寫入memstore 之前會寫入到一個 write ahead log(WAL)中。WAL 檔案是追加、順序寫入的,WAL 每個 regionserver 只有一個, 同一個 regionserver 上所有 region 寫入同一個的 WAL 檔案。這樣當某個 regionserver 失敗時,可以通過 WAL 檔案,將所有的操作順序重新載入到 memstore 中。

14.HBase 在進行模型設計時重點在什麼地方?

一張表中定義多少個Column Family 最合適?為什麼?

Column Family 的個數具體看錶的資料,一般來說劃分標準是根據資料訪問頻度,如一張表裡有些列訪問相對頻繁,而另一些列訪問很少, 這時可以把這張表劃分成兩個列族,分開儲存,提高訪問效率。

15.如何提高 HBase 客戶端的讀寫效能?請舉例說明

① 開啟 bloomfilter 過濾器,開啟 bloomfilter 比沒開啟要快 3、4 倍

② Hbase 對於記憶體有特別的需求,在硬體允許的情況下配足夠多的記憶體給它

③ 通過修改 hbase-env.sh 中的 export HBASE_HEAPSIZE=3000 #這裡預設為 1000m

④ 增大 RPC 數量通過修改 hbase-site.xml 中的 hbase.regionserver.handler.count 屬性,可以適當的放大 RPC 數量,預設值為 10 有點小。

16.HBase 叢集安裝注意事項?

① HBase 需要 HDFS 的支援,因此安裝 HBase 前確保 Hadoop 叢集安裝完成;

② HBase 需要 ZooKeeper 叢集的支援,因此安裝 HBase 前確保ZooKeeper 叢集安裝完成;

③ 注意 HBase 與 Hadoop 的版本相容性;

④ 注意 hbase-env.sh 配置檔案和 hbase-site.xml 配置檔案的正確配置;

⑤ 注意 regionservers 配置檔案的修改;

⑥ 注意叢集中的各個節點的時間必須同步,否則啟動 HBase 叢集將會報錯。

17.直接將時間戳作為行健,在寫入單個 region 時候會發生熱點問題?

region 中的 rowkey 是有序儲存,若時間比較集中。就會儲存到一個 region中,這樣一個 region 的資料變多,其它的 region 資料很少,載入資料就會很慢, 直到 region 分裂,此問題才會得到緩解。

18.請描述如何解決 HBase 中 region 太小和 region 太大帶來的衝突?

Region 過大會發生多次 compaction,將資料讀一遍並重寫一遍到 hdfs 上,佔用 io,region 過小會造成多次 split,region 會下線,影響訪問服務, 最佳的解決方法是調整 hbase.hregion. max.filesize 為 256m。

最後推薦一本大資料資料分析與處理相關書籍,《Python資料分析與大資料處理從入門到精通》

(1)全面:資料分析與大資料處理所需的所有技術,包含基礎理論、核心概念、實施流程,從程式語言準備、資料採集與清洗、資料分析與視覺化,到大型資料的分散式儲存與分散式計算等。

(2)深入:一本書講透1種程式語言和14種資料分析與大處理工具,以及大資料分析技術及項目開發方法。

(3)豐富:包含45個「新手問答」、17個章節的「實訓」、3個項目綜合實戰、50道Python面試題精選。


IT145.com E-mail:sddin#qq.com