反向掃描APIhtml
HBASE-4811(https://issues.apache.org/jira/browse/HBASE-4811)實現了一個API來掃描一個表或範圍內的一個範圍java
表反向,減小了對正向或反向掃描優化模式的需求。此功能在HBase 0.98和更高版本中可用。有關更多信息,請參閱Scan.setReversed()(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Scan.html#setReversed-boolean-)。node
數據庫處理中的一個常見問題是快速找到最新版本的值。使用反向時間戳做爲密鑰的一部分的技術能夠幫助解決這個問題的一個特例。在Tom White的書Hadoop:The Definitive Guide(O'Reilly)的HBase章節中也發現,該技術涉及在任何密鑰的末尾附加(Long.MAX_VALUE - 時間戳)。 [鍵] [reverse_timestamp]。git
經過執行掃描[鍵]並獲取第一條記錄,能夠找到表格中[鍵]的最新值。因爲HBase密鑰的排序順序不一樣,所以該密鑰在[key]的任何較舊的行鍵以前排序,所以是第一個。程序員
(或很長一段時間),同時經過使用相同的掃描技術能夠快速訪問任何其餘版本。github
行鍵的範圍爲ColumnFamilies。 所以,相同的rowkey能夠存在於沒有碰撞的表中存在的每一個ColumnFamily中。算法
行鍵沒法更改。 他們能夠在表格中「更改」的惟一方法是該行被刪除而後從新插入。 這是HBase dist-list上的一個至關常見的問題,因此在第一次(和/或在插入大量數據以前)得到rowkeys是值得的。數據庫
若是您預先拆分表格,瞭解您的rowkey如何在區域邊界上分佈是很是重要的。做爲重要的一個例子,考慮使用可顯示的十六進制字符做爲鍵的前導位置(例如,「0000000000000000」到「ffffffffffffffff」)的示例。經過Bytes.split(這是在建立Admin.createTable(byte [] startKey,byte [] endKey,numRegions)中的區域時使用的分割策略來運行這些關鍵範圍)將生成如下分割...apache
48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 // 0api
54 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 -10 // 6
61 = 67 -67 -67 -67 -67 -67 -67 -67 -67 -67 -67 -67 -67 -68 // =
68 -124 -124 -124 -124 -124 -124 -124 -124 -124 -124 -124 -124 -124 -124 -126 // D
75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 72 // K
82 18 18 18 18 18 18 18 18 18 18 18 18 18 18 14 // R
88 -40 -40 -40 -40 -40 -40 -40 -40 -40 -40 -40 -40 -40 -40 -44 // X
95 -97 -97 -97 -97 -97 -97 -97 -97 -97 -97 -97 -97 -97 -97 -102 // _
102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 // f
(注意:前導字節做爲註釋列在右側。)鑑於第一個分割是'0'而最後一個分割是'f',一切都很好,對吧?沒那麼快。
問題是全部的數據都會堆積在前兩個區域和最後一個區域,從而產生一個「塊狀」(也多是「熱」)區域問題。要理解爲何,請參閱ASCII表(http://www.asciitable.com)。 '0'是字節48,'f'是字節102,但字節值(字節58到96)間存在巨大的差距,永遠不會出如今這個密鑰空間中,由於惟一的值是[0-9]和[af ]。所以,中間地區將永遠不會被使用。爲了使用該示例密鑰空間進行預分割工做,須要分割的自定義定義(即,而且不依賴於內置分割方法)。
第1課:預分割表一般是最佳作法,但您須要預先拆分它們,以即可以在鍵空間中訪問全部區域。雖然此示例演示了十六進制密鑰空間的問題,但任何密鑰空間都會出現一樣的問題。瞭解你的數據。
第2課:雖然一般不可取,但只要全部建立的區域均可在鍵空間中訪問,則使用十六進制鍵(更通常而言,可顯示的數據)仍可用於預分割表。
總結這個例子,如下是如何爲十六進制密鑰預先建立合適的分割的例子:
public static boolean createTable(Admin admin, HTableDescriptor table, byte[][] splits) throws IOException {
try {
admin.createTable( table, splits ); return true;
} catch (TableExistsException e) {
logger.info("table " + table.getNameAsString() + " already exists");
}
}
public static byte[][] getHexSplits(String startKey, String endKey, int numRegions) { byte[][] splits = new byte[numRegions-1][];
BigInteger lowestKey = new BigInteger(startKey, 16); BigInteger highestKey = new BigInteger(endKey, 16); BigInteger range = highestKey.subtract(lowestKey);
BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions)); lowestKey = lowestKey.add(regionIncrement);
for(int i=0; i < numRegions-1;i++) {
BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i))); byte[] b = String.format("%016x", key).getBytes();
splits[i] = b;
}
return splits;
}
要存儲的行版本的最大數量是經過HColumnDescriptor(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html)爲每一個列族配置的。 最大版本的缺省值爲1.這是一個重要的參數,由於如數據模型部分所述,HBase不會覆蓋行值,而是每次按時間(和限定符)存儲不一樣的值。 在重要的壓縮過程當中刪除多餘的版本。 最大版本的數量可能須要根據應用需求增長或減小。
建議不要將最高版本數設置爲極高的級別(例如,數百或更多),除非這些舊值對您很是重要,由於這會大大增長StoreFile大小。
像行版本的最大版本數同樣,每一個列族經過配置保留的最小行數版本
HColumnDescriptor(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html)。 min版本的默認值爲0,這意味着該功能被禁用。行版本參數的最小數量與生存時間參數一塊兒使用,而且能夠與行版本數量參數組合,以容許諸如「保留最多T分鐘數據值,最多N個版本,可是至少保留M個版本「(其中M是最小行數的值,M <N)。此參數只應在爲列族啓用生存時間時設置,而且必須小於行版本的數量。
HBase經過Put(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Put.html)和Result(https:// hbase)支持「bytes-in / bytes-out」 .apache.org / apidocs / org / apache / hadoop / hbase / client / Result.html),所以能夠將任何能夠轉換爲字節數組的值存儲爲值。輸入能夠是字符串,數字,複雜對象,甚至圖像,只要它們能夠呈現爲字節。
值的大小有實際的限制(例如,在HBase中存儲10-50MB的對象可能太多了)。在郵件列表中搜索關於此主題的對話。 HBase中的全部行都符合數據模型,幷包含版本控制。在進行設計時考慮到這一點,以及ColumnFamily的塊大小。
值得特別說起的一種支持的數據類型是「計數器」(即可以執行數字的原子增量)。請參閱表中的增量(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Table.html#increment%28org.apache.hadoop.hbase.client.Increment%29)。
計數器上的同步在RegionServer上完成,而不是在客戶端上完成。
若是您有多個表,請不要忘記考慮鏈接模式設計的可能性。
ColumnFamilies能夠以秒爲單位設置TTL長度,一旦達到到期時間,HBase將自動刪除行。這適用於全部版本的行 - 即便是當前版本。在該行的HBase中編碼的TTL時間以UTC指定。
存儲僅包含過時行的文件將在小型壓縮中刪除。將hbase.store.delete.expired.storefile設置爲false會禁用此功能。將最小版本數設置爲0之外的值也會禁用此功能。
有關更多信息,請參閱HColumnDescriptor(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html)。 HBase的最新版本也支持設置時間以每一個單元爲基礎生存。參見HBASE-10560
(https://issues.apache.org/jira/browse/HBASE-10560)以獲取更多信息。單元TTL做爲突變屬性提交
使用突變#setTTL請求(追加,增長,放置等)。若是設置了TTL屬性,則該操做將應用於服務器上更新的全部單元。單元TTL處理和ColumnFamily TTL之間有兩個顯着的區別:
單元TTL以毫秒爲單位而不是秒。
單元TTL不能將一個單元的有效生命週期延長超過ColumnFamily級TTL設置。
默認狀況下,刪除標記延伸回到開始時間。所以,獲取(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Get.html)或掃描(https://hbase.apache.org/apidocs/org/apache/hadoop /hbase/client/Scan.html)操做將不會看到已刪除的單元格(行或列),即便獲取或掃描操做指示刪除標記放置以前的時間範圍。
ColumnFamilies能夠選擇保留已刪除的單元格。在這種狀況下,只要這些操做指定的時間範圍在影響單元格的任何刪除的時間戳以前結束,仍然能夠檢索已刪除的單元格。這容許甚至在存在刪除的狀況下進行時間點查詢。
Example 17. Change the Value of KEEP_DELETED_CELLS Using HBase Shell
Example 18. Change the Value of KEEP_DELETED_CELLS Using the API
讓咱們來講明在表上設置KEEP_DELETED_CELLS屬性的基本效果。 首先,without:
create 'test', {NAME=>'e', VERSIONS=>2147483647}
put 'test', 'r1', 'e:c1', 'value', 10
put 'test', 'r1', 'e:c1', 'value', 12
put 'test', 'r1', 'e:c1', 'value', 14
delete 'test', 'r1', 'e:c1', 11
hbase(main):017:0> scan 'test', {RAW=>true, VERSIONS=>1000}
ROW COLUMN+CELL
r1 column=e:c1, timestamp=14, value=value
r1 column=e:c1, timestamp=12, value=value
r1 column=e:c1, timestamp=11, type=DeleteColumn
r1 column=e:c1, timestamp=10, value=value
1 row(s) in 0.0120 seconds
hbase(main):018:0> flush 'test'
0 row(s) in 0.0350 seconds
hbase(main):019:0> scan 'test', {RAW=>true, VERSIONS=>1000}
ROW COLUMN+CELL
r1 column=e:c1, timestamp=14, value=value
r1 column=e:c1, timestamp=12, value=value
r1 column=e:c1, timestamp=11, type=DeleteColumn
1 row(s) in 0.0120 seconds
hbase(main):020:0> major_compact 'test'
0 row(s) in 0.0260 seconds
hbase(main):021:0> scan 'test', {RAW=>true, VERSIONS=>1000}
ROW COLUMN+CELL
r1 column=e:c1, timestamp=14, value=value
r1 column=e:c1, timestamp=12, value=value
1 row(s) in 0.0120 seconds
JAVA
注意刪除單元格是如何放開的。
如今讓咱們僅使用在表上設置的KEEP_DELETED_CELLS運行相同的測試(您能夠執行表或每列家族):
hbase(main):005:0> create 'test', {NAME=>'e', VERSIONS=>2147483647, KEEP_DELETED_CELLS => true}
0 row(s) in 0.2160 seconds
=> Hbase::Table - test
hbase(main):006:0> put 'test', 'r1', 'e:c1', 'value', 10
0 row(s) in 0.1070 seconds
hbase(main):007:0> put 'test', 'r1', 'e:c1', 'value', 12
0 row(s) in 0.0140 seconds
hbase(main):008:0> put 'test', 'r1', 'e:c1', 'value', 14
0 row(s) in 0.0160 seconds
hbase(main):009:0> delete 'test', 'r1', 'e:c1', 11
0 row(s) in 0.0290 seconds
hbase(main):010:0> scan 'test', {RAW=>true, VERSIONS=>1000}
ROW COLUMN+CELL
r1 column=e:c1, timestamp=14,
value=value
r1 column=e:c1, timestamp=12,
value=value
r1 column=e:c1, timestamp=11,
type=DeleteColumn
r1 column=e:c1, timestamp=10,
value=value
1 row(s) in 0.0550 seconds
hbase(main):011:0> flush 'test'
0 row(s) in 0.2780 seconds
hbase(main):012:0> scan 'test', {RAW=>true, VERSIONS=>1000}
ROW COLUMN+CELL
r1 column=e:c1, timestamp=14,
value=value
r1 column=e:c1, timestamp=12,
value=value
r1 column=e:c1, timestamp=11,
type=DeleteColumn
r1 column=e:c1, timestamp=10,
value=value
1 row(s) in 0.0620 seconds
hbase(main):013:0> major_compact 'test'
0 row(s) in 0.0530 seconds
hbase(main):014:0> scan 'test', {RAW=>true, VERSIONS=>1000}
ROW COLUMN+CELL
r1 column=e:c1, timestamp=14,
value=value
r1 column=e:c1, timestamp=12,
value=value
r1 column=e:c1, timestamp=11,
type=DeleteColumn
r1 column=e:c1, timestamp=10,
value=value
1 row(s) in 0.0650 seconds
KEEP_DELETED_CELLS是爲了不從HBase中刪除單元格時,刪除它們的惟一緣由是刪除標記。 所以,若是使用KEEP_DELETED_CELLS啓用已刪除的單元格,若是您編寫的版本多於配置的最大版本,或者您有TTL且單元格超過配置的超時等,則刪除的單元格將被刪除。
這部分也能夠標題爲「若是個人表rowkey看起來像這樣,但我也想要像這樣查詢個人表。」 dist-list上的一個常見示例是row-key格式爲「user-timestamp」的格式,但對於特定時間範圍內的用戶活動有報告要求。所以,用戶選擇容易,由於它處於密鑰的主導位置,但時間不是。
沒有一個最好的方法來解決這個問題的答案,由於它取決於...
用戶數量
數據大小和數據到達率
報告要求的靈活性(例如,徹底特定的日期選擇與預先配置的範圍)
指望的查詢執行速度(例如,對於臨時報告來講90秒多是合理的,而對於其餘方面可能太長)
解決方案也受集羣規模和解決方案所需的處理能力的影響。常見的技巧在下面的小節中介紹。這是一個全面但並不是詳盡的方法清單。
二級索引須要額外的集羣空間和處理並不使人驚訝。這正是RDBMS中發生的狀況,由於建立備用索引的操做須要更新空間和處理週期。
RDBMS產品在這方面更加先進,能夠開箱即用地處理替代索引管理。可是,HBase在更大的數據量下能夠更好地擴展,因此這是一項功能交換。
在實施任何這些方法時,請注意Apache HBase性能調整。另外,請參閱David Butler在這個dist-list線程HBase,mail#user - Stargate + hbase中的響應
(http://search-hadoop.com/m/nvbiBp2TDP/Stargate%252Bhbase&subj=Stargate+hbase)
根據具體狀況,可能適合使用客戶端請求過濾器。 在這種狀況下,不會建立二級索引。 可是,請勿嘗試在應用程序(如單線程客戶端)上對此類大型表進行全面掃描。
二級索引能夠在另外一個經過MapReduce做業按期更新的表中建立。 這項工做能夠在一天內執行,但根據加載策略,它仍然可能與主數據表不一樣步。
有關更多信息,請參閱mapreduce.example.readwrite。
另外一種策略是在將數據發佈到集羣時構建二級索引(例如寫入數據表,寫入索引表)。 若是這是在數據表已經存在以後採起的方法,那麼對於具備MapReduce做業的二級索引將須要引導(請參閱secondary.indexes.periodic)。
在時間範圍很是普遍(例如,長達一年的報告)以及數據量很大的狀況下,彙總表是經常使用的方法。 這些將經過MapReduce做業生成到另外一個表中。
有關更多信息,請參閱mapreduce.example.summary。
協處理器就像RDBMS觸發器同樣。這些增長了0.92。有關更多信息,請參閱協處理器
HBase目前支持傳統(SQL)數據庫術語中的「約束」。 Constraints的建議用法是強制執行表中屬性的業務規則(例如,確保值在1-10範圍內)。也可使用約束來強制引用完整性,可是強烈建議不要使用約束,由於它會顯着下降啓用完整性檢查的表的寫入吞吐量。從版本0.94開始,能夠在Constraint(https://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/constraint/Constraint.html)上找到有關使用約束的大量文檔。
如下將描述HBase的一些典型數據提取用例,以及如何處理rowkey設計和構造。注意:這只是潛在方法的一個例證,而不是詳盡的清單。瞭解您的數據,並瞭解您的處理要求。
強烈建議您在閱讀這些案例研究以前,首先閱讀HBase和Schema Design的其他部分。描述瞭如下案例研究:
記錄數據/時間序列數據
日誌數據/時間序列上的類固醇
客戶訂單
高/寬/中圖式設計
列表數據
假設正在收集如下數據元素。
主機名
時間戳
記錄事件
值/消息
咱們能夠將它們存儲在名爲LOG_DATA的HBase表中,但rowkey會是什麼? 從這些屬性中,rowkey將是主機名,時間戳和日誌事件的一些組合 - 但具體是什麼?
44.1.1。行密鑰主導位置中的時間戳
rowkey [timestamp] [hostname] [log-event]受單調遞增行鍵/時間序列數據中描述的單調遞增rowkey問題的影響。
經過在時間戳上執行mod操做,在dist-lists中常常提到關於「分組」時間戳的另外一種模式。若是時間掃描很重要,這多是一個有用的方法。必須注意桶的數量,由於這將須要相同數量的掃描來返回結果。
long bucket = timestamp%numBuckets;
JAVA
構建:
[桶] [時間戳] [主機名] [登陸事件]
JAVA
如上所述,要選擇特定時間範圍的數據,須要爲每一個存儲桶執行掃描。例如,100個存儲桶將在密鑰空間中提供普遍的分佈,但它須要100次掃描才能得到單個時間戳的數據,所以存在權衡。
44.1.2。主持人在Rowkey主導地位
若是存在大量的主機來經過密鑰空間來傳播寫入和讀取,則rowkey [主機名] [日誌事件] [時間戳]是候選者。若是按主機名掃描是優先事項,則此方法很是有用。
44.1.3。時間戳或反向時間戳?
若是最重要的訪問路徑是拉取最近的事件,則將時間戳存儲爲反向時間戳(例如timestamp = Long.MAX_VALUE - timestamp)將建立可以對[hostname] [log-事件]來獲取最近捕獲的事件。
這兩種方法都不是錯的,只是取決於最適合這種狀況的東西。
反向掃描API
表反向,減小了對正向或反向掃描優化模式的需求。此功能在HBase 0.98和更高版本中可用。有關更多信息,請參閱Scan.setReversed()(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Scan.html#setReversed-boolean-)。
44.1.4。可變長度或固定長度的行鍵?
記住在HBase的每一列上加蓋行密碼是很是重要的。若是主機名是a而且事件類型是e1,那麼生成的rowkey將會很小。可是,若是所攝入的主機名是myserver1.mycompany.com,而且事件類型是com.package1.subpackage2.subsubpackage3.ImportantService,該怎麼辦?
在rowkey中使用一些替換多是有意義的。至少有兩種方法:散列和數字。在Rowkey Lead Position示例中的主機名中,它可能以下所示:
帶有哈希的複合Rowkey:
[主機名的MD5散列] = 16個字節
[事件類型的MD5散列] = 16個字節
[時間戳] = 8個字節
帶數字替換的複合行列碼:
對於這種方法,除了LOG_DATA以外,還須要另外一個查找表,稱爲LOG_TYPES。 LOG_TYPES的rowkey將是:
[類型](例如,指示主機名與事件類型的字節)
原始主機名或事件類型的[bytes]可變長度字節。
此rowkey的列多是一個具備指定編號的長整數,可經過使用HBase計數器得到
(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Table.html#incrementColumnValue-byte:A-byte:A-byte:A-long-)
因此獲得的複合rowkey將是:
[代替主機名長] = 8個字節
[長時間取代事件類型] = 8個字節
[時間戳] = 8個字節
在Hash或Numeric替換方法中,主機名和事件類型的原始值能夠存儲爲列。
這其實是OpenTSDB的方法。 OpenTSDB作的是重寫數據並在特定的時間段內將行打包成列。 有關詳細說明,請參閱:http://opentsdb.net/schema.html,以及HBaseCon2012從OpenTSDB得到的經驗教訓(https://www.slideshare.net/cloudera/4-opentsdb-hbasecon)。
可是,這是通常概念的工做原理:例如,以這種方式攝入數據...
[主機名] [日誌事件] [時間戳1] [主機名] [日誌事件] [時間戳2] [主機名] [日誌事件] [時間戳3]
每一個細節事件都有獨立的rowkeys,可是會被重寫成這樣...
[主機名] [登陸事件] [TIMERANGE]
而且每一個上述事件被轉換成相對於開始時間範圍(例如每5分鐘)以時間偏移存儲的列。 這顯然是一種很是先進的處理技術,但HBase使這成爲可能。
假設HBase用於存儲客戶和訂單信息。 有兩種核心記錄類型被攝取:客戶記錄類型和訂單記錄類型。
顧客號碼
顧客姓名
地址(例如,城市,州,郵編)
電話號碼等
訂單記錄類型將包含以下內容:
顧客號碼
訂單號
銷售日期
一系列用於裝運位置和訂單項的嵌套對象(有關詳細信息,請參閱訂單對象設計)
假設客戶編號和銷售訂單的組合惟一地標識訂單,這兩個屬性將組成rowkey,特別是組合鍵,例如:
[customer number][order number]
爲一個ORDER表。 可是,還有更多的設計決策須要:原始值是rowkeys的最佳選擇?
Log Data用例中的相同設計問題在這裏面對咱們。 客戶編號的密鑰空間是什麼,以及格式是什麼(例如,數字?字母數字?)因爲在HBase中使用固定長度的密鑰以及能夠在密鑰空間中支持合理分佈的密鑰是有利的,所以相似 選項出現:
帶有哈希的複合Rowkey:
[客戶號碼的MD5] = 16字節
[訂單號的MD5] = 16字節組合數字/哈希組合Rowkey:
[代替客戶號碼] = 8個字節
[訂單號的MD5] = 16字節
單表? 多表?
傳統的設計方法會爲CUSTOMER和SALES分開表格。 另外一種選擇是將多個記錄類型打包到一個表中(例如,CUSTOMER ++)。
客戶記錄類型Rowkey:
[客戶ID]
[type] =表示客戶記錄類型的類型'1'訂單記錄類型Rowkey:
[客戶ID]
[type] =指示訂單記錄類型爲'2'的類型
[訂購]
這種特定的CUSTOMER ++方法的優勢是經過客戶ID組織許多不一樣的記錄類型(例如,單次掃描可讓你獲得關於該客戶的全部信息)。 缺點是掃描特定記錄類型並不容易。
訂單對象設計
如今咱們須要解決如何建模Order對象。假設類結構以下:
訂購
(訂單能夠有多個ShippingLocations
(一個ShippingLocation能夠有多個LineItems,在存儲這些數據時有多個選項,徹底標準化
經過這種方法,ORDER,SHIPPING_LOCATION和LINE_ITEM將會有單獨的表格。
ORDER表的rowkey如上所述:schema.casestudies.custorder SHIPPING_LOCATION的複合rowkey以下所示:
[訂單rowkey]
[出貨地點編號](例如,第一地點,第二地點等)LINE_ITEM表的複合行鍵將是這樣的:
[訂單rowkey]
[出貨地點編號](例如,第一地點,第二地點等)
[訂單項編號](例如,第一個線性項,第二個等)
這樣的標準化模型極可能是RDBMS的方法,但這不是HBase惟一的選擇。這種作法的缺點是要檢索任何訂單的信息,您須要:
獲取訂單的訂單表
在SHIPPING_LOCATION表上掃描該訂單以獲取ShippingLocation實例
在每一個ShippingLocation的LINE_ITEM上掃描
這是一個RDBMS不管如何都會在封面下作的事情,但因爲HBase中沒有鏈接,因此您只是更加意識到這一點。
單一表與記錄類型
採用這種方法,將會存在一個包含單個表的ORDER
Order rowkey如上所述:schema.casestudies.custorder
[訂單rowkey]
[訂單記錄類型]
ShippingLocation複合rowkey將以下所示:
[訂單rowkey]
[SHIPPING記錄類型]
[出貨地點編號](例如,第一地點,第二地點等)LineItem複合行鍵將是這樣的:
[訂單rowkey]
[LINE記錄類型]
[出貨地點編號](例如,第一地點,第二地點等)
[訂單項編號](例如,第一個線性項,第二個等)
反規範化
具備記錄類型的單一表格的一種變體是對一些對象層次結構進行非規範化和扁平化,好比將ShippingLocation屬性摺疊到每一個LineItem實例上。
LineItem複合rowkey將以下所示:
[訂單rowkey]
[LINE記錄類型]
[訂單項編號](例如,第一個lineitem,第二個等等,必須注意整個訂單中都有惟一),LineItem列將以下所示:
項目編號
數量
價錢
shipToLine1(從ShippingLocation非正規化)
shipToLine2(從ShippingLocation非正規化)
shipToCity(從ShippingLocation非正規化)
shipToState(從ShippingLocation非正規化)
shipToZip(從ShippingLocation非正規化)
這種方法的優勢包括不太複雜的對象層次結構,但其中一個缺點是,若是這些信息發生變化,更新會變得更加複雜。
對象BLOB
經過這種方法,整個Order對象圖都以某種方式做爲BLOB進行處理。例如,上面描述了ORDER表的rowkey:schema.casestudies.custorder,而一個名爲「order」的列將包含一個能夠反序列化的對象,該對象包含一個容器Order,ShippingLocations和LineItems。
這裏有不少選項:JSON,XML,Java序列化,Avro,Hadoop Writable等等。全部這些都是相同方法的變體:將對象圖編碼爲字節數組。應該注意這種方法,以確保向後兼容,以防對象模型發生變化,使舊的持久結構仍能從HBase中讀出。
優勢是可以以最少的I / O管理複雜的對象圖(例如,在本例中爲單個HBase Get Order),但缺點包括前面提到的關於序列化的向後兼容性,序列化的語言依賴性(例如Java序列化只適用於Java客戶端),事實上你必須反序列化整個對象才能得到BLOB中的任何信息,以及像Hive這樣的框架難以使用像這樣的自定義對象。
本節將介紹出如今遠程列表中的其餘模式設計問題,特別是高和寬表。這些是通常準則而不是法律 - 每一個應用程序都必須考慮本身的需求。
行與版本
一個常見的問題是應該更喜歡行仍是HBase的內置版本。上下文一般是保留行的「不少」版本的地方(例如,它明顯高於1個最大版本的HBase默認值)。 rows-approach須要在rowkey的某些部分存儲一個時間戳,以便在每次連續更新時不會覆蓋它們。
首選項:行(通常來講)。
行與列
另外一個常見問題是,應該更喜歡行仍是列。上下文一般在寬表格的極端狀況下,例如具備1行100萬個屬性,或100萬行,每列1列。
首選項:行(通常來講)。須要說明的是,本指南在上下文中是很是寬泛的狀況,而不是標準的用例,其中須要存儲幾十或者一百列。可是這兩個選項之間也有一條中間路徑,那就是「行列爲列」。
行做爲列
行與列之間的中間路徑將打包數據,對於某些行,這些數據將成爲單獨的行。在這種狀況下,OpenTSDB就是最好的例子,其中一行表示一個定義的時間範圍,而後將離散事件視爲列。這種方法一般更加複雜,而且可能須要重寫數據的額外複雜性,但具備I / O高效的優勢。有關此方法的概述,請參閱schema.casestudies.log-steroids。
在Apache HBase中。
題 *
咱們正在研究如何在HBase中存儲大量(每用戶)列表數據,而且咱們試圖弄清楚哪一種訪問模式最有意義。一種選擇是將大部分數據存儲在一個密鑰中,因此咱們能夠有這樣的內容:
<FixedWidthUserName> <FixedWidthValueId1>:「」(無值)
<FixedWidthUserName> <FixedWidthValueId2>:「」(無值)
<FixedWidthUserName> <FixedWidthValueId3>:「」(無值)
JAVA
咱們的另外一個選擇是徹底使用:
<FixedWidthUserName> <FixedWidthPageNum0>:<FixedWidthLength> <FixedIdNextPageNum> <ValueId1> <ValueId2> <ValueId3> ...
<FixedWidthUserName> <FixedWidthPageNum1>:<FixedWidthLength> <FixedIdNextPageNum> <ValueId1> <ValueId2> <ValueId3> ...
XML
每行將包含多個值。因此在一種狀況下,讀取前三十個值將是:
掃描{STARTROW =>'FixedWidthUsername'LIMIT => 30} JAVA
而在第二種狀況下會是這樣
獲得'FixedWidthUserName \ x00 \ x00 \ x00 \ x00'JAVA
通常的使用模式是僅讀取這些列表的前30個值,而且不常常訪問更深刻地閱讀列表。一些用戶在這些列表中的總值將達到30%,而一些用戶將擁有數百萬(即冪律分佈)
單值格式彷佛會佔用HBase更多的空間,但會提供一些改進的檢索/分頁靈活性。是否有任何顯着的性能優點可以經過獲取與分頁掃描分頁?
我最初的理解是,若是咱們的分頁大小未知(而且緩存設置恰當),那麼執行掃描應該會更快,但若是咱們始終須要相同的頁面大小,則掃描速度應該更快。我聽到不一樣的人告訴了我關於表演的相反事情。我假設頁面大小會相對一致,因此對於大多數用例,咱們能夠保證咱們只須要固定頁面長度的狀況下的一頁數據。我還會假設咱們將不常常更新,但可能會插入這些列表的中間(這意味着咱們須要更新全部後續行)。
感謝您的幫助/建議/後續問題。
答案*
若是我正確理解你,你最終試圖以「user,valueid,value」的形式存儲三元組,對嗎?例如,相似於:
「user123,firstname,Paul」,「user234,lastname,Smith」
JAVA
(但用戶名是固定寬度,而valueids是固定寬度)。
並且,您的訪問模式符合如下要求:「對於用戶X,列出接下來的30個值,以valueid Y開頭」。是對的嗎?這些值應該返回按valueid排序?
tl; dr版本是,你可能應該爲每一個用戶+值添加一行,除非你肯定須要,不然不要自行構建複雜的行內分頁方案。
您的兩個選項反映了人們在設計HBase模式時常見的問題:我應該選擇「高」仍是「寬」?您的第一個模式是「高」:每行表明一個用戶的一個值,所以每一個用戶的表中有不少行;行鍵是user + valueid,而且會有(可能)單個列限定符,意思是「值」。這是
正確)。你能夠在任何用戶+ valueid開始掃描,閱讀下一個30,並完成。你放棄的是可以在一個用戶的全部行周圍提供事務保證,但它聽起來並不像你須要的那樣。一般建議這樣作(參見https://hbase.apache.org/book.html#schema.smackdown)。
第二個選項是「寬」:使用不一樣的限定符(其中限定符是valueid)將一堆值存儲在一行中。簡單的作法是將一個用戶的全部值存儲在一行中。我猜你跳到了「分頁」版本,由於你認爲在單行中存儲數百萬列會對性能形成影響,這多是也可能不是真的;只要您不想在單個請求中作太多事情,或者執行諸如掃描並返回行中的全部單元格之類的內容,它不該該基本上變得更糟。客戶端具備容許您獲取特定的列的片斷的方法。
請注意,這兩種狀況都不會從根本上佔用更多的磁盤空間;您只是將部分識別信息「移動」到左側(在行鍵中,在選項一中)或向右(在選項2中的列限定符中)。在封面下,每一個鍵/值仍然存儲整個行鍵和列名稱。 (若是這有點使人困惑,請花一個小時觀看Lars George關於理解HBase架構設計的優秀視頻:http://www.youtube.com/watch?v = _HLoH_PgrLk)。
正如你注意到的那樣,手動分頁版本有不少複雜性,好比必須跟蹤每一個頁面中有多少內容,若是插入新值,則從新洗牌等。這看起來要複雜得多。在分機上它可能有一些輕微的速度優點(或缺點!)
將hbase.regionserver.handler.count(在hbase-site.xml中)設置爲cores x spindles以實現併發。
可選地,將呼叫隊列分紅單獨的讀取和寫入隊列以用於區別服務。參數
hbase.ipc.server.callqueue.handler.factor指定呼叫隊列的數量:
0表示單個共享隊列
1表示每一個處理程序有一個隊列。
0到1之間的值與處理程序的數量成比例地分配隊列數量。例如,.5的值在每一個處理程序之間共享一個隊列。
使用hbase.ipc.server.callqueue.read.ratio(0.98中的hbase.ipc.server.callqueue.read.share)將調用隊列分爲讀寫隊列:
0.5意味着將有相同數量的讀寫隊列
讀取比寫入少0.5
> 0.5以上的寫入比讀取
設置hbase.ipc.server.callqueue.scan.ratio(HBase 1.0+)將讀取調用隊列分爲小讀和長讀隊列:
0.5意味着將有相同數量的短讀取和長讀取隊列
更短的讀數<0.5
> 0.5爲更長的閱讀
禁用Nagle的算法。 延遲的ACK能夠將RPC往返時間加起來大約200ms。 設置如下參數:
在Hadoop的core-site.xml中:
ipc.server.tcpnodelay = true
ipc.client.tcpnodelay = true
在HBase的hbase-site.xml中:
hbase.ipc.client.tcpnodelay = true
hbase.ipc.server.tcpnodelay = true
儘量快地檢測區域服務器故障。 設置如下參數:
在hbase-site.xml中,將zookeeper.session.timeout設置爲30秒或更短期來綁定故障檢測(20-30秒是一個好的開始)。
檢測並避免不健康或失敗的HDFS數據節點:在hdfs-site.xml和hbase-site.xml中,設置如下參數:
dfs.namenode.avoid.read.stale.datanode = true
dfs.namenode.avoid.write.stale.datanode = true
跳過本地塊的網絡。 在hbase-site.xml中,設置如下參數:
dfs.client.read.shortcircuit = true
dfs.client.read.shortcircuit.buffer.size = 131072(重要避免OOME)
確保數據的局部性。 在hbase-site.xml中,設置hbase.hstore.min.locality.to.skip.major.compact = 0.7(意思是0.7 <= n <= 1)
確保DataNode有足夠的處理程序進行塊傳輸。 在hdfs-site.xml中,設置如下參數:
dfs.datanode.max.xcievers> = 8192
調整JVM GC以獲取低收集延遲
使用CMS收集器:-XX:+ UseConcMarkSweepGC
保持伊甸園空間儘量小,以減小平均收集時間。例:
-XX:CMSInitiatingOccupancyFraction = 70
優化低收集延遲而不是吞吐量:-Xmn512m
並行收集伊甸園:-XX:+ UseParNewGC
避免在壓力下收集:-XX:+ UseCMSInitiatingOccupancyOnly
限制每一個請求掃描器的結果大小,因此一切都適合倖存者空間,但沒有任職期限。在hbase-site.xml中,將hbase.client.scanner.max.result.size設置爲eden空間的1/8(使用-Xmn512m這是〜51MB)
設置max.result.size x handler.count小於生存者空間
OS級調整
關閉透明大頁面(THP):
echo never> / sys / kernel / mm / transparent_hugepage / enabled echo never> / sys / kernel / mm / transparent_hugepage / defrag
設置vm.swappiness = 0
將vm.min_free_kbytes設置爲至少1GB(較大內存系統上爲8GB)
使用vm.zone_reclaim_mode = 0禁用NUMA區域回收
在客戶端的hbase-site.xml中,設置如下參數:
設置hbase.client.pause = 1000
設置hbase.client.retries.number = 3
若是你想騎跨分割和區域移動,大幅增長hbase.client.retries.number(> = 20)
設置RecoverableZookeeper重試計數:zookeeper.recovery.retry = 1(不重試)
在服務器端的hbase-site.xml中,設置Zookeeper會話超時以檢測服務器故障:
zookeeper.session.timeout⇐30秒(20-30是比較好的)
HBase時間線一致性(HBASE-10070)啓用只讀副本後,區域(副本)的只讀副本將分佈在羣集中。 One RegionServer爲默認或主副本提供服務,這是惟一能夠服務寫入的副本。 其餘Region Server服務於輔助副本,請遵循主要RegionServer,並僅查看提交的更新。 輔助副本是隻讀的,但能夠在主服務器故障時當即提供讀取操做,從而將讀取可用性從幾秒鐘減小到幾毫秒。 Phoenix支持時間線一致性4.4.0提示:
部署HBase 1.0.0或更高版本。
在服務器端啓用時間線一致副本。
使用如下方法之一設置時間線一致性:
使用ALTER SESSION SET CONSISTENCY ='TIMELINE'
在JDBC鏈接字符串中將鏈接屬性Consistency設置爲時間軸
TableInputFormat(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/mapreduce/TableInputFormat.html)用於源MapReduce做業中的HBase表格時,其拆分器將爲每一個映射任務建立一個映射任務表的區域。 所以,若是表格中有100個區域,則不管在「掃描」中選擇多少個列族,該做業都會有100個地圖任務。
對於那些有興趣實現自定義拆分器的人,請參閱TableInputFormatBase中的getSplits方法(https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/mapreduce/TableInputFormatBase.html)。 這是map-task分配的邏輯所在。
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。關於此部分暫時不填入。後續將繼續補充
Hadoop認證配置
要使用強身份驗證運行HBase RPC,您必須將hbase.security.authentication設置爲kerberos。 在這種狀況下,您還必須將hadoop.security.authentication設置爲core-site.xml中的kerberos。 不然,您將對HBase使用強身份驗證,但不會對底層HDFS使用強身份驗證,不然會取消任何收益。
Kerberos KDC
您須要有一個可用的Kerberos KDC。
首先,參考security.prerequisites並確保您的基礎HDFS配置是安全的。
將如下內容添加到集羣中每臺服務器計算機上的hbase-site.xml文件中:
<property>
<name>hbase.security.authentication</name>
<value>kerberos</value>
</property>
<property>
<name>hbase.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.token.TokenProvider</value>
</property>
部署這些配置更改時,須要徹底關閉並從新啓動HBase服務。
首先,請參閱先決條件並確保您的基礎HDFS配置是安全的。
將如下內容添加到每一個客戶端上的hbase-site.xml文件中:
<property>
<name>hbase.security.authentication</name>
<value>kerberos</value>
</property>
客戶端環境必須經過kinit命令從KDC或keytab登陸到Kerberos,而後才能與HBase羣集通訊。
請注意,若是客戶端和服務器端站點文件中的hbase.security.authentication不匹配,客戶端將沒法與羣集進行通訊。
一旦將HBase配置爲安全RPC,就能夠選擇配置加密通訊。 爲此,請將如下內容添加到每一個客戶端上的hbase-site.xml文件中:
<property>
<name>hbase.rpc.protection</name>
<value>privacy</value>
</property>
此配置屬性也能夠在每一個鏈接的基礎上進行設置。 在提供給表的配置中進行設置:
Connection connection = ConnectionFactory.createConnection(conf);
conf.set("hbase.rpc.protection", "privacy");
try (Connection connection = ConnectionFactory.createConnection(conf); Table table = connection.getTable(TableName.valueOf(tablename))) {
.... do your stuff
}
對於加密通訊,預計會有大約10%的性能損失。
將如下內容添加到每一個Thrift網關的hbase-site.xml文件中
<property>
<name>hbase.thrift.keytab.file</name>
<value>/etc/hbase/conf/hbase.keytab</value>
</property>
<property>
<name>hbase.thrift.kerberos.principal</name>
<value>$USER/_HOST@HADOOP.LOCALDOMAIN</value>
<!-- TODO: This may need to be HTTP/_HOST@<REALM> and _HOST may not work. You may have to put the concrete full hostname.
-->
</property>
<!-- Add these if you need to configure a different DNS interface from the default -->
<property>
<name>hbase.thrift.dns.interface</name>
<value>default</value>
</property>
<property>
<name>hbase.thrift.dns.nameserver</name>
<value>default</value>
</property>
分別替換$ USER和$ KEYTAB的相應憑證和密鑰表。
爲了使用Thrift API主體與HBase進行交互,還須要將hbase.thrift.kerberos.principal添加到acl表。 例如,爲了給予Thrift API主體thrift_server管理訪問權限,像這樣的命令就足夠了。
grant 'thrift_server', 'RWCA'
有關ACL的更多信息,請參閱訪問控制標籤(ACL)部分
Thrift網關將使用提供的憑證向HBase進行身份驗證。 Thrift網關自己不會執行認證。 全部經過Thrift網關訪問的客戶端都將使用Thrift網關的憑證並擁有其權限。
用於安全操做的客戶端配置 - Thrift Gateway描述瞭如何使用固定用戶向HBase驗證Thrift客戶端。做爲替代,您能夠將Thrift網關配置爲表明客戶端向HBase進行身份驗證,並使用代理用戶訪問HBase。這在HBASE-11349(https://issues.apache.org/jira/browse/HBASE-11349)中爲Thrift 1和HBASE-11474(https://issues.apache.org/jira/browse/HBASE)實施-11474)爲Thrift 2。
節儉框架運輸的侷限性
若是您使用框架式運輸,您還不能利用此功能,由於此時SASL不適用於Thrift框架式運輸。
要啓用它,請執行如下操做。
1.按照安全操做客戶端配置 - Thrift Gateway中所述的步驟,確保Thrift以安全模式運行。
2.確保HBase配置爲容許代理用戶,如REST網關模擬配置中所述。
3.在運行Thrift網關的每一個羣集節點的hbase-site.xml中,將屬性hbase.thrift.security.qop設置爲如下三個值之一:
integrity - authentication and integrity checking
authentication - authentication checking only
4.從新啓動Thrift網關進程以使更改生效。若是節點正在運行Thrift,則jps命令的輸出將列出ThriftServer進程。要中止節點上的Thrift,請運行命令bin / hbase-daemon.sh stop thrift。要在節點上啓動Thrift,請運行命令bin / hbase-daemon.sh start thrift。
表明客戶端配置Thrift網關進行身份驗證描述如何配置Thrift網關以表明客戶端對HBase進行身份驗證,以及如何使用代理用戶訪問HBase。 這種方法的侷限性在於客戶端使用特定的憑證集進行初始化後,在會話期間它不能更改這些憑證。 doAs功能提供了使用相同客戶端模擬多個主體的靈活方式。 此功能在H BASE-12640(https://issues.apache.org/jira/browse/HBASE-12640)中爲Thrift 1實施,但目前不適用於Thrift 2。
要啓用doAs功能,請將如下內容添加到每一個Thrift網關的hbase-site.xml文件中:
<property>
<name>hbase.regionserver.thrift.http</name>
<value>true</value>
</property>
<property>
<name>hbase.thrift.support.proxyuser</name>
<value>true/value>
</property>
要在使用doAs模擬時容許代理用戶,請將如下內容添加到每一個HBase節點的hbase-site.xml文件中:
<property>
<name>hadoop.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.groups</name>
<value>$GROUPS</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.hosts</name>
<value>$GROUPS</value>
</property>
看看演示客戶端
(https://github.com/apache/hbase/blob/master/hbase-examples/src/main/java/org/apache/hadoop/hbase/thrift/HttpDoAsClient.java)以得到關於如何使用的整體思路 這個功能在你的客戶端。
將如下內容添加到每一個REST網關的hbase-site.xml文件中:
<property>
<name>hbase.rest.keytab.file</name>
<value>$KEYTAB</value>
</property>
<property>
<name>hbase.rest.kerberos.principal</name>
<value>$USER/_HOST@HADOOP.LOCALDOMAIN</value>
</property>
分別替換$ USER和$ KEYTAB的相應憑證和密鑰表。 REST網關將使用提供的憑證對HBase進行身份驗證。
爲了使用REST API主體與HBase進行交互,還須要將hbase.rest.kerberos.principal添加到acl表。 例如,要賦予REST API主體rest_server管理訪問權限,像這樣的命令就足夠了:
有關ACL的更多信息,請參閱訪問控制標籤(ACL)部分
HBase REST網關支持客戶端訪問網關的SPNEGO HTTP身份驗證(https://hadoop.apache.org/docs/stable/hadoop-auth/index.html)。 要爲客戶端訪問啓用REST網關Kerberos身份驗證,請將如下內容添加到每一個REST網關的hbase-site.xml文件中。
<property>
<name>hbase.rest.support.proxyuser</name>
<value>true</value>
</property>
<property>
<name>hbase.rest.authentication.type</name>
<value>kerberos</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.principal</name>
<value>HTTP/_HOST@HADOOP.LOCALDOMAIN</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.keytab</name>
<value>$KEYTAB</value>
</property>
<!-- Add these if you need to configure a different DNS interface from the default -->
<property>
<name>hbase.rest.dns.interface</name>
<value>default</value>
</property>
<property>
<name>hbase.rest.dns.nameserver</name>
<value>default</value>
</property>
用$ KEYTAB替代HTTP的keytab。
HBase REST網關支持不一樣的'hbase.rest.authentication.type':簡單,kerberos。 您也能夠經過實現Hadoop AuthenticationHandler來實現自定義身份驗證,而後將完整的類名稱指定爲'hbase.rest.authentication.type'值。 有關更多信息,請參閱SPNEGO HTTP身份驗證(https://hadoop.apache.org/docs/stable/hadoop-auth/index.html)。
默認狀況下,REST網關不支持模擬。 它以用戶的身份訪問HBase,按照上一節中的配置。 對於HBase服務器,全部請求都來自REST網關用戶。 實際用戶不詳。 您能夠打開模擬支持。 經過模擬,REST網關用戶是代理用戶。 HBase服務器知道每一個請求的實際/真實用戶。 所以它能夠應用適當的受權。
要打開REST網關模擬,咱們須要配置HBase服務器(主服務器和區域服務器)以容許代理用戶; 配置REST網關以啓用模擬。
要容許代理用戶,請將如下內容添加到每一個HBase服務器的hbase-site.xml文件中:
<property>
<name>hadoop.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.groups</name>
<value>$GROUPS</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.hosts</name>
<value>$GROUPS</value>
</property>
將REST網關代理用戶替換爲$ USER,並將容許的組列表替換爲$ GROUPS。
要啓用REST網關模擬,請將如下內容添加到每一個REST網關的hbase-site.xml文件中。
<name>hbase.rest.authentication.type</name>
<value>kerberos</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.principal</name>
<value>HTTP/_HOST@HADOOP.LOCALDOMAIN</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.keytab</name>
<value>$KEYTAB</value>
</property>
用$ KEYTAB替代HTTP的keytab。
較新版本的Apache HBase(> = 0.92)支持客戶端的可選SASL身份驗證。 另請參閱Matteo Bertozzi有關了解Apache HBase中的用戶身份驗證和受權的文章(https://blog.cloudera.com/blog/2012/09/understanding-user-authentication-and-authorization-in-apache-hbase/)。
本節介紹如何設置Apache HBase和客戶端,以便用戶訪問HBase資源。
如下部分介紹如何設置簡單的用戶訪問。 簡單的用戶訪問不是一種運行HBase的安全方法。 此方法用於防止用戶犯錯。 它可用於在開發系統上模擬訪問控制,而無需設置Kerberos。
此方法不用於防止惡意或黑客入侵。 爲了使HBase可以抵禦這些類型的攻擊,您必須配置HBase進行安全操做。 請參閱安全客戶端訪問Apache HBase部分並完成此處描述的全部步驟。
將如下內容添加到集羣中每臺服務器計算機上的hbase-site.xml文件中:
<property>
<name>hbase.security.authentication</name>
<value>simple</value>
</property>
<property>
<name>hbase.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<property>
<name>hbase.coprocessor.regionserver.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
0.94版本如下不適用上述xml配置。
ZooKeeper具備可插入的身份驗證機制,可使用不一樣的方法訪問客戶端。 ZooKeeper甚至容許同時驗證和未驗證的客戶端。經過爲每一個znode提供訪問控制列表(ACL)來限制對znodes的訪問。 ACL包含兩個組件,即身份驗證方法和主體。 ACL不是分層強制執行的。有關詳細信息,請參閱ZooKeeper程序員指南(https://zookeeper.apache.org/doc/r3.3.6/zookeeperProgrammers.html#sc_ZooKeeperPluggableAuthentication)。
HBase守護進程經過SASL和Kerberos向ZooKeeper進行身份驗證(請參閱使用ZooKeeper進行SASL身份驗證)。 HBase設置znode ACL,以便只有HBase用戶和配置的hbase超級用戶(hbase.superuser)才能訪問和修改數據。在ZooKeeper用於服務發現或與客戶端共享狀態的狀況下,由HBase建立的znodes也將容許任何人(無論身份驗證)讀取這些znode(clusterId,主地址,元位置等),但只有HBase用戶能夠修改它們。
全部管理的數據都保存在文件系統(hbase.rootdir)的根目錄下。訪問文件系統中的數據和WAL文件應受到限制,以便用戶不能繞過HBase層,並從文件系統中查看底層數據文件。 HBase假定使用的文件系統(HDFS或其餘)分層次地強制執行權限。若是沒有提供足夠的文件系統保護(受權和身份驗證),HBase級受權控制(ACL,可見性標籤等)就沒有意義,由於用戶能夠隨時訪問文件系統中的數據。
HBase對其根目錄強制執行posix-like權限700(rwx ------)。這意味着只有HBase用戶能夠讀寫FS中的文件。經過在hbase-site.xml中配置hbase.rootdir.perms能夠更改默認設置。須要從新啓動活動主服務器,以便更改使用的權限。對於1.2.0以前的版本,您能夠檢查是否提交了HBASE-13780,若是沒有,您能夠根據須要手動設置根目錄的權限。使用HDFS,該命令將是:
sudo -u hdfs hadoop fs -chmod 700 /hbase
若是您使用不一樣的hbase.rootdir,則應該更改/ hbase。
在安全模式下,應配置SecureBulkLoadEndpoint並將其用於將用戶做業從MR做業建立到HBase守護程序和HBase用戶的正確處理。分佈式文件系統中的臨時目錄用於批量加載
(hbase.bulkload.staging.dir,默認爲/ tmp / hbase-staging)應具備(模式711或rwx-x-x),以便用戶能夠訪問在該父目錄下建立的暫存目錄,但不能執行任何其餘操做操做。有關如何配置SecureBulkLoadEndPoint,請參閱安全批量加載。
在HBase客戶端和服務器進程和網關之間配置安全身份驗證後,您須要考慮數據自己的安全性。 HBase提供了幾種保護數據的策略:
基於角色的訪問控制(RBAC)控制哪些用戶或組可使用熟悉的角色範例來讀取和寫入給定的HBase資源或執行協處理器端點。
可見性標籤,容許您標記單元格並控制對標記單元格的訪問,以進一步限制誰能夠讀取或寫入數據的某些子集。可見性標籤存儲爲標籤。有關更多信息,請參閱hbase.tags。
在HFile和WAL中對底層文件系統的靜態數據進行透明加密。這能夠保護您的數據免受能夠訪問底層文件系統的攻擊者的影響,而無需更改客戶端的實現。它還能夠防止不正確放置的磁盤泄漏數據,這對法律和法規聽從性可能很是重要。
下面討論這些功能中的每一個功能的服務器端配置,管理和實現細節,以及任何性能折衷。最後給出一個示例安全配置,以顯示全部這些功能一塊兒使用,由於它們可能在真實世界的場景中。
HBase安全的各個方面都在積極發展和快速發展。您爲了保護您的數據而採起的任何策略都應該進行完全的測試。另外,其中一些功能還處於實驗階段。要利用其中的許多功能,您必須運行HBase 0.98+並使用HFile v3文件格式。
保護敏感文件
本節中的幾個過程要求您在羣集節點之間複製文件。複製包含敏感字符串的密鑰,配置文件或其餘文件時,請使用安全方法(如ssh)來避免泄露敏感數據。
過程:基本的服務器端配置
<property>
<name>hfile.format.version</name>
<value>3</value>
</property>
標籤是HFile v3的一項功能。 標籤是做爲單元的一部分的元數據,與密鑰,值和版本分開。 標籤是實現細節,爲其餘安全相關功能(如單元級ACL和可見性標籤)提供基礎。 標籤存儲在HFiles自身中。 未來可能會使用標籤來實現其餘HBase功能。 您無需瞭解不少關於標籤的信息,以便使用它們啓用的安全功能。
實施細節
每一個單元能夠有零個或多個標籤。 每一個標籤都有一個類型和實際的標籤字節數組。
就像行鍵,列族,限定符和值能夠被編碼同樣(參見data.block.encoding.types),標籤也能夠被編碼。 您能夠在列族級別啓用或禁用標籤編碼,而且默認狀況下啓用。 使用HColumnDescriptor#setCompressionTags(boolean compressTags)方法來管理列族的編碼設置。 您還須要爲列族啓用DataBlockEncoder,以使標記的編碼生效。
若是啓用WAL壓縮,則能夠經過設置WAL的值來啓用WAL中每一個標記的壓縮
在hbase-site.xml中將hbase.regionserver.wal.tags.enablecompression設置爲true。 標記壓縮使用字典編碼。
使用WAL加密時,不支持標記壓縮。
HBase中的ACL基於用戶對組的訪問權限,以及給定組訪問給定資源的權限。 ACL被實現爲稱爲AccessController的協處理器。
HBase不維護私有組映射,但依賴於Hadoop組映射器,它映射LDAP或Active Directory等目錄中的實體和HBase用戶。任何支持的Hadoop組映射器均可以工做。而後,針對資源(全局,名稱空間,表格,單元或端點)授予用戶特定的權限(讀取,寫入,執行,建立,管理)。
啓用Kerberos和訪問控制後,客戶端對HBase的訪問將獲得驗證,而且用戶數據是專用的,除非明確授予訪問權限。
與關係數據庫相比,HBase具備更簡單的安全模型,特別是在客戶端操做方面。例如,插入(新記錄)和更新(現有記錄)之間沒有區別,由於二者都摺疊成投入。
瞭解訪問級別
HBase訪問級別是相互獨立授予的,並容許在給定範圍內進行不一樣類型的操做。
讀取(R) - 能夠讀取給定範圍的數據
寫入(W) - 能夠在給定範圍寫入數據
執行(X) - 能夠在給定範圍內執行協處理器端點
建立(C) - 能夠在給定範圍內建立表或刪除表(甚至不建立它們)
管理員(A) - 能夠執行羣集操做,例如平衡羣集或在給定範圍內分配區域可能的範圍包括:
超級用戶 - 超級用戶能夠執行HBase中可用的任何操做,以訪問任何資源。在羣集上運行HBase的用戶是超級用戶,分配給HMaster上的hbase-site.xml中的配置屬性hbase.superuser的任何主體都是如此。
全局 - 在全局範圍授予的權限容許管理員對集羣的全部表進行操做。
名稱空間 - 在命名空間範圍授予的權限適用於給定名稱空間內的全部表。
表 - 在表範圍授予的權限適用於給定表中的數據或元數據。
ColumnFamily - 在ColumnFamily範圍內授予的權限適用於該ColumnFamily內的單元格。
單元格 - 在單元格範圍內授予的權限適用於該確切的單元格座標(鍵,值,時間戳)。這容許政策與數據一塊兒發展。
要更改特定單元格上的ACL,請使用新ACL寫入更新後的單元格,以得到原始座標的精確座標。
若是您有多版本模式而且想要更新全部可見版本的ACL,則須要爲全部可見版本編寫新的單元格。應用程序能夠徹底控制策略演變。
上述規則的例外是附加和增量處理。追加和增量能夠在操做中攜帶ACL。若是包含在操做中,那麼它將應用於追加或增量的結果。不然,保存您正在追加或增長的現有單元的ACL。
訪問級別和範圍的組合建立了可授予用戶的可能訪問級別的矩陣。在生產環境中,根據執行特定工做所需的內容來考慮訪問級別是有用的。如下列表描述了一些常見類型的HBase用戶的適當訪問級別。重要的是不要授予給定用戶執行其所需任務所需的更多訪問權限。
超級用戶 - 在生產系統中,只有HBase用戶應具備超級用戶訪問權限。在開發環境中,管理員可能須要超級用戶訪問才能快速控制和管理羣集。可是,這種類型的管理員一般應該是全局管理員而不是超級用戶。
全局管理員 - 全局管理員能夠執行任務並訪問HBase中的每一個表。在典型的生產環境中,管理員不該具備對錶內數據的讀取或寫入權限。
具備管理員權限的全局管理員能夠在羣集上執行羣集範圍的操做,例如平衡,分配或取消分配區域或調用明確的主要壓縮。這是一個操做角色。
具備建立權限的全局管理員能夠建立或刪除HBase中的任何表。這更像是一個DBA類型的角色。
在當前實施中,具備管理員權限的全局管理員能夠授予他本身對錶的讀寫權限並得到對該表數據的訪問權限。所以,只需將全局管理員權限授予實際須要它們的可信用戶。
還要注意,具備建立權限的全局管理員能夠在ACL表上執行Put操做,模擬授予或撤銷並繞過Global Admin權限的受權檢查。
因爲這些問題,請謹慎授予全局管理員權限。
命名空間管理員 - 具備建立權限的命名空間管理員能夠在該命名空間內建立或刪除表,並獲取和恢復快照。具備管理員權限的名稱空間管理員能夠對該名稱空間內的表執行操做,例如拆分或主要壓縮。
表管理員 - 表管理員只能在該表上執行管理操做。具備建立權限的表管理員能夠從該表建立快照或從快照中恢復該表。具備管理員權限的表管理員能夠在該表上執行操做,例如拆分或主要壓縮。
用戶 - 用戶能夠讀取或寫入數據,或二者兼有。若是給定可執行文件,用戶也能夠執行協處理器端點
權限。
Table 8. Real-World Example of Access Levels
Job Title |
Scope |
Permissions |
Description |
Senior Administrator |
Global |
Access, Create |
Manages the cluster and gives access to Junior Administrators. |
Junior Administrator |
Global |
Create |
Creates tables and gives access to Table Administrators. |
Table Administrator |
Table |
Access |
Maintains a table from an operations point of view. |
Data Analyst |
Table |
Read |
Creates reports from HBase data. |
Web Application |
Table |
Read, Write |
Puts data into HBase and uses HBase data to perform operations. |
ACL矩陣
有關ACL如何映射到特定HBase操做和任務的更多詳細信息,請參閱附錄acl矩陣。
實施細節
單元級ACL使用標籤實現(請參閱標籤)。爲了使用單元級別的ACL,您必須使用HFile v3和HBase 0.98或更高版本。
1.由HBase建立的文件由運行HBase進程的操做系統用戶擁有。要與HBase文件交互,您應該使用API或批量加載功能。
2. HBase不在HBase內部爲「角色」建模。相反,組名能夠被授予權限。這容許經過組成員身份對角色進行外部建模。組經過Hadoop組映射服務在HBase外部建立和操做。
服務器端配置
1.做爲先決條件,執行過程:基本服務器端配置中的步驟。
2.經過在hbase-site.xml中設置如下屬性來安裝和配置AccessController協處理器。這些屬性包含一個類的列表。
若是您使用AccessController以及VisibilityController,則AccessController必須首先出如今列表中,由於在這兩個組件都處於活動狀態時,VisibilityController將委派訪問
安全配置示例。
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController, org.apache.hadoop.hbase.security.token.TokenProvider</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<property>
<name>hbase.coprocessor.regionserver.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<property>
<name>hbase.security.exec.permission.checks</name>
<value>true</value>
</property>
或者,您能夠經過將hbase.rpc.protection設置爲隱私來啓用傳輸安全性。 這須要HBase
0.98.4或更新版本
可見性標籤控件可用於僅容許與給定標籤關聯的用戶或主體讀取或訪問具備該標籤的單元格。例如,您可能會標記單元格絕密,而且只能將該標籤的訪問權授予管理員組。可見性標籤是使用標籤實現的,標籤是HFile v3的一個功能,並容許您以每一個單元爲基礎存儲元數據。標籤是一個字符串,可使用邏輯運算符(&,|或!)將標籤組合爲表達式,並使用圓括號進行分組。 HBase不能對錶達式進行任何形式的驗證,除了基本的良構。可見性標籤自己沒有意義,能夠用來表示敏感級別,特權級別或任何其餘任意的語義含義。
在HBase 0.98.6及更高版本中,可見性標籤和表達式支持UTF-8編碼。當使用org.apache.hadoop.hbase.security.visibility.VisibilityClient類提供的addLabels(conf,labels)方法建立標籤並經過掃描或獲取在受權中傳遞標籤時,標籤能夠包含UTF-8字符以及一般在可見性標籤中使用的邏輯運算符,以及普通的Java符號,而不須要任何轉義方法。可是,當您經過Mutation傳遞CellVisibility表達式時,若是使用UTF-8字符或邏輯運算符,則必須用CellVisibility.quote()方法將表達式括起來。請參閱TestExpressionParser和源文件hbase-client / src / test / java / org / apache / hadoop / hbase / client / TestScan.java。
用戶在Put操做期間向單元添加可見性表達式。在默認配置中,用戶不須要訪問標籤就能夠用它來標記單元格。此行爲由配置選項hbase.security.visibility.mutations.checkauths控制。若是將此選項設置爲true,則用戶正在修改的標籤做爲突變的一部分必須與用戶關聯,不然突變將失敗。在獲取或掃描期間肯定用戶是否有權讀取標記的單元格,而且不容許用戶讀取的結果被過濾掉。這會致使相同的I / O處罰,如同返回結果同樣,但會減小網絡負載。
可見性標籤也能夠在刪除操做中指定。有關可見性標籤和刪除的詳細信息,請參閱HBASE-10885(https://issues.apache.org/jira/browse/HBASE-10885)。
當RegionServer首次收到請求時,用戶的有效標籤集創建在RPC上下文中。用戶與標籤關聯的方式是可插入的。默認插件經過添加到獲取或掃描的受權中指定的標籤,並檢查針對主叫用戶的已認證標籤列表的標籤。當客戶端傳遞用戶未經過認證的標籤時,默認插件會丟棄它們。您能夠經過Get#setAuthorizations(Authorizations(String,...))和Scan#setAuthorizations(Authorizations(String,...))傳遞一部分用戶認證標籤;方法。
能夠按照與用戶相同的方式向組授予可見性標籤。組前綴爲@符號。當檢查用戶的可見性標籤時,服務器將包括用戶所屬的組的可見性標籤以及用戶本身的標籤。當使用API VisibilityClient#getAuths或Shell命令get_auths爲用戶檢索可見性標籤時,咱們將返回專門爲該用戶添加的標籤,而不是組級標籤。
可見性標籤訪問檢查由VisibilityController協處理器執行。您可使用界面VisibilityLabelService來提供自定義實現和/或控制可見性標籤與單元格一塊兒存儲的方式。例如,查看源文件hbase-server / src / test / java / org / apache / hadoop / hbase / security / visibility / TestVisibilityLabelsWithCustomVisLabService.java。
可見性標籤能夠與ACL一塊兒使用。
標籤必須在可見標籤中使用以前明肯定義。請參閱下面的示例來了解如何完成此操做。
目前沒有辦法肯定哪些標籤已應用於單元格。參見HBASE-12470
(https://issues.apache.org/jira/browse/HBASE-12470)以獲取詳細信息。
可見性標籤目前不適用於超級用戶。
Table 9. Examples of Visibility Expressions
Expression |
Interpretation |
fulltime |
Allow access to users associated with the fulltime label. |
!public |
Allow access to users not associated with the public label. |
( secret | topsecret ) & !probationary |
Allow access to users associated with either the secret or topsecret label and not associated with the probationary label. |
1.做爲先決條件,執行過程:基本服務器端配置中的步驟。
2.經過在hbase-site.xml中設置如下屬性來安裝和配置VisibilityController協處理器。 這些屬性包含類名的列表。
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
</property>
若是一塊兒使用AccessController和VisibilityController協處理器,AccessController
必須首先出如今列表中,由於在這兩個組件都處於活動狀態時,VisibilityController會將其系統表上的訪問控制委託給AccessController。
3.調整配置
默認狀況下,用戶可使用任何標籤來標記單元格,包括它們沒有關聯的標籤,這意味着用戶能夠放入他沒法閱讀的數據。 例如,即便用戶沒有與該標籤相關聯,用戶也能夠用(假設的)'topsecret'標籤來標記單元格。 若是您只但願用戶可以標記與其關聯的標籤的單元格,請將hbase.security.visibility.mutations.checkauths設置爲true。 在這種狀況下,若是使用用戶未關聯的標籤,則突變將失敗。
分發您的配置並從新啓動羣集以使更改生效。
HBase提供了一種保護靜態數據的機制,位於HDFS或其餘分佈式文件系統中的HFiles和WAL。 雙層體系結構用於靈活和非侵入式密鑰旋轉。 「透明」意味着客戶端不須要實施變動。 數據寫入時,它被加密。 當它被讀取時,它被按需解密。
它是怎麼運行的
管理員爲集羣提供主密鑰,該主密鑰存儲在管理工做站上的每一個受信任的HBase進程均可訪問的密鑰提供程序中,包括HMaster,RegionServers和客戶端(如HBase Shell)。默認密鑰提供程序與Java KeyStore API和任何支持它的密鑰管理系統集成在一塊兒。其餘自定義密鑰提供者實現是可能的密鑰檢索機制在hbase-site.xml中配置
外部密鑰服務器或硬件安全模塊中。此主密鑰由HBase進程經過配置的密鑰提供程序根據須要進行解析。
接下來,經過建立或修改列描述符以包含兩個附加屬性,能夠在模式中的每列系列中指定加密用途:要使用的加密算法的名稱(當前僅支持「AES」),以及可選的數據密鑰用集羣主密鑰打包(加密)。若是沒有爲ColumnFamily顯式配置數據密鑰,則HBase將爲每一個HFile建立一個隨機數據密鑰。與替代方案相比,這提供了安全性的漸進式改進。除非須要提供明確的數據密鑰,例如在使用給定數據密鑰生成用於批量導入的加密HFile的狀況下,只需在ColumnFamily模式元數據中指定加密算法,並讓HBase按需建立數據密鑰。每列系列按鍵便於低影響增量式按鍵旋轉,並減小關鍵材料的任何外部泄漏的範圍。包裝後的數據密鑰存儲在ColumnFamily模式元數據中,並存儲在列族的每一個HFile中,並使用羣集主密鑰進行加密。 Column Family配置爲加密後,任何新的HFile都將被加密寫入。爲了確保全部HFile的加密,在啓用此功能後觸發主要壓縮。
當HFile打開時,數據密鑰從HFile中提取,用集羣主密鑰解密,並用於解密HFile的其他部分。若是主密鑰不可用,HFile將不可讀。若是遠程用戶以某種方式獲取對HDile數據的訪問權限,或者因爲某些HDFS權限失效或丟棄了不適當的媒體,將沒法解密數據密鑰或文件數據。
也能夠加密WAL。儘管WAL是暫時的,可是若是底層文件系統受到威脅,則有必要對WALEdits進行加密,以免對加密列族的HFile進行保護。當啓用WAL加密時,不管相關的HFile是否加密,全部WAL都會被加密。
服務器端配置
此過程假定您正在使用默認的Java密鑰庫實現。 若是您正在使用自定義實現,請檢查其文檔並進行相應調整。
$ keytool -keystore /path/to/hbase/conf/hbase.jks \
-storetype jceks -storepass **** \
-genseckey -keyalg AES -keysize 128 \
-alias <alias>
上一個命令在HBase conf /目錄中建立了一個名爲hbase.jks的文件。 設置此文件的權限和全部權,以便只有HBase服務賬戶用戶能夠讀取該文件,並將密鑰安全地分發給全部HBase服務器。
配置HBase守護進程。
在區域服務器上的hbase-site.xml中設置如下屬性,將HBase守護程序配置爲使用由KeyStore文件支持的密鑰提供程序或檢索集羣主密鑰。 在下面的示例中,將****替換爲密碼。
<property>
<name>hbase.crypto.keyprovider</name>
<value>org.apache.hadoop.hbase.io.crypto.KeyStoreKeyProvider</value>
</property>
<property>
<name>hbase.crypto.keyprovider.parameters</name>
<value>jceks:///path/to/hbase/conf/hbase.jks?password=****</value>
</property>
默認狀況下,將使用HBase服務賬戶名稱來解析羣集主密鑰。 可是,您可使用任意別名(在keytool命令中)存儲它。 在這種狀況下,請將如下屬性設置爲您使用的別名。
<property>
<name>hbase.crypto.master.key.name</name>
<value>my-alias</value>
</property>
配置HBase 1.0之後。 對於之前的版本,請在hbase-site.xml文件中設置如下屬性
<property>
<name>hfile.format.version</name>
<value>3</value>
</property>
或者,您可使用不一樣的密碼提供者,能夠是Java密碼加密(JCE)算法提供者,也能夠是自定義HBase密碼實現。
JCE:
安裝簽名的JCE提供程序(支持128位密鑰的AES / CTR / NoPadding模式)
將其最高優先級添加到JCE站點配置文件$ JAVA_HOME / lib / security / java.security。
在hbase-site.xml中更新hbase.crypto.algorithm.aes.provider和hbase.crypto.algorithm.rng.provider選項。
定製HBase密碼:
實現org.apache.hadoop.hbase.io.crypto.CipherProvider。
將實現添加到服務器類路徑。
更新hbase-site.xml中的hbase.crypto.cipherprovider。
4.配置WAL加密。
經過設置如下屬性,在每一個RegionServer的hbase-site.xml中配置WAL加密。 您也能夠將這些包含在HMaster的hbase-site.xml中,但HMaster沒有WAL而且不會使用它們。
<property>
<name>hbase.regionserver.hlog.reader.impl</name>
<value>org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogReader</value>
</property>
<property>
<name>hbase.regionserver.hlog.writer.impl</name>
<value>org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogWriter</value>
</property>
<property>
<name>hbase.regionserver.wal.encryption</name>
<value>true</value>
</property>
5.在hbase-site.xml文件上配置權限。
因爲密鑰庫密碼存儲在hbase-site.xml中,所以您須要確保只有HBase用戶可使用文件全部權和權限來讀取hbase-site.xml文件。
6.從新啓動羣集。
將新的配置文件分發到全部節點並從新啓動羣集。
行政
管理任務能夠在HBase Shell或Java API中執行。
Java API
本節中的Java API示例取自源文件hbase-
服務器/ SRC /測試/ JAVA /組織/阿帕奇/ hadoop的/ HBase的/ UTIL / TestHBaseFsckEncryption.java。 。
這些例子以及它們的源文件都不屬於公共HBase API的一部分,僅供參考。有關使用說明,請參閱官方API。
在列系列上啓用加密
要在列系列上啓用加密,您可使用HBase Shell或Java API。啓用加密後,觸發重大壓縮。當主要壓縮完成時,HFiles將被加密。
旋轉數據鍵
要旋轉數據鍵,首先更改列描述符中的ColumnFamily鍵,而後觸發一個主要壓縮。壓縮完成後,全部HFile將使用新數據密鑰從新加密。在壓實完成以前,舊的HFile仍然可使用舊密鑰進行讀取。
在使用隨機數據鍵和指定鍵之間切換
若是將某個列族配置爲使用特定的鍵,而且您但願返回爲該列族使用隨機生成的鍵的默認行爲,請使用Java API來更改HColumnDescriptor,以便不會使用鍵ENCRYPTION_KEY發送值。
旋轉主密鑰
要旋轉主密鑰,請首先生成並分發新密鑰。而後更新KeyStore以包含新的主密鑰,並使用不一樣的別名將舊的主密鑰保存在KeyStore中。接下來,將備用配置配置到hbase-site.xml文件中的舊主密鑰。
因爲客戶端必須將從MapReduce做業生成的文件的全部權轉移給HBase,因此在安全模式下的批量加載比正常設置涉及更多。 安全批量加載由名爲的協處理器實現
SecureBulkLoadEndpoint(https://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/security/access/SecureBulkLoadEndpoint.html),它使用配置屬性hbase.bulkload.staging.dir配置的登臺目錄,它 默認爲
的/ tmp/ HBase的分段/。
安全批量加載算法
只有一次,建立一個世界可穿越的並由運行HBase(模式711或rwx-x-x)的用戶所擁有的臨時目錄。 該目錄的列表將以下所示:
$ ls -ld /tmp/hbase-staging
drwx--x--x 2 hbase hbase 68 3 Sep 14:54 /tmp/hbase-staging
用戶將數據寫入該用戶擁有的安全輸出目錄。 例如,/ user / foo / data。
在內部,HBase建立一個全局可讀寫的祕密分段目錄(-rwxrwxrwx,777)。 例如,/ tmp / hbase-staging / averylongandrandomdirectoryname。 該目錄的名稱和位置不會公開給用戶。 HBase管理這個目錄的建立和刪除。
用戶使數據具備世界可讀性和世界可寫性,將數據移入隨機登臺目錄,而後調用
SecureBulkLoadClient#bulkLoadHFiles方法。
安全的優點在於祕密目錄的長度和隨機性。 要啓用安全批量加載,請將如下屬性添加到hbase-site.xml。