1、 HBase的特點是什么?
1)大:一個表可以有數十億行,上百萬列;
2)無模式:每行都有一個可排序的主鍵和任意多的列,列可以根據需要動態的增加,同一張表中不同的行可以有截然不同的列;
3)面向列:面向列(族)的存儲和權限控制,列(族)獨立檢索;
4)稀疏:空(null)列並不占用存儲空間,表可以設計的非常稀疏;
5)數據多版本:每個單元中的數據可以有多個版本,默認情況下版本號自動分配,是單元格插入時的時間戳;
6)數據類型單一:Hbase中的數據都是字符串,沒有類型。
2、HBase和Hive的區別?
Hive和Hbase是兩種基於Hadoop的不同技術–Hive是一種類SQL的引擎,並且運行MapReduce任務,Hbase是一種在Hadoop之上的NoSQL 的Key/vale數據庫。
當然,這兩種工具是可以同時使用的。就像用Google來搜索,用FaceBook進行社交一樣,Hive可以用來進行統計查詢,HBase可以用來進行實時查詢,
數據也可以從Hive寫到Hbase,設置再從Hbase寫回Hive。
3、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)。
4、描述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唯一原則
必須在設計上保證其唯一性。
5、描述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 方法添加過濾器,這也是分頁、多條件查詢的基礎。
6、請描述HBase中scan對象的setCache和setBatch方法的使用?(☆☆☆☆☆)
setCache用於設置緩存,即設置一次RPC請求可以獲取多行數據。對於緩存操作,如果行的數據量非常大,多行數據有可能超過客戶端進程的內存容量,
由此引入批量處理這一解決方案。
setBatch 用於設置批量處理,批量可以讓用戶選擇每一次ResultScanner實例的next操作要取回多少列,例如,在掃描中設置setBatch(5),
則一次next()返回的Result實例會包括5列。如果一行包括的列數超過了批量中設置的值,則可以將這一行分片,每次next操作返回一片,當一行的列數不能被批量中
設置的值整除時,最后一次返回的Result實例會包含比較少的列,如,一行17列,batch設置為5,則一共返回4個Result實例,這4個實例中包括的列數分別
為5、5、5、2。
組合使用掃描器緩存和批量大小,可以讓用戶方便地控制掃描一個范圍內的行鍵所需要的RPC調用次數。Cache設置了服務器一次返回的行數,
而Batch設置了服務器一次返回的列數。
假如我們建立了一張有兩個列族的表,添加了10行數據,每個行的每個列族下有10列,這意味着整個表一共有200列(或單元格,因為每個列只有一個版本),
其中每行有20列。
① Batch參數決定了一行數據分為幾個Result,它只針對一行數據,Batch再大,也只能將一行的數據放入一個Result中。所以當一行數據有10列,
而Batch為100時,也只能將一行的所有列都放入一個Result,不會混合其他行;
② 緩存值決定一次RPC返回幾個Result,根據Batch划分的Result個數除以緩存個數可以得到RPC消息個數(之前定義緩存值決定一次返回的行數,
這是不准確的,准確來說是決定一次RPC返回的Result個數,由於在引入Batch之前,一行封裝為一個Result,因此定義緩存值決定一次返回的行數,但引入Batch后,
更准確的說法是緩存值決定了一次RPC返回的Result個數);
RPC請求次數 = (行數 * 每行列數) / Min(每行的列數,批量大小) / 掃描器緩存
下圖展示了緩存和批量兩個參數如何聯動,下圖中有一個包含9行數據的表,每行都包含一些列。使用了一個緩存為6、批量大小為3的掃描器,
需要三次RPC請求來傳送數據:
7、請詳細描述HBase中一個cell的結構?
HBase中通過row和columns確定的為一個存貯單元稱為cell。
Cell:由{row key, column(=<family> + <label>), version}唯一確定的單元。cell 中的數據是沒有類型的,全部是字節碼形式存貯。
8、簡述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執行合並操作,最終的結果是整理合並出一個文件。
9、每天百億數據存入HBase,如何保證數據的存儲正確和在規定的時間里全部錄入完畢,不殘留數據?(☆☆☆☆☆)
需求分析:
1)百億數據:證明數據量非常大;
2)存入HBase:證明是跟HBase的寫入數據有關;
3)保證數據的正確:要設計正確的數據結構保證正確性;
4)在規定時間內完成:對存入速度是有要求的。
解決思路:
1)數據量百億條,什么概念呢?假設一整天60x60x24 = 86400秒都在寫入數據,那么每秒的寫入條數高達100萬條,HBase當然是支持不了每秒百萬條數據的,
所以這百億條數據可能不是通過實時地寫入,而是批量地導入。批量導入推薦使用BulkLoad方式(推薦閱讀:Spark之讀寫HBase),性能是普通寫入方式幾倍以上;
2)存入HBase:普通寫入是用JavaAPI put來實現,批量導入推薦使用BulkLoad;
3)保證數據的正確:這里需要考慮RowKey的設計、預建分區和列族設計等問題;
4)在規定時間內完成也就是存入速度不能過慢,並且當然是越快越好,使用BulkLoad。
10、請列舉幾個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開銷。
11、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,byte[][]splitkeys)可以指定預分區的splitKey,
即是指定region間的rowkey臨界值。
12、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,如果有則進行恢復。
13、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一分為二。
14、HBase內部機制是什么?
Hbase是一個能適應聯機業務的數據庫系統
物理存儲:hbase的持久化數據是將數據存儲在HDFS上。
存儲管理:一個表是划分為很多region的,這些region分布式地存放在很多regionserver上Region內部還可以划分為store,
store內部有memstore和storefile。
版本管理:hbase中的數據更新本質上是不斷追加新的版本,通過compact操作來做版本間的文件合並Region的split。
集群管理:ZooKeeper + HMaster + HRegionServer。
15、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中。
16、HBase在進行模型設計時重點在什么地方?一張表中定義多少個Column Family最合適?為什么?(☆☆☆☆☆)
Column Family的個數具體看表的數據,一般來說划分標准是根據數據訪問頻度,如一張表里有些列訪問相對頻繁,而另一些列訪問很少,
這時可以把這張表划分成兩個列族,分開存儲,提高訪問效率。
17、如何提高HBase客戶端的讀寫性能?請舉例說明(☆☆☆☆☆)
① 開啟bloomfilter過濾器,開啟bloomfilter比沒開啟要快3、4倍
② Hbase對於內存有特別的需求,在硬件允許的情況下配足夠多的內存給它
③ 通過修改hbase-env.sh中的 export HBASE_HEAPSIZE=3000 #這里默認為1000m
④ 增大RPC數量
通過修改hbase-site.xml中的hbase.regionserver.handler.count屬性,可以適當的放大RPC數量,默認值為10有點小。
18、HBase集群安裝注意事項?
① HBase需要HDFS的支持,因此安裝HBase前確保Hadoop集群安裝完成;
② HBase需要ZooKeeper集群的支持,因此安裝HBase前確保ZooKeeper集群安裝完成;
③ 注意HBase與Hadoop的版本兼容性;
④ 注意hbase-env.sh配置文件和hbase-site.xml配置文件的正確配置;
⑤ 注意regionservers配置文件的修改;
⑥ 注意集群中的各個節點的時間必須同步,否則啟動HBase集群將會報錯。
19、直接將時間戳作為行健,在寫入單個region 時候會發生熱點問題,為什么呢?(☆☆☆☆☆)
region中的rowkey是有序存儲,若時間比較集中。就會存儲到一個region中,這樣一個region的數據變多,其它的region數據很少,加載數據就會很慢,
直到region分裂,此問題才會得到緩解。
20、請描述如何解決HBase中region太小和region太大帶來的沖突?(☆☆☆☆☆)
Region過大會發生多次compaction,將數據讀一遍並重寫一遍到hdfs 上,占用io,region過小會造成多次split,region 會下線,影響訪問服務,
最佳的解決方法是調整hbase.hregion. max.filesize 為256m。