hbase权威指南学习笔记
生活随笔
收集整理的這篇文章主要介紹了
hbase权威指南学习笔记
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、簡介
1.列式存儲數(shù)據(jù)庫
以列為單位聚合數(shù)據(jù),然后將列值順序的存入磁盤,而傳統(tǒng)數(shù)據(jù)庫時為行式數(shù)據(jù)庫,連續(xù)地存儲整行
列式數(shù)據(jù)庫:對于特定的查詢,不需要所有的值,在分析型數(shù)據(jù)庫最常見
1)關(guān)系型數(shù)據(jù)庫存在的問題
高并發(fā)的解決步驟
增加用于讀取的從服務(wù)器,將讀寫分離
增加緩存,如Memcached,但無法保證數(shù)據(jù)的一致性
將數(shù)據(jù)分區(qū)到多個數(shù)據(jù)庫中,運維成本高。分區(qū)主要描述了邏輯上水平劃分?jǐn)?shù)據(jù)的方案,特點是將數(shù)據(jù)分文件或分服務(wù)器存儲,而不是連續(xù)存儲。數(shù)據(jù)的分區(qū)是在固定范圍內(nèi)實施的:在傳入數(shù)據(jù)之前,必須提前劃分好數(shù)據(jù)的存儲范圍
一致性模型:數(shù)據(jù)庫必須保證每一步操作都是從一致的狀態(tài)到下一個一致的狀態(tài) 按照嚴(yán)格強(qiáng)度劃分: 嚴(yán)格一致性:數(shù)據(jù)的變化是原子的,一經(jīng)改變及時生效 順序一致性:每個客戶端看到的數(shù)據(jù)依照它們操作執(zhí)行的順序而變化 因果一致性:客戶端以因果關(guān)系順序觀察到數(shù)據(jù)的改變 最終一致性:在沒有更新數(shù)據(jù)的一段時間里,系統(tǒng)將通過廣播早證副本之間的數(shù)據(jù)一致性 弱一致性:沒有做出保證的情況下,所有的更新會通過廣播的形式傳遞,展現(xiàn)給不同客戶端的數(shù)據(jù)順序可能是不一樣
阻抗匹配:為一個給定問題找到一個理想的解決方案,除了使用通用的解決方案,還應(yīng)該知道有什么可用的解決方案,從而找到最適合解決該問題的系統(tǒng)
2.表、行、列和單元格 最基本的單位是列,一列或多列形成一行,并由唯一的行健(row key)來確定存儲,一個表有若干行,其中每列可能有多個版本,在每個單元格中存儲了不同的值 一行由若干列組成,若干列又構(gòu)成了一個列族,一個列族的所有列存儲在同一個底層文件中,這個存儲文件叫做HFile,列族需要在表創(chuàng)建的時候就定義好,常見的引用列的格式為family:qualifer,列族的數(shù)量有限制,但是列的數(shù)量沒有限制,列值也沒有長度和類型的限制 在Hbase中空值是沒有任何消耗的,它們不占用任何的存儲空間 每列或每個單元格的值都具有時間戳,默認(rèn)由系統(tǒng)指定,也可以由用戶顯示設(shè)置 BigTable和Hbase的典型使用場景是webtable,存儲從互聯(lián)網(wǎng)中抓取的網(wǎng)頁 行數(shù)據(jù)的存儲操作都是原子的,可以讀寫任意數(shù)目的列,目前還不支持跨行事務(wù)和跨表事務(wù)
3.自動分區(qū) Hbase中擴(kuò)展和負(fù)載均衡的基本單元稱為region,region本質(zhì)上是以行健排序的連續(xù)存儲的區(qū)間
4.存儲API API提供了建表、刪表、增加列族和刪除列族的操作,同時還提供了修改表和列族元數(shù)據(jù)的功能 scanAPI提供了高效遍歷某個范圍的行的功能 在服務(wù)器的地址空間中執(zhí)行來自客戶端的代碼,支持這種功能的服務(wù)器框架叫做協(xié)處理器(coprocessor)
5.實現(xiàn) 每次更新數(shù)據(jù)時,都會先將數(shù)據(jù)記錄在提交日志上(commit log)中,在Hbase中這叫預(yù)寫日志(write-ahead log,WAL),然后才將這些數(shù)據(jù)寫入內(nèi)存中的memstore中,到超過給定的最大值值,就寫到磁盤的HFile文件,HFile是不可被改變的 合并HFile機(jī)制 minor合并:將多個小文件(默認(rèn)最小3個,最大10個)重寫到數(shù)據(jù)較少的大文件中,每個HFile都是經(jīng)過歸類的,所以合并的速度很快,只受磁盤IO的影響 major合并:將一個region中一個列族的若干個HFile重寫到一個新的HFile中,major合并能掃描所有的鍵值對,順序重寫全部的數(shù)據(jù)
二、客戶端API:基礎(chǔ)知識 1.概述 Hbase主要的客戶端接口是有org.apache.hadoop.hbase.client包中的HTable提供的HTable類提供的,通過這個類用戶可以向Hbase存儲和檢索數(shù)據(jù) 所有修改數(shù)據(jù)的操作都保證了行級別的原子性 創(chuàng)建HTable實例是有代價的,每個實例都需要掃描.META.表,以檢查該表是否存在,是否可用,以及一些其他操作,因此推薦用戶在每個線程(在開始時)只創(chuàng)建一次HTable實例,而后在客戶端應(yīng)用的生存期內(nèi)復(fù)用這個對象,如果用戶需要使用多個HTable實例,應(yīng)考慮使用HTablePool類 Hable(Configuration conf,"tableName")
2.CRUD操作 2.CRUD操作 2.1 put方法:向Hbase存儲數(shù)據(jù) 1)調(diào)用HTable的put方法格式: void put(Put put)或void put(List<put> puts) Put對象的構(gòu)造方法如下 創(chuàng)建Put實例之后,就可以使用add方法 向該實例添加數(shù)據(jù)了,每一次調(diào)用add()都可以特定的添加一列數(shù)據(jù),如果再加上一個時間戳選項,就能形成一個數(shù)據(jù)單元格。每個KeyValue實例包含器完成地址(行健、列族、列以及時間戳)和實際數(shù)據(jù),KeyValue是Hbase在存儲架構(gòu)中最底層的類 可以使用如下方法檢查是否存在特定的單元格,而不需要遍歷整個集合 通過客戶端訪問配置文件 當(dāng)你調(diào)用任何一個靜態(tài)create()方法時,代碼會嘗試使用當(dāng)前的java classpath來載入兩個配置文件hbase-default.xml和hbase-site.xml
Hbase的一個特殊功能是能為一個單元格存儲多個版本的數(shù)據(jù),這個版本使用一個時間戳,必須確保所有服務(wù)器的時間都是正確的,并且相互之間是同步的,默認(rèn)情況下Hbase會保留3個版本的數(shù)據(jù) 若需要頻繁的修改某些行,用戶有必要創(chuàng)建一個RowLock實例來防止其他用戶訪問這些行
2)KeyValue類 數(shù)據(jù)和坐標(biāo)都是以java的byte[]形式存儲的,使用這種類型的目的是允許存儲任意類型的數(shù)據(jù)
3)客戶端的寫緩沖區(qū) 每一個put操作實際上都是一個RPC操作,它將客戶端數(shù)據(jù)傳送到服務(wù)器后返回,這只適合小數(shù)據(jù)量的操作,Hbase的API配備了一個客戶端的寫緩沖區(qū)(write buffer),緩沖區(qū)負(fù)責(zé)收集put操作,然后調(diào)用RPC操作一次性將put送往服務(wù)器,全局交換機(jī)制控制著該緩沖區(qū)是否在使用,其方法如下 void setAutoFlush(boolean autoFlush) 默認(rèn)情況下,客戶端緩沖區(qū)是禁用的,可以通過將autoflush設(shè)置為false來激活緩沖區(qū),通過setBufferSize(long size)來配置客戶端寫緩沖區(qū)的大小,默認(rèn)大小是2M,為每一個用戶創(chuàng)建的HTable實例都設(shè)置緩沖器大小十分麻煩,可以在hbase-site.xml中添加一個較大的預(yù)設(shè)值,配置如下 <property> <name>hbase.client.write.value</name> <value>20971520</value> </property>
當(dāng)需要強(qiáng)制把數(shù)據(jù)寫到服務(wù)器端時,用flushCommit()函數(shù) 隱式刷寫:在用戶調(diào)用put()或setBufferSize()時觸發(fā),這兩個方法都會將目前占用的緩沖區(qū)大小和用戶配置的緩沖區(qū)大小進(jìn)行比較,此外調(diào)用HTable的close()也會無條件地隱式刷寫 用戶可以通過訪問ArrayList<Put> getWriteBuffer()來訪問客戶端寫緩沖區(qū)的內(nèi)容 如果用戶只存儲大單元格,那么客戶端緩沖區(qū)的作用就不大了 4)Put列表 調(diào)用void put(List<put> puts)時,客戶端先把所有的Put實例插入到本地寫緩沖區(qū)中,然后隱式的調(diào)用flushCache(),如果其中有失敗的Put實例(有些檢查是在客戶端完成的,如確認(rèn)Put實例的內(nèi)容是否為null或是否指定了列),那么后面的Put實例不會被添加到緩沖區(qū),也不會觸發(fā)刷寫命令,當(dāng)使用基于列表的Put調(diào)用時,用戶需要特別注意:用戶無法控制服務(wù)器執(zhí)行put的順序,如果要保證寫入的順序,需要小心地使用這個操作。
5)原子性操作compare-and-set 有一種特別的put調(diào)用,其能保證自身操作的原子性:checkAndPut(row,family,qualifier,value,Put put),這種有原子性的操作經(jīng)常被用于賬戶結(jié)余,狀態(tài)轉(zhuǎn)換或數(shù)據(jù)處理等場景 有一種特別的檢查通過checkAndPut()調(diào)用來完成,即只有在另外一個值不存在的情況下,才執(zhí)行這個修改,要執(zhí)行這種操作只需要將參數(shù)value設(shè)置為null Hbase提供的compare-and-set操作,只能檢查和修改同一行數(shù)據(jù)
2.2 get方法:客戶端獲取已存儲數(shù)據(jù)的方法 Result get(Get get); 1)單行Get 構(gòu)造Get實例: Get(rowkey) Get(rowkey,RowLock rowLock) 可以通過多種標(biāo)準(zhǔn)篩選目標(biāo)數(shù)據(jù): Get addFamily(family):只能取得一個指定的列族 Get addColumn(family,qualifier):獲取指定的列 Get setTimeRange(long minStamp,long masStamp)、 Get setTimeStamp(long timeStamp) Get setMaxVersions(int maxVersions)
2)result類 get()返回的結(jié)果包含所有匹配的單元格數(shù)據(jù),被封裝成一個Result類 常用方法: byte[] getValue(family,qualifier):取得特定單元格的值 byte[] value():返回第一列對應(yīng)的最新單元格的值 byte[] getRow():返回行健 int size():檢查是否有對應(yīng)的記錄 boolean isEmpty():檢查是否有對應(yīng)的記錄 KeyValue[] raw() List<KeyValue> list():用戶可以方便的迭代數(shù)據(jù) List<KeyValue> getColumn(family,qualifier) KeyValue getColumnLatest(family,qualifier) boolean containsColumn(family,qualifier) NavigableMap<byte[],NavigableMap[],NavigableMap<Long,byte[]>>> getMap():把請求返回的內(nèi)容都裝入一個Map類實例中,可以遍歷所有結(jié)果
3)get列表 Result[] get(List<Get> gets); boolean exists(Get get):查看存儲的數(shù)據(jù)是否存在 getRowOrBefore(row,family):
2.3 刪除方法 1)單行刪除 void delete(Delete delete) Delete實例構(gòu)造方法 Delete(rowkey) Delete(rowkey,long timestamp,RowLock rowLock) 常用方法 Delete deleteFamily(family[,long timestamp]) Delete deleteColumns(family,qualifier[,long timestamp]):沒指定timestamp,則刪除所有版本 Delete deleteColumn(family,qualifier[,long timestamp]):沒指定timestamp,則刪除最新版本
2)Delete的列表 void delete(List<Delete> deletes)
3)原子性操作compare-and-delete boolean checkAndDelete(row,qualifier,value,Delete delete)
2.4批處理操作 事實上許多基于列表的操作都是基于batch()方法是實現(xiàn)的。 方法: void batch(List<Row> actions,Object[] results) Object[] batch(List<Row> actions) 注:不可以將針對同一行數(shù)據(jù)的Put和Delete操作放在同一個批處理請求中 Row是Put、Get、Delete類的父類 當(dāng)用戶使用batch()功能時,Put實例不會被客戶端寫入緩沖區(qū)中緩沖,batch()請求是同步的,會把操作直接發(fā)送給服務(wù)器 兩種方法相同點: get、put、delete操作都支持,如果執(zhí)行時出現(xiàn)問題,客戶端將拋出異常并報告問題,都不適用客戶端的寫緩沖區(qū) 不同點: void batch(acitons,results):能訪問成功操作的結(jié)果,同時也可以獲取遠(yuǎn)程失敗的異常 Object[] batch(actions):只返回客戶端異常,不能訪問程序執(zhí)行中的部分結(jié)果 注:在檢查結(jié)果之前,所有的批處理操作都已經(jīng)執(zhí)行了:即使用戶收到異常,其他的操作也都已經(jīng)執(zhí)行了 批量處理可以感知暫時性錯誤(如NoServingRegionException)會多次重試這個操作,用戶可以通過調(diào)整hbase.client.retries.number配置項(默認(rèn)為10)來增加或減少重試次數(shù)
2.5 行鎖 region服務(wù)器提供一個行鎖的特性,保證了只有一個客戶端能獲取一行的數(shù)據(jù)相應(yīng)的鎖,同時對該行進(jìn)行修改。用戶應(yīng)該盡可能的避免使用行鎖,如果必須使用,那么一定要節(jié)約占用鎖的時間 Get不需要鎖:服務(wù)器應(yīng)用了一個多版本的并發(fā)控制機(jī)制來保證行級讀操作,只有當(dāng)一個變動被應(yīng)用到整個行之后,客戶端才能讀出這個改動,當(dāng)改動進(jìn)行中時,所有的客戶端讀取到的數(shù)據(jù)都是將是所有列以前的版本
2.6 掃描 類似于數(shù)據(jù)庫中的游標(biāo) ResultScanner getScanner(Scan scan) ResultScanner getScanner(family) ResultScanner getScanner(family,qualifier) scan類的構(gòu)造器 Scan() Scan(startRow,Filter filter) Scan(startRow) Scan(startRow,stopRow) 注:如果用戶只需要數(shù)據(jù)的子集,那么限制掃面的范圍就能發(fā)揮Hbase的優(yōu)勢,如果不讀取整個列族,那么整個列族的文件都不會讀取,這就是列族存儲架構(gòu)的優(yōu)勢 1)ResultScanner類 掃描操作不會通過一次RPC請求返回所有匹配的行,而是以"行"為單位進(jìn)行返回 Result next() Result[] next(int nbRows) void close() 要確保盡早釋放掃描器實例,當(dāng)使用完ResultScanner之后應(yīng)調(diào)用它的close()方法,釋放所有由掃描器控制的資源 就像行級鎖一樣,掃描器也使用同樣的租約超時限制,保護(hù)其不被時效的客戶端阻塞太久,通過如下配置 <property> <name>hbase.regionserver.lease.period</name> <value>120000</value> </property> 2)緩存與批量處理 如果一次RPC請求可以返回多行數(shù)據(jù),這樣使用掃描器更有意義,可以由掃描器緩存實現(xiàn),默認(rèn)情況下,這個緩存是關(guān)閉的。可以從兩個層面打開它 在表的層面,這個表的所有掃描器實例的緩存都會生效,用戶使用一下的Htable方法設(shè)置表級的掃描器緩存: void setScannerCaching(int scannerCaching), int getScannerCaching():默認(rèn)是1 在掃描器層面,這樣只會影響當(dāng)前的掃描實例,用戶使用一下的Scan類的方法設(shè)置掃描器級的掃描器緩存: void setCaching(int scannerCaching) int getCaching():默認(rèn)是1 此外用戶可以修改整個集群的配置 <property> <name>hbase.client.scanner.caching</name> <value>10</value> </property> 這樣所有scan的實例的掃描器緩存就都被設(shè)置為10了 注:當(dāng)數(shù)據(jù)量非常大的行,可能超過客戶端進(jìn)程的內(nèi)存容量,解決方法:使用Scan類的批量操作 setBatch(int batch) int getBatch() 緩存是面向行一級的操作,而批量是面向列一級的操作。
2.8 各種特性 1)Htable使用方法 void close():使用完一個HTable實例后,需要調(diào)用一次close(),它會刷寫所有客戶端緩沖的寫操作 HTableDescriptor getTableDescripor():每個表都使用一個HTableDescriptor實例類來定義表結(jié)構(gòu) Map<HRegion,HServerAddress> getRegionInfo():獲取某一行數(shù)據(jù)的具體位置信息
三、客戶端API:高級特性 1.過濾器 Get和Scan兩個類都支持過濾器,過濾器的基本接口叫做Filter,用戶還可以通過繼承Filter類實現(xiàn)自己的需求 1.1 比較運算符 1.2 比較器 1.3 Hbase提供的第一類:比較過濾器 用戶創(chuàng)建實例時需要一個比較運算符和一個比較器實例 CompareFilter(CompareOp op,WriteableByteArrayComparable valueComparator)
1.4 Hbase提供的第二類:專用過濾器
1.5 附加過濾器(應(yīng)用在其他過濾器上) 跳轉(zhuǎn)過濾器:SkipFilter(Filter filter):當(dāng)被包裝的過濾器遇到一個需要過濾的KeyValue時,用戶可以擴(kuò)展并過濾整行數(shù)據(jù) 全匹配過濾器:WhileMatchFilter
1.6 FilterList 需要多個過濾器共同限制返回到客戶端的結(jié)果 FilterList(List<Filter> rowFilters) FilterList(Operator op) FilterList(List<Filter> rowFilters,Operator op) 參數(shù)rowFilters以列表的形式組合過濾器,參數(shù)operator決定了組合它們的結(jié)果,默認(rèn)是為MUST_PASS_ALL,使用ArrayList可以保證過濾器的執(zhí)行順序與它們添加到列表中的順序一致
1.7 自定義過濾器 用戶可以實現(xiàn)Filter接口或者直接繼承FilterBase類
用戶自定義過濾器部署 編寫代碼-->打成jar包-->把文件發(fā)送到每個region服務(wù)器上-->修改hbase-env.sh文件如下 export HBASE_CLASSPATH="/hbase-book/target.aa.jar"-->重啟hbase
2 計數(shù)器 2.1 簡介 許多收集統(tǒng)計信息的應(yīng)用有點擊流和在線廣告意見,這些需要被收集到日志文件中用戶后續(xù)的分析,用戶可以使用計數(shù)器做實時統(tǒng)計,從而放棄延遲較高的批處理操作 雖然用戶可以一次更新多個計數(shù)器,但是它們必須屬于同一行,更新多個計數(shù)器需要通過獨立的API調(diào)用,即多個RPC請求 初始化計數(shù)器:用戶不用初始化計數(shù)器,當(dāng)用戶第一次使用計數(shù)器時,計數(shù)器自動設(shè)置為0,即當(dāng)用戶創(chuàng)建一個新列時,計數(shù)器的值是0 在shell中操作計數(shù)器使用incr '<table>','<row>','<column>',[increment-value]與get_counter '<table>','<row>','<column>' 客戶端API操作計數(shù)器 1)單計數(shù)器 只能操作一個計數(shù)器:用戶需要自己設(shè)定列,方法由HTable提供的 long incrementColumnValue(row,family,qualifier,long amount) long incrementColumnValue(row,family,qualifier,long amount,boolean writeToWAL) 2)多計數(shù)器 Result increment(Increment increment) 需要創(chuàng)建一個Increment實例,構(gòu)造方法如下 Increment() Increment(row) Increment(row,RowLock rowLock) 向其中加入實際的計數(shù)器:addColumn(family,qualifier,long maxStamp)
3.協(xié)處理器 協(xié)處理器允許用戶在region服務(wù)器上運行自己的代碼,也就是允許用戶執(zhí)行region級的操作,并可以使用如觸發(fā)器類似的功能 另一類適合使用協(xié)處理器的場景就是權(quán)限控制 協(xié)處理器框架提供了一些類,用戶可以通過繼承這些類擴(kuò)展自己的功能,主要有兩類,即observer和endpoint observer:回調(diào)函數(shù)(也被稱為鉤子函數(shù),hook)在一些特定時間發(fā)生時。這些事件包括用戶產(chǎn)生的事件和服務(wù)器內(nèi)部自動產(chǎn)生的事件 RegionObserver:用戶可以用這種處理器處理數(shù)據(jù)修改事件,它們與表的region聯(lián)系緊密 MasterObserver:可以被用作管理或DDL類型的操作,這些是集群級事件 WALObserver:提供控制WAL的鉤子函數(shù)
endpoint:通過添加一些遠(yuǎn)程調(diào)用來動態(tài)擴(kuò)展RPC協(xié)議,可以把它理解為與RDBMS中類似的存儲過程。endpoint可以與observer的實現(xiàn)組合起來直接作用于服務(wù)器的狀態(tài)
Coprocesspor類 所有協(xié)處理器的類都必須實現(xiàn)這個接口,它定義了協(xié)處理器的基本預(yù)定。提供了兩個被應(yīng)用于框架的枚舉類Priority(SYSTEM,USER)和State 待續(xù)!!!!
4.HtablePool 為Hbase集群提供一個客戶端連接池,用戶可以通過以下任意一個構(gòu)造器來創(chuàng)建池: HTablePool() HtablePool(Configuration conf,int maxSize) HtablePool(Configuration conf,int maxSize,HTableInterfaceFactory fac) HTableInterfaceFactory:用戶可以創(chuàng)建自定義的工廠類,例如,為Htable實例使用特定的配置,或可以讓實例完成一些初始化操作。如果用戶想自己擴(kuò)展HtableInterfaceFactory,則必須實現(xiàn)兩個方法createHTableInterface(conf,tableName)和releaseHtableInterface 使用表實例池方式:getTable(String tableName);getTable(byte[] tableName);void putTable(HtableInterface table)
5.連接管理 每個HTable實例都需要建立和遠(yuǎn)程主機(jī)的連接,這些連接在內(nèi)部使用HConnection類表示,被HConnectionManager類管理并共享。用戶沒必要和這兩個類打交道,只需要創(chuàng)建一個Configuration實例,然后利用客戶端API使用這些類。 Hbase內(nèi)部使用鍵值映射來存儲連接,使用Configuration實例作為鍵值映射的鍵。 HtablePool類,所有連接池中的Htable實例都自動共用一個提供的Configuration實例,共享它們的連接。 共享連接的缺點在于釋放,如果用戶不顯示關(guān)閉連接,它將一直存在,直到客戶端退出,建議用戶不在需要使用Htable時主動調(diào)用其close(),釋放資源,以下是顯式清理連接方法 deleteConnection(Configuration conf,boolean stop); deleteAllConnection(boolean stop)
四、客戶端API:管理功能 1.模式定義 1)表:使用表的主要原因是控制表中的所有列以達(dá)到共享表內(nèi)的某些特性的目的 表描述符的構(gòu)造函數(shù): HTableDescriptor(); HTableDescriptor(String name); HTableDescriptor(byte[] name); HTableDescriptor(HTableDescriptor desc);
任意不相交的系統(tǒng)間的遠(yuǎn)程通信都使用到了Hadoop RPC框架,需要遠(yuǎn)程方法中參數(shù)都實現(xiàn)Writeable接口,進(jìn)而能夠序列化對象并遠(yuǎn)程傳輸
2)表屬性 表名一定不能以".","-"開頭,表名只能包含拉丁字母或數(shù)字、下劃線、".","-"
列族: void addFamily(HColumnDescriptor family) boolean hasFamily(byte[] c) HColumnDescriptor[] getColumnFamilies() HColumnDescriptor getFamily(byte[] column)
文件大小限制: long getMaxFileSize() void setMaxFileSize(long maxFileSize) 如果一個列族的存儲單元已使用的存儲空間超過了大小限制,region將發(fā)生拆分,maxFileSize默認(rèn)值是256M 這個參數(shù)只是大致的預(yù)期值,而在某些特殊條件下,文件大小可能超過這個預(yù)期值(一行數(shù)據(jù)不能跨region存儲)
只讀:默認(rèn)所有的表都可寫,對于特殊的表來說,只讀參數(shù)有特殊的用途。調(diào)用setReadOnly(boolean readOnly)設(shè)置
memstore刷寫大小:寫操作會寫入到寫緩沖區(qū),人后按照合適的條件順序?qū)懭氲揭粋€新的存儲文件(磁盤)中,可以通過setMemStoreFlushSize(long memstoreFlushSize),這個memstoreFlushSize的默認(rèn)值是64MB
延遲日志刷寫: Hbase有兩種將WAL保存到磁盤的方式,一種是延遲日志刷寫,另一種不是,通過setDeferredLogFlush(boolean isDeferredLogFlush),isDeferredLogFlush的默認(rèn)值為false
3)列族 列族定義了所有列的共享信息,并且可以通過客戶端創(chuàng)建任意數(shù)量的列。定位到某個具體的列需要列族名和列名合并在一起,以:分隔,如family:qualifier 構(gòu)造方法: 列族名:getName()或getNameAsString() 不能被重命名,通常的做法是新建一個列族,然后使用API從舊列族中復(fù)制數(shù)據(jù)到新列族 列族名不能以"."開頭,也不能包含":"、"\"或ISO控制符
最大版本數(shù):所有列族都限定了每個值能夠保留的最大版本數(shù),Hbase會移除超過最大版本數(shù)的數(shù)據(jù),通過setMaxVersions(int maxVersion)設(shè)置,這個maxVersion默認(rèn)為3.
壓縮: Hbase支持插件式的壓縮算法,允許用戶選擇最合適的壓縮算法 塊大小: 在Hbase中,所有的存儲文件都被劃分為若干個小存儲塊,這些小存儲塊在get或scan操作時會加載到內(nèi)存中,通過setBlockSize(int size)設(shè)置,默認(rèn)大小是64KB 注:HFile的不同于HDFS中的塊,HDFS提到的塊是用于拆分大文件以提供分布式存儲,且便于MapReduce框架進(jìn)行并行計算的存儲單元;而HBase中的塊主要用于高效加載和緩沖數(shù)據(jù)
緩存塊: Hbase順序的讀取一個數(shù)據(jù)塊到內(nèi)存緩存中,這個參數(shù)默認(rèn)是為true,每次讀取的塊都會緩存到內(nèi)存中,但是如果順序讀取某個特定的列族,最好將這個屬性設(shè)置為false,通過setBlockCacheEnabled(boolean blockCacheEnabled)方法設(shè)置
生存期TTL: Hbase支持版本數(shù)據(jù)保存的時間,TTL設(shè)置了一個基于時間戳的臨界值,內(nèi)部管理會自動檢查TTL的值是否達(dá)到上限,在major合并過程中時間戳被判定為超過TTL的數(shù)據(jù)會被刪掉,可以通過setTimeToLive(int timestamp)方法設(shè)置,TTL的參數(shù)為秒,默認(rèn)值是Integer.MAX_VALUE,理解為永久保留
在內(nèi)存中:setInMemory(boolean inMemory) 將inMemory設(shè)置為true只是一種承諾,或者說高優(yōu)先級。在正常數(shù)據(jù)讀取過程中,塊數(shù)據(jù)被加載到緩沖區(qū)中并長期駐留在內(nèi)存中,除非堆壓力過大,這個時候才會強(qiáng)制從內(nèi)存中卸載這部分?jǐn)?shù)據(jù)
布隆過濾器: 能夠減少特定訪問模式下的查詢時間,由于這種模式增加了內(nèi)存和存儲的負(fù)擔(dān),這個模式默認(rèn)為關(guān)閉狀態(tài) 復(fù)制范圍:Hbase提供跨集群同步的功能,本地集群的數(shù)據(jù)更新可以及時同步到其他集群,復(fù)制范圍參數(shù)默認(rèn)為0,即這個功能處于關(guān)閉狀態(tài)。可以通過setScope(int scope)設(shè)置,1表示開啟實時同步
2.HBaseAdmin HBaseAdmin提供了創(chuàng)建表、列族、檢查表是否存在,修改表結(jié)構(gòu)和列族結(jié)構(gòu)、以及刪除表功能 構(gòu)造方法:HbaseAdmin(Configuration conf)
1)表操作 建表: void createTable(HTableDescriptor desc) void createTable(HTableDescriptor desc,byte[] startKey,byte[] endKey,int numRegions) void createTable(HTableDescriptor desc,byte[][] splitKeys) void createTableAsync(HTableDescriptor desc,byte[][] splitKeys) HTable類中的方法getStartEndKey()來獲取所有region的邊界
獲取所有表的列表,以及判斷是否存在 boolean tableExists(String tableName) boolean tableExists(byte[] tableName) HTableDescriptor[] listTables() HTableDescriptor getTableDescriptor(byte[] tableName)
刪除表: void deleteTable(String tableName) void deleteTable(byte[] tableName)
在刪除表之前需要將表禁用,region服務(wù)器會先將內(nèi)存中近期內(nèi)還未提交的已修改的數(shù)據(jù)刷寫到磁盤,然后關(guān)閉所有region,并更新這樣表的元數(shù)據(jù),將所有region標(biāo)記為下線狀態(tài)。
2)集群管理 允許用戶查看集群當(dāng)前的狀態(tài): static void checkHBaseAvailable(Configuration) ClusterStatus getClusterStatus() void closeRegion(String regionname,String hostAndport) 注:所有可用表的region都應(yīng)該是在線狀態(tài) void majorCompact(String tableNameOrRegionName)
五、可用的客戶端 1.REST、Thrift,Avro介紹 它們都支持大量的語言,Protocol Buffer與Thrift和Avro最大的不同是它沒有自己的RPC堆,而它生成的RPC定義需要被后來其他的RPC庫使用,Hbase提供了REST、Thrift、Avro的輔助服務(wù),它們可以實現(xiàn)成專門的網(wǎng)關(guān)服務(wù),這些服務(wù)運行在共享或?qū)S玫臋C(jī)器上。Thrift和Avro都有各自的RPC實現(xiàn),所以網(wǎng)關(guān)服務(wù)僅是在它們的基礎(chǔ)上進(jìn)行了封裝,至于REST,HBase則采用了自己的實現(xiàn),并提供了訪問存儲數(shù)據(jù)的路徑。 每個請求使用一個服務(wù)而非建立一個連接的優(yōu)勢在于用戶可以復(fù)用連接來獲得最優(yōu)性能。 2.交互 1)使用原生Java:直接使用HTable并通過原生的RPC調(diào)用與HBase服務(wù)器進(jìn)行交互。 2)REST: 操作:基于REST服務(wù)的客戶端是在能夠與HBase通信之前需要先啟動REST網(wǎng)關(guān)服務(wù),使用hbase-daemon.sh start rest命令。REST服務(wù)提供了HBase表提供的所有操作,REST服務(wù)器返回的值都經(jīng)過了base64Binary編碼。 支持的格式:通過使用HTTP Content-Type和Accept頭,調(diào)用者可以自動選擇發(fā)送和接收信息的數(shù)據(jù)格式 Plain(text/plain): XML(text/xml):默認(rèn)的存儲和查詢格式是XML JSON(application/json):curl -H "Accept:application/json" http://<servername>:testtable/%01%02%03/colfam1:col1
REST的java客戶端: REST服務(wù)器同樣具有全面的java客戶端API,位于org.apache.hadoop.hbase.rest.client包中,其中核心類為RemoteHTable和RemoteAdmin
3)Thrift 在使用Thrift之前需要安裝Thrift,并且需要啟動HBase提供的Thrift Server 啟動Thrift命令:hbase-daemon.sh start thrift
4)Avro 在使用Thrift之前需要安裝Avro,并且需要啟動HBase提供的Avro Server 啟動Avro命令:hbase-daemon.sh start Avro
3.批量處理客戶端 1)Mapreduce:兩種方式,原生java API或Clojure 2)Hive Hive與Hbase之前的版本需要匹配,細(xì)微的RPC變化可能影響交互 3)pig 4)Cascading
4.shell 1)命令 引用名:命令行要求在使用表名和列名時需要通過單引號或雙引號對其進(jìn)行引用。 引用值:命令行支持二進(jìn)制、八進(jìn)制、十六進(jìn)制的輸入和輸出,用戶在引用時必須使用雙引號 使用逗號分隔參數(shù) Ruby散列屬性: 一些命令中需要設(shè)置鍵值對屬性,使用Ruby散列按照以下方式來完成 {'key1'=>'val1','key2'=>'val2',...}
DDL命令 alter 使用modifyTable()修改現(xiàn)有表結(jié)構(gòu)
DML命令:
工具命令: assgn 分配一個region到一臺region服務(wù)器中
復(fù)制命令:
腳本: 可以使用Nagios或其他監(jiān)控工具發(fā)送腳本 用戶還以使用管道的形式運行命令
5.基于Web UI 1)master的web默認(rèn)端口是60010,region服務(wù)默認(rèn)端口是60030
六、與Mapreduce集成 1.類 InputFormat InputFormat負(fù)責(zé):拆分輸入數(shù)據(jù),同時返回一個RecordReader實例,定義了鍵值對象的類,并提供了next()遍歷數(shù)據(jù) 就HBase而言,它提供了一組專用的實現(xiàn),叫TableInputFormatBase,該實現(xiàn)的子類是TableInputFormat mapper HBase提供了一個TableMapper類,將鍵的類型強(qiáng)制轉(zhuǎn)換為ImmutableBytesWritable類,同時將改制的類型強(qiáng)制轉(zhuǎn)換為Result類型,TableMapper類沒有實現(xiàn)具體的功能,它只是添加了鍵值對的簽名 Reducer HBase提供了一個TableReducer類 OutputFormat Hbase提供了一個TableOutputFormat
2.支撐類 Mapreduce的支撐類與TableMapReduceUtil類一同協(xié)作在HBase上執(zhí)行Mapreduce任務(wù),它有一個靜態(tài)方法能配置作業(yè),病并使作業(yè)可以使用Hbase作為數(shù)據(jù)源或目標(biāo)
3.在HBase上的Mapreduce 當(dāng)運行Mapreduce作業(yè)所需庫中的文件不是綁定在Hadoop或Mapreduce框架中時,用戶就必須確保這些庫文在作業(yè)之前已經(jīng)可用,用戶一般兩個選擇:在所有的任務(wù)節(jié)點上準(zhǔn)備靜態(tài)的庫或直接提供作業(yè)所需的所有庫 1)靜態(tài)配置: 將jar文件復(fù)制到所有節(jié)點的常用路徑中 將這些jar文件的完整路徑寫入hadoop-env.sh配置文件中,按照如右方式編輯HADOOP-CLASSPATH變量:HADOOP-CLASSPATH="<extra-entries>":HADOOP-CLASSPATH 重啟所有的任務(wù)的NodeManager使變更生效 2)動態(tài)配置:Hadoop有一個特殊的功能,它可以讀取操作目錄中/lib目錄下所包含的所有庫的jar文件,用戶可以使用此功能生成所謂的胖jar文件,胖jar文件使用maven的Maven Assembly插件
七、架構(gòu) 1.數(shù)據(jù)查找和傳輸 1)B+樹:它的葉節(jié)點項目鏈接并且有序,能夠通過主鍵對記錄進(jìn)行高效的插入、查找以及刪除,它表能為一個動態(tài)、多層并由上下界的索引,同時要注意維護(hù)每一段所包含的鍵數(shù)目
2)LSM樹(log-structured merge-tree):輸入數(shù)據(jù)首先存儲在日志文件,這些文件內(nèi)的數(shù)據(jù)完全有序,當(dāng)有日志文件被修改時,對應(yīng)的更新會被保存在內(nèi)存中加速查詢,修改數(shù)據(jù)文件的操作通過滾動合并完成。
2.存儲 1)概覽 注:HBase主要處理兩種文件:一種是WAL文件,另一種是實際的數(shù)據(jù)文件,這兩種文件都是由HRegionServer管理
2)讀取數(shù)據(jù)流程
HRegionServer負(fù)責(zé)打開region,并創(chuàng)建一個對應(yīng)的HRegion實例,它會為每個表的HColumnFamily創(chuàng)建一個Store實例,每個Store實例包含多個StoreFile(HFile的輕量級封裝)和一個MemStore,一個HRegionServer共享一個HLog實例
3)寫路徑
4)region拆分
5)合并 minor合并:負(fù)責(zé)重寫最后生成的幾個文件到一個更大的文件中,文件數(shù)量有hbase.hstore.compaction.min決定,默認(rèn)值是3,minor合并處理的最大文件數(shù)默認(rèn)為10,用戶可以通過hbase.hstore.compaction.max來配置 major合并:把所有文件壓縮成一個單獨的文件,在memstore被刷寫到磁盤后出發(fā)檢查,或shell命令major-compact后觸發(fā),配置相關(guān)參數(shù) hbase.hregion.majorcompaction(默認(rèn)為24小時)和hbase.hregion.majorcompaction.jitter(默認(rèn)為0.2)
6)HFile 注:文件長度可變,唯一固定的塊是File Info和Trailer,Trailer是指向其他快遞的指針,塊大小是由HColumnDescriptor配置的,該配置可以在創(chuàng)建表的時候由用戶指定,默認(rèn)大小時64K,每一個塊都包含一個magic頭部和一定數(shù)量的序列化的KeyValue實例
7)WAL WAL存儲了對數(shù)據(jù)的所有更改,實現(xiàn)了WAL的類叫HLog類,HLog類的一個特性就是跟蹤修改,通過使用序列號來實現(xiàn)
3.ZooKeeper HBase使用ZooKeeper作為其協(xié)同服務(wù)組件,其主要功能包括跟蹤region服務(wù)器、保存root region的地址等 HBase建立的znode列表,默認(rèn)為/hbase,這個znode的名稱由zookeeper.znode.parent屬性決定, 以下是znode的列表以及他們的作用 /hbase/hbaseid:包括clusterID,與存儲在HDFS上的hbase.id文件內(nèi)容相同。 /hbase/master:包含服務(wù)器名稱 /hbase/replication:包含副本信息 /hbase/root-region-server:包含-ROOT-region所在的region服務(wù)器的機(jī)器名,這個經(jīng)常在region定位中使用 /hbase/rs:所偶region服務(wù)器的根節(jié)點,集群使用它來跟蹤服務(wù)器異常 /hbase/shutdown:集群的啟動事假和關(guān)閉時間 /hbase/table:當(dāng)表被禁用,信息會被添加到這個znode之下
4.復(fù)制 HBase復(fù)制可以作為一種災(zāi)難恢復(fù)的方法,并且可以提供HBase層的高可用性 HBase復(fù)制中最基本的機(jī)構(gòu)模式是"主推送",因為每個region服務(wù)器都有自己的WAL,所以很容易保存現(xiàn)在正在復(fù)制的位置 注:參與復(fù)制的集群可以不相等,主機(jī)群會通過隨機(jī)分配盡量均衡從集群的負(fù)載
1)常規(guī)處理 客戶端發(fā)送Put、Delete、或Increment到region服務(wù)器,這些請求包含的鍵值對會被region服務(wù)器轉(zhuǎn)化為WALEdit,同時WALEdit會被復(fù)制程序檢查,并以列族為單元復(fù)制數(shù)據(jù)。修改被添加到WAL中,并把實際數(shù)據(jù)添加到Memstore。 2)沒有反饋的從集群 如果從集群的region服務(wù)器沒有響應(yīng)rpc請求,主集群的region服務(wù)器將會睡眠并按照配置的次數(shù)重試。如果從集群的region服務(wù)器還是不可用,主機(jī)全會重新選擇一臺其他的機(jī)器來提交修改 3)挑選要復(fù)制的目標(biāo)集群 主集群的region服務(wù)器連接從集群的ZooKeeper群組,然后掃描/hbase/rs目錄來發(fā)現(xiàn)所有可用的并隨機(jī)選擇一部分服務(wù)器來復(fù)制數(shù)據(jù)(默認(rèn)是10%)
八、高級用法 1.rowkey設(shè)計 1)高表與寬表 HBase中的表可以設(shè)計為高表和寬表,前者指表中列少兒行多,后者則正好相反。用戶應(yīng)當(dāng)盡量將需要查詢的維度或信息存儲在行健中,應(yīng)為用它篩選的效率最高 此外,HBase只能按行分片,因此高表更有優(yōu)勢
2)時間序列:當(dāng)處理流式事件時,最常用的就是按時間序列組織數(shù)據(jù),這些數(shù)據(jù)會被有序的存儲在一個特定的范圍內(nèi),到時系統(tǒng)產(chǎn)生讀寫熱點,解決這個問題的方法就是想辦法將數(shù)據(jù)分散到所有的region服務(wù)器上,有很多中方法,例如在行鍵前價格,通常情況下如下選擇
時間順序關(guān)系 每個列族下的列可以作為輔助索引單獨進(jìn)行排序,主要內(nèi)容在主要的列族下,索引放在另外一個列族下,為了編碼創(chuàng)建太多的列族,可以把所有輔助索引存儲在有一個單獨的列族下,同時列鍵的最左端使用索引ID這個前綴來表示不同的順序
2.輔助索引 輔助索引存儲了新坐標(biāo)和現(xiàn)有坐標(biāo)之間的映射關(guān)系,一些為可行的解決方案 由客戶端管理索引: 把責(zé)任完全轉(zhuǎn)移到應(yīng)用層的典型做法是把一個數(shù)據(jù)表和一個查找/映射表結(jié)合起來,每當(dāng)程序?qū)憯?shù)據(jù)表的時候,它也同時更新映射表(輔助索引表)。讀數(shù)據(jù)時可以直接在主表進(jìn)行查詢,從輔助索引表中先查找原表的行鍵,再在原表中讀取實際數(shù)據(jù)。優(yōu)點:用戶可以按照需求設(shè)計映射表。缺點:Hbase不能保證跨行操作的原子性 用戶可以自由設(shè)計主索引和輔助索引之間的映射關(guān)系時,必須接受的缺點是用戶需要實現(xiàn)所有存儲和查找數(shù)據(jù)必需的方法
帶索引的事務(wù)型HBase 開源的ITHBase,擴(kuò)展了HBase,最核心的擴(kuò)展是增加了保證所有輔助索引,提供了一個IndexedTableDescriptor,提供了數(shù)據(jù)表的輔助索引操作支持,大多數(shù)類被添加了索引支持功能的類替換了
帶索引的HBase IHBase是完全在內(nèi)存中維護(hù)索引,索引永遠(yuǎn)都是同步的,不需要額外的事務(wù)控制,索引的定義由IdxIndexDescriptor類完成
3.搜索集成 使用任意關(guān)鍵字來搜索數(shù)據(jù),滿足這種需要往往是集成一個完整的搜索引擎 Lucene:獨立于HBase使用的Lucene或其他派生類的解決方案可以通過Mapreduce建立索引。 HBasene:選擇的方法是直接在HBase內(nèi)部建立搜索索引,同時為用戶提供Lucene的API,它把每個文檔的字段、詞存儲在一個單獨的行,同時包含這個詞的文檔儲存在這一行的列中
九、監(jiān)控集群 1.監(jiān)控框架 每個HBase進(jìn)程都會提供一系列監(jiān)控指標(biāo),這些監(jiān)控指標(biāo)可以被各種監(jiān)控API和工具使用,包括JMX和Ganglia。每種服務(wù)器都有多組監(jiān)控指標(biāo),這些監(jiān)控指標(biāo)按子系統(tǒng)分組并隸屬于一種服務(wù)器 HBase使用Hadoop的監(jiān)控框架,并繼承了其所有類和特性,這個框架基于MetricsContext接口來處理監(jiān)控數(shù)據(jù)點的生成,并使用這些數(shù)據(jù)點監(jiān)控和繪圖 1)可用的實現(xiàn)列表: GangliaContext:用來推送監(jiān)控指標(biāo)到Ganglia FileContext:將監(jiān)控指標(biāo)寫入磁盤上一個文件中 TimeStampingFileContext:將監(jiān)控指標(biāo)寫入磁盤上一個文件中,但是為每個監(jiān)控指標(biāo)添加一個時間戳前綴 CompositeContext:允許為監(jiān)控指標(biāo)生成不止一個上下文 NullContext:監(jiān)控指標(biāo)框架的關(guān)閉選項,使用這個上下文時,不生成也不聚合監(jiān)控指標(biāo) NullContextWithUpdateThread:不生成任何監(jiān)控指標(biāo),但是啟動聚合統(tǒng)計線程。這種上下文在通過JMX檢索監(jiān)控指標(biāo)時使用
多重監(jiān)控指標(biāo)使用MetricsRecored分組,來描述一個具體的子系統(tǒng)。HBase使用這些組分別來保存master、region機(jī)器,以及其他服務(wù)器的統(tǒng)計信息,每個組都有唯一的名字:<context-name>.<record-name>.<metrics-name>。上下文有內(nèi)置的定時器來觸發(fā)并將監(jiān)控指標(biāo)推送至目標(biāo)
2)各種指標(biāo)類型: 整型值:(IV) 長整型值:(LV) 速率(R):一個代表速率的浮點型值,可以是每秒操作或者消息數(shù) 字符串:存儲靜態(tài)的,基于文本的信息。并用來報告HBase版本信息和構(gòu)建時間 時間變化整型(TVI):上下文會維護(hù)一個單調(diào)遞增累加計數(shù)器。框架使用這個方法對各種消息進(jìn)行技術(shù) 時間變化長整型(TVL):用于增速較快的計數(shù)器 時間變化率(TVR):需要追蹤操作數(shù)或消息的數(shù)量,以及完成操作所用的時間,通常用來計算一次操作完成的平均時間 持續(xù)型時間變化率(PTVR):添加了對持續(xù)的周期性的監(jiān)控指標(biāo)的必要的支持。 3)master提供的監(jiān)控指標(biāo)
4)region服務(wù)器監(jiān)控指標(biāo): 塊緩存監(jiān)控指標(biāo) 塊緩存用來保存底層HFile從HDFS讀取的存儲塊。count(LV)監(jiān)控指標(biāo)反映了當(dāng)前緩存中保存的塊數(shù)目,size(LV)監(jiān)控指標(biāo)時占用java堆空間大小,free(LV)監(jiān)控指標(biāo)時堆空間為緩存保留的可用空間,evicted(LV)反映了命中緩存總數(shù)與請求緩存總數(shù)的關(guān)系 塊緩存追蹤追蹤緩存命中hit(LV)和緩存失效miss(LV)的數(shù)目,以及命中率hit radio(LV),其反映了命中緩存總數(shù)與請求緩存總數(shù)的關(guān)系。所有讀操作使用緩存,不管用戶是否制定過將使用的塊保留在緩存中。使用setCacheBlocks()僅僅影響塊的保留策略 合并監(jiān)控 compaction size(PTVR)和compaction time(PTVR)分別代表需要合并的存儲文件總大小和操作花費時間 compaction queue size:用來監(jiān)測一個region服務(wù)器有多少文件當(dāng)前正在排隊等待合并
memstore監(jiān)控指標(biāo) memstore size MB(IV):服務(wù)器上所有memstore總共占用的堆大小 flush queue zie(IV):將要被刷寫的region的數(shù)目
存儲監(jiān)控指標(biāo): store files(IV):所有存儲文件的數(shù)目 store file index MB(IV):所有存儲文件的塊索引和元數(shù)據(jù)的總和大小
I/O監(jiān)控指標(biāo): fs read latency(TVR):文件系統(tǒng)的讀延遲 fs write latency:寫延遲 fs sync latency:統(tǒng)計了預(yù)寫日志記錄同步到文件系統(tǒng)的延遲
RPC監(jiān)控指標(biāo) Ganglia 組成: Ganglia監(jiān)控守護(hù)進(jìn)程(gmond):監(jiān)控守護(hù)進(jìn)程需要在每臺需要監(jiān)控的機(jī)器上運行,它搜集本地數(shù)據(jù),準(zhǔn)備統(tǒng)計,然后被其他系統(tǒng)拉取。通過單一或組播方網(wǎng)絡(luò)消息傳播的主機(jī)變化情況,使用組播方式,每個監(jiān)控守護(hù)進(jìn)程可以獲取集群完整狀態(tài),所有的服務(wù)器擁有同樣的組播地址 Ganglia元數(shù)據(jù)守護(hù)進(jìn)程(gmetad):元數(shù)據(jù)守護(hù)進(jìn)程安裝在一個中心節(jié)點上,作為整個集群的管理節(jié)點。元數(shù)據(jù)守護(hù)進(jìn)程從一個或多個監(jiān)控守護(hù)進(jìn)程拉去數(shù)據(jù)來獲取整個集群的狀態(tài),然后使用RDTool將這些信息存放在一個用于輪詢的時間序列數(shù)據(jù)庫中。 GangliaPHP:展示統(tǒng)計信息
十、性能優(yōu)化 1.垃圾回收優(yōu)化 垃圾回收時master通常不會產(chǎn)生問題,只需要添加到region服務(wù)器的啟動參數(shù)中。 用戶可以通過向hbase-env.sh配置文件中添加HBASE_OPTS或者HBASE_REGIONSERVER_OPTS變量來設(shè)置垃圾回收的相關(guān)選項。后者僅影響region服務(wù)器進(jìn)程,也是推薦的修改方式 指定新生代的方式:-XX:MaxNewSize=128m -XX:NewSize=128m或-Xmn128m 注意:默認(rèn)值對于多數(shù)region服務(wù)器面對的負(fù)載還是太小,所以她必須增大
建議在JRE日志中輸入垃圾回收的詳細(xì)信息,通過添加以下JRE選項: -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:$HBASE-HOME/logs/gc-hbase.log 該日志不會按日期定時滾動,需要手動處理(例如:使用基于crontab的每日滾動轉(zhuǎn)存任務(wù))
通過不同的JRE參數(shù)來指定不同的垃圾回收實現(xiàn)策略,推薦的值是: -XX:+UseParNewGC and -XX:+UseConcMarkSweepGC UseParNewGC:停止運行java進(jìn)程二期清空年輕代堆 ConcMarkSweepGC:不停止java進(jìn)程的情況下異步并行的完成工作
2.預(yù)拆分region 管理接口中createTable()方法或shell中的create命令可以接受列表形式提供的拆分行健作為參數(shù)
3.負(fù)載均衡: master有一個內(nèi)置的叫做均衡器的特性,在默認(rèn)的情況下,均衡器每五分鐘運行一次,可以通過hbase.balancer.period屬性設(shè)置 均衡器有一個可以限制自身運行時間的上限,用戶可以通過hbase.balance.max.balancing屬性來設(shè)置,默認(rèn)為均衡器間隔周期的一半
4.合并region HBase集成了一個工具能夠讓用戶在集群沒有工作時河北那個兩個相鄰的region,工具為org.apache.hadoop.hbase.util.Merge
5.客戶端API:最佳實踐 1)禁止自動刷寫:當(dāng)有大量的寫入操作時,使用setAutoFlush(false)方法,確認(rèn)HTable自動刷寫的特性已經(jīng)關(guān)閉,如果禁用了自動刷寫,add(Put)操作指導(dǎo)寫緩沖區(qū)被填滿時才會被送出,可以調(diào)用HTable的flushCommits()方法顯式刷寫數(shù)據(jù),調(diào)用HTable的close()也會隱式調(diào)用flushCommits() 2)使用掃面緩存:如果HBase被用作一個MapReduce作業(yè)的輸入源,請最好將作為MapReduce作業(yè)輸入掃描器實例的緩存用setCaching()方法設(shè)置為比默認(rèn)值1大得多的值,使用默認(rèn)值意味著map任務(wù)處理每條記錄都請求region服務(wù)器 3)限定掃描范圍 當(dāng)Scan用來處理大量行時注意哪些屬性被選中了,從而限制掃描范圍 4)關(guān)閉ResultScanner 如果用戶忘記關(guān)閉由HTable.getScanner()返回的ResultScanner實例,則可能對服務(wù)器端造成影響,一定要在try/catche的finally塊中關(guān)閉ResultScanner 5)塊緩存用法 Scan實例通過setCacheBlock()方法來設(shè)置使用region服務(wù)器中的塊緩存,如果MapReduce作業(yè)中使用掃描,這個方法應(yīng)當(dāng)被設(shè)為false,對于那些頻繁訪問行的行,建議使用塊緩存 6)關(guān)閉Put上WAL 提高吞吐量方式,使用Put的writeToWAL(false)來關(guān)閉WAL,不過一旦region服務(wù)器故障就會丟失數(shù)據(jù)
6.配置 1)減少Zookeeper超時 默認(rèn)在region服務(wù)器和ZooKeeper集群之間的超時時間是3分鐘,通過zookeeper.session.timeout屬性設(shè)置,在改變值之前,確認(rèn)用戶服務(wù)器上JVM的垃圾回收機(jī)制是受控的 2)增加處理線程 hbase.regionserver.handler.count屬性定義了響應(yīng)外部用戶訪問數(shù)據(jù)表請求的線程數(shù),默認(rèn)值10有些偏小,將這個值設(shè)置的高也有可能產(chǎn)生問題,并發(fā)的寫請求造成壓力 3)增加堆大小 如果用戶使用更好的服務(wù)器,可以給HBase分配8G內(nèi)存或更大,用戶可以在hbase-env.sh文件中調(diào)整HBASE_HEAPSIZE的設(shè)置,master會默認(rèn)1GB的堆運行,region服務(wù)器則會按照用戶單獨指定的堆空間運行 4)啟動數(shù)據(jù)壓縮 用戶應(yīng)當(dāng)為存儲文件啟動壓縮,尤其推薦使用Snappy或LZO壓縮 5)增加region大小 默認(rèn)region大小為256M,用戶可以增加其大小,但是該參數(shù)的大小要仔細(xì)評估 6)調(diào)整塊緩存大小 控制堆中塊緩存大小的屬性是一個浮動點數(shù)類型的百分比,默認(rèn)值是20%,可以通過perf.hfile.block.cache.size屬性改變這個值,看看是否存在許多塊被換出的情況,如果存在,則可以考慮增加塊緩存的大小。用戶負(fù)載大多數(shù)為讀請求是另一個增加緩存大小的原因。 7)調(diào)整memstore限制 內(nèi)存存儲占用的堆大小用hbase.regionserver.global.memstore.upperLimit屬性來配置,默認(rèn)值為40%,此外hbase.regionserver.global.memstore.lowerLimit屬性(默認(rèn)為35%)用戶控制當(dāng)服務(wù)器清空memstore之后剩余的大小,當(dāng)用戶主要在處理讀請求時,可以考慮通知減少memstore的上線限來增加塊緩存的空間 8)增加阻塞時存儲文件數(shù)目 這個值通過hbase.hstore.blockingStoreFiles屬性來設(shè)置的,它決定了當(dāng)存儲文件的數(shù)據(jù)達(dá)到閾值時,更新操作將會被阻塞,當(dāng)應(yīng)用經(jīng)常遇到大負(fù)載的突發(fā)寫請求時,用戶可以稍微增加這個值來應(yīng)對這種情況,其默認(rèn)值是7 9)增加阻塞倍率 屬性hbase.hregion.memstore.block.multiplier的默認(rèn)值是2,當(dāng)memstore達(dá)到屬性multiplier乘以flush的大小限制時會阻止進(jìn)一步更新 10)減少最大日志文件的限制 設(shè)置hbase.regionserver.maxlogs屬性使得用戶能夠控制基于磁盤的WAL文件數(shù)目,進(jìn)而控制刷寫頻率,該參數(shù)的默認(rèn)值是32
負(fù)載測試 Hbase有自己的性能評價工具,名為PE,使用命令:hbase org.apache.hadoop.hbase.PerformanceEvaluation YCSB:Yahoo的云服務(wù)基準(zhǔn)測試系統(tǒng)也可用于對HBase集群進(jìn)行超負(fù)荷測試
十一、集群管理 1.運維任務(wù) 1)減少節(jié)點 使用hbase-daemon.sh stop regionserver停止region服務(wù)器 如果關(guān)閉節(jié)點時負(fù)載均衡還在運行,則在復(fù)雜均衡和master恢復(fù)下線的region服務(wù)器之間可能存在競爭,要避免這種情況,使用shell命令:balance_switch false禁用負(fù)載均衡 HBase0.90.2之后引入了一種可以讓region服務(wù)器逐漸減少其負(fù)載并停止服務(wù)的方法,使用graceful_stop.sh腳本來完成 用戶也可以用graceful_stop.sh腳本來重啟服務(wù)器,并將之前屬于它的region移回原味(用戶可能選擇后者以保持?jǐn)?shù)據(jù)的局部性),最簡單的滾動重啟可以使用如下命令(確認(rèn)之前已經(jīng)關(guān)閉負(fù)載均衡): for i in 'cat conf/regionservers|sort; do ./bin/graceful_stop.sh --restart --reload --debug $i; done $> /tmp/log.txt &
2.數(shù)據(jù)任務(wù) 1)導(dǎo)入/導(dǎo)出 HBase發(fā)布了一些有用的工具,其中兩個支持導(dǎo)入和導(dǎo)出MapReduce作業(yè)。這些工具包含在HBase的JAR文件中,用戶可以通過hadoop jar命令來獲得這些工具,使用格式:hadoop jar $HBASE_HOME/HBASE-0.91.0-SNAPSHOT.jar <command>
一致性模型:數(shù)據(jù)庫必須保證每一步操作都是從一致的狀態(tài)到下一個一致的狀態(tài) 按照嚴(yán)格強(qiáng)度劃分: 嚴(yán)格一致性:數(shù)據(jù)的變化是原子的,一經(jīng)改變及時生效 順序一致性:每個客戶端看到的數(shù)據(jù)依照它們操作執(zhí)行的順序而變化 因果一致性:客戶端以因果關(guān)系順序觀察到數(shù)據(jù)的改變 最終一致性:在沒有更新數(shù)據(jù)的一段時間里,系統(tǒng)將通過廣播早證副本之間的數(shù)據(jù)一致性 弱一致性:沒有做出保證的情況下,所有的更新會通過廣播的形式傳遞,展現(xiàn)給不同客戶端的數(shù)據(jù)順序可能是不一樣
阻抗匹配:為一個給定問題找到一個理想的解決方案,除了使用通用的解決方案,還應(yīng)該知道有什么可用的解決方案,從而找到最適合解決該問題的系統(tǒng)
2.表、行、列和單元格 最基本的單位是列,一列或多列形成一行,并由唯一的行健(row key)來確定存儲,一個表有若干行,其中每列可能有多個版本,在每個單元格中存儲了不同的值 一行由若干列組成,若干列又構(gòu)成了一個列族,一個列族的所有列存儲在同一個底層文件中,這個存儲文件叫做HFile,列族需要在表創(chuàng)建的時候就定義好,常見的引用列的格式為family:qualifer,列族的數(shù)量有限制,但是列的數(shù)量沒有限制,列值也沒有長度和類型的限制 在Hbase中空值是沒有任何消耗的,它們不占用任何的存儲空間 每列或每個單元格的值都具有時間戳,默認(rèn)由系統(tǒng)指定,也可以由用戶顯示設(shè)置 BigTable和Hbase的典型使用場景是webtable,存儲從互聯(lián)網(wǎng)中抓取的網(wǎng)頁 行數(shù)據(jù)的存儲操作都是原子的,可以讀寫任意數(shù)目的列,目前還不支持跨行事務(wù)和跨表事務(wù)
3.自動分區(qū) Hbase中擴(kuò)展和負(fù)載均衡的基本單元稱為region,region本質(zhì)上是以行健排序的連續(xù)存儲的區(qū)間
4.存儲API API提供了建表、刪表、增加列族和刪除列族的操作,同時還提供了修改表和列族元數(shù)據(jù)的功能 scanAPI提供了高效遍歷某個范圍的行的功能 在服務(wù)器的地址空間中執(zhí)行來自客戶端的代碼,支持這種功能的服務(wù)器框架叫做協(xié)處理器(coprocessor)
5.實現(xiàn) 每次更新數(shù)據(jù)時,都會先將數(shù)據(jù)記錄在提交日志上(commit log)中,在Hbase中這叫預(yù)寫日志(write-ahead log,WAL),然后才將這些數(shù)據(jù)寫入內(nèi)存中的memstore中,到超過給定的最大值值,就寫到磁盤的HFile文件,HFile是不可被改變的 合并HFile機(jī)制 minor合并:將多個小文件(默認(rèn)最小3個,最大10個)重寫到數(shù)據(jù)較少的大文件中,每個HFile都是經(jīng)過歸類的,所以合并的速度很快,只受磁盤IO的影響 major合并:將一個region中一個列族的若干個HFile重寫到一個新的HFile中,major合并能掃描所有的鍵值對,順序重寫全部的數(shù)據(jù)
二、客戶端API:基礎(chǔ)知識 1.概述 Hbase主要的客戶端接口是有org.apache.hadoop.hbase.client包中的HTable提供的HTable類提供的,通過這個類用戶可以向Hbase存儲和檢索數(shù)據(jù) 所有修改數(shù)據(jù)的操作都保證了行級別的原子性 創(chuàng)建HTable實例是有代價的,每個實例都需要掃描.META.表,以檢查該表是否存在,是否可用,以及一些其他操作,因此推薦用戶在每個線程(在開始時)只創(chuàng)建一次HTable實例,而后在客戶端應(yīng)用的生存期內(nèi)復(fù)用這個對象,如果用戶需要使用多個HTable實例,應(yīng)考慮使用HTablePool類 Hable(Configuration conf,"tableName")
2.CRUD操作 2.CRUD操作 2.1 put方法:向Hbase存儲數(shù)據(jù) 1)調(diào)用HTable的put方法格式: void put(Put put)或void put(List<put> puts) Put對象的構(gòu)造方法如下 創(chuàng)建Put實例之后,就可以使用add方法 向該實例添加數(shù)據(jù)了,每一次調(diào)用add()都可以特定的添加一列數(shù)據(jù),如果再加上一個時間戳選項,就能形成一個數(shù)據(jù)單元格。每個KeyValue實例包含器完成地址(行健、列族、列以及時間戳)和實際數(shù)據(jù),KeyValue是Hbase在存儲架構(gòu)中最底層的類 可以使用如下方法檢查是否存在特定的單元格,而不需要遍歷整個集合 通過客戶端訪問配置文件 當(dāng)你調(diào)用任何一個靜態(tài)create()方法時,代碼會嘗試使用當(dāng)前的java classpath來載入兩個配置文件hbase-default.xml和hbase-site.xml
Hbase的一個特殊功能是能為一個單元格存儲多個版本的數(shù)據(jù),這個版本使用一個時間戳,必須確保所有服務(wù)器的時間都是正確的,并且相互之間是同步的,默認(rèn)情況下Hbase會保留3個版本的數(shù)據(jù) 若需要頻繁的修改某些行,用戶有必要創(chuàng)建一個RowLock實例來防止其他用戶訪問這些行
2)KeyValue類 數(shù)據(jù)和坐標(biāo)都是以java的byte[]形式存儲的,使用這種類型的目的是允許存儲任意類型的數(shù)據(jù)
3)客戶端的寫緩沖區(qū) 每一個put操作實際上都是一個RPC操作,它將客戶端數(shù)據(jù)傳送到服務(wù)器后返回,這只適合小數(shù)據(jù)量的操作,Hbase的API配備了一個客戶端的寫緩沖區(qū)(write buffer),緩沖區(qū)負(fù)責(zé)收集put操作,然后調(diào)用RPC操作一次性將put送往服務(wù)器,全局交換機(jī)制控制著該緩沖區(qū)是否在使用,其方法如下 void setAutoFlush(boolean autoFlush) 默認(rèn)情況下,客戶端緩沖區(qū)是禁用的,可以通過將autoflush設(shè)置為false來激活緩沖區(qū),通過setBufferSize(long size)來配置客戶端寫緩沖區(qū)的大小,默認(rèn)大小是2M,為每一個用戶創(chuàng)建的HTable實例都設(shè)置緩沖器大小十分麻煩,可以在hbase-site.xml中添加一個較大的預(yù)設(shè)值,配置如下 <property> <name>hbase.client.write.value</name> <value>20971520</value> </property>
當(dāng)需要強(qiáng)制把數(shù)據(jù)寫到服務(wù)器端時,用flushCommit()函數(shù) 隱式刷寫:在用戶調(diào)用put()或setBufferSize()時觸發(fā),這兩個方法都會將目前占用的緩沖區(qū)大小和用戶配置的緩沖區(qū)大小進(jìn)行比較,此外調(diào)用HTable的close()也會無條件地隱式刷寫 用戶可以通過訪問ArrayList<Put> getWriteBuffer()來訪問客戶端寫緩沖區(qū)的內(nèi)容 如果用戶只存儲大單元格,那么客戶端緩沖區(qū)的作用就不大了 4)Put列表 調(diào)用void put(List<put> puts)時,客戶端先把所有的Put實例插入到本地寫緩沖區(qū)中,然后隱式的調(diào)用flushCache(),如果其中有失敗的Put實例(有些檢查是在客戶端完成的,如確認(rèn)Put實例的內(nèi)容是否為null或是否指定了列),那么后面的Put實例不會被添加到緩沖區(qū),也不會觸發(fā)刷寫命令,當(dāng)使用基于列表的Put調(diào)用時,用戶需要特別注意:用戶無法控制服務(wù)器執(zhí)行put的順序,如果要保證寫入的順序,需要小心地使用這個操作。
5)原子性操作compare-and-set 有一種特別的put調(diào)用,其能保證自身操作的原子性:checkAndPut(row,family,qualifier,value,Put put),這種有原子性的操作經(jīng)常被用于賬戶結(jié)余,狀態(tài)轉(zhuǎn)換或數(shù)據(jù)處理等場景 有一種特別的檢查通過checkAndPut()調(diào)用來完成,即只有在另外一個值不存在的情況下,才執(zhí)行這個修改,要執(zhí)行這種操作只需要將參數(shù)value設(shè)置為null Hbase提供的compare-and-set操作,只能檢查和修改同一行數(shù)據(jù)
2.2 get方法:客戶端獲取已存儲數(shù)據(jù)的方法 Result get(Get get); 1)單行Get 構(gòu)造Get實例: Get(rowkey) Get(rowkey,RowLock rowLock) 可以通過多種標(biāo)準(zhǔn)篩選目標(biāo)數(shù)據(jù): Get addFamily(family):只能取得一個指定的列族 Get addColumn(family,qualifier):獲取指定的列 Get setTimeRange(long minStamp,long masStamp)、 Get setTimeStamp(long timeStamp) Get setMaxVersions(int maxVersions)
2)result類 get()返回的結(jié)果包含所有匹配的單元格數(shù)據(jù),被封裝成一個Result類 常用方法: byte[] getValue(family,qualifier):取得特定單元格的值 byte[] value():返回第一列對應(yīng)的最新單元格的值 byte[] getRow():返回行健 int size():檢查是否有對應(yīng)的記錄 boolean isEmpty():檢查是否有對應(yīng)的記錄 KeyValue[] raw() List<KeyValue> list():用戶可以方便的迭代數(shù)據(jù) List<KeyValue> getColumn(family,qualifier) KeyValue getColumnLatest(family,qualifier) boolean containsColumn(family,qualifier) NavigableMap<byte[],NavigableMap[],NavigableMap<Long,byte[]>>> getMap():把請求返回的內(nèi)容都裝入一個Map類實例中,可以遍歷所有結(jié)果
3)get列表 Result[] get(List<Get> gets); boolean exists(Get get):查看存儲的數(shù)據(jù)是否存在 getRowOrBefore(row,family):
2.3 刪除方法 1)單行刪除 void delete(Delete delete) Delete實例構(gòu)造方法 Delete(rowkey) Delete(rowkey,long timestamp,RowLock rowLock) 常用方法 Delete deleteFamily(family[,long timestamp]) Delete deleteColumns(family,qualifier[,long timestamp]):沒指定timestamp,則刪除所有版本 Delete deleteColumn(family,qualifier[,long timestamp]):沒指定timestamp,則刪除最新版本
2)Delete的列表 void delete(List<Delete> deletes)
3)原子性操作compare-and-delete boolean checkAndDelete(row,qualifier,value,Delete delete)
2.4批處理操作 事實上許多基于列表的操作都是基于batch()方法是實現(xiàn)的。 方法: void batch(List<Row> actions,Object[] results) Object[] batch(List<Row> actions) 注:不可以將針對同一行數(shù)據(jù)的Put和Delete操作放在同一個批處理請求中 Row是Put、Get、Delete類的父類 當(dāng)用戶使用batch()功能時,Put實例不會被客戶端寫入緩沖區(qū)中緩沖,batch()請求是同步的,會把操作直接發(fā)送給服務(wù)器 兩種方法相同點: get、put、delete操作都支持,如果執(zhí)行時出現(xiàn)問題,客戶端將拋出異常并報告問題,都不適用客戶端的寫緩沖區(qū) 不同點: void batch(acitons,results):能訪問成功操作的結(jié)果,同時也可以獲取遠(yuǎn)程失敗的異常 Object[] batch(actions):只返回客戶端異常,不能訪問程序執(zhí)行中的部分結(jié)果 注:在檢查結(jié)果之前,所有的批處理操作都已經(jīng)執(zhí)行了:即使用戶收到異常,其他的操作也都已經(jīng)執(zhí)行了 批量處理可以感知暫時性錯誤(如NoServingRegionException)會多次重試這個操作,用戶可以通過調(diào)整hbase.client.retries.number配置項(默認(rèn)為10)來增加或減少重試次數(shù)
2.5 行鎖 region服務(wù)器提供一個行鎖的特性,保證了只有一個客戶端能獲取一行的數(shù)據(jù)相應(yīng)的鎖,同時對該行進(jìn)行修改。用戶應(yīng)該盡可能的避免使用行鎖,如果必須使用,那么一定要節(jié)約占用鎖的時間 Get不需要鎖:服務(wù)器應(yīng)用了一個多版本的并發(fā)控制機(jī)制來保證行級讀操作,只有當(dāng)一個變動被應(yīng)用到整個行之后,客戶端才能讀出這個改動,當(dāng)改動進(jìn)行中時,所有的客戶端讀取到的數(shù)據(jù)都是將是所有列以前的版本
2.6 掃描 類似于數(shù)據(jù)庫中的游標(biāo) ResultScanner getScanner(Scan scan) ResultScanner getScanner(family) ResultScanner getScanner(family,qualifier) scan類的構(gòu)造器 Scan() Scan(startRow,Filter filter) Scan(startRow) Scan(startRow,stopRow) 注:如果用戶只需要數(shù)據(jù)的子集,那么限制掃面的范圍就能發(fā)揮Hbase的優(yōu)勢,如果不讀取整個列族,那么整個列族的文件都不會讀取,這就是列族存儲架構(gòu)的優(yōu)勢 1)ResultScanner類 掃描操作不會通過一次RPC請求返回所有匹配的行,而是以"行"為單位進(jìn)行返回 Result next() Result[] next(int nbRows) void close() 要確保盡早釋放掃描器實例,當(dāng)使用完ResultScanner之后應(yīng)調(diào)用它的close()方法,釋放所有由掃描器控制的資源 就像行級鎖一樣,掃描器也使用同樣的租約超時限制,保護(hù)其不被時效的客戶端阻塞太久,通過如下配置 <property> <name>hbase.regionserver.lease.period</name> <value>120000</value> </property> 2)緩存與批量處理 如果一次RPC請求可以返回多行數(shù)據(jù),這樣使用掃描器更有意義,可以由掃描器緩存實現(xiàn),默認(rèn)情況下,這個緩存是關(guān)閉的。可以從兩個層面打開它 在表的層面,這個表的所有掃描器實例的緩存都會生效,用戶使用一下的Htable方法設(shè)置表級的掃描器緩存: void setScannerCaching(int scannerCaching), int getScannerCaching():默認(rèn)是1 在掃描器層面,這樣只會影響當(dāng)前的掃描實例,用戶使用一下的Scan類的方法設(shè)置掃描器級的掃描器緩存: void setCaching(int scannerCaching) int getCaching():默認(rèn)是1 此外用戶可以修改整個集群的配置 <property> <name>hbase.client.scanner.caching</name> <value>10</value> </property> 這樣所有scan的實例的掃描器緩存就都被設(shè)置為10了 注:當(dāng)數(shù)據(jù)量非常大的行,可能超過客戶端進(jìn)程的內(nèi)存容量,解決方法:使用Scan類的批量操作 setBatch(int batch) int getBatch() 緩存是面向行一級的操作,而批量是面向列一級的操作。
2.8 各種特性 1)Htable使用方法 void close():使用完一個HTable實例后,需要調(diào)用一次close(),它會刷寫所有客戶端緩沖的寫操作 HTableDescriptor getTableDescripor():每個表都使用一個HTableDescriptor實例類來定義表結(jié)構(gòu) Map<HRegion,HServerAddress> getRegionInfo():獲取某一行數(shù)據(jù)的具體位置信息
三、客戶端API:高級特性 1.過濾器 Get和Scan兩個類都支持過濾器,過濾器的基本接口叫做Filter,用戶還可以通過繼承Filter類實現(xiàn)自己的需求 1.1 比較運算符 1.2 比較器 1.3 Hbase提供的第一類:比較過濾器 用戶創(chuàng)建實例時需要一個比較運算符和一個比較器實例 CompareFilter(CompareOp op,WriteableByteArrayComparable valueComparator)
- 行過濾器(父類為比較過濾器)RowFilter
- 列族過濾器(父類為比較過濾器)FamilyFilter
- 列名過濾器(父類為比較過濾器)QualifierFilter
- 值過濾器(父類為比較過濾器)ValueFilter
- 參考列過濾器(父類為比較過濾器)DependentColumnFilter:可以把它理解為一個ValueFilter和一個時間戳過濾器的組合
1.4 Hbase提供的第二類:專用過濾器
- 單列值過濾器:SingleColumnValueFilter,用一列的值決定是否一行數(shù)據(jù)被過濾
- SingleColumnValueFilter(family,qualifier,CompareOp op,value)
- 單列值排除過濾器:SingleColumnValueExcludeFilter
- 前綴過濾器:PrefixFilte(byte[] prefix):返回所有與前綴匹配的行
- 分頁過濾器:PageFilter(int pageSize):用戶可以使用這個過濾器對結(jié)果進(jìn)行分頁。當(dāng)用戶創(chuàng)建分頁過濾器實例時,需要執(zhí)行pageSize參數(shù),注:物理上分離的服務(wù)器中并行執(zhí)行過濾器操作時,需要注意,在不同的region服務(wù)器上并行執(zhí)行的過濾器操作不能共享它們現(xiàn)在的狀態(tài)和邊界,因此每個過濾器都會在完成掃描前獲取pageCount行的結(jié)果,這種情況可能使分頁過濾器可能失效
- 行健過濾器:KeyOnlyFilter:只返回結(jié)果中的鍵
- FirstKeyOnlyFilter:訪問一行中第一列,這種過濾器通常用在行數(shù)統(tǒng)計的應(yīng)用場景中
- InclusiveStopFilter(byte[] endRow):掃描操作中的開始行被包含在結(jié)果中,但終止行被排除在外,使用這個過濾器時,用戶可以將結(jié)束行包含在結(jié)果中
- 時間戳過濾器:TimestampFilter(List<Long> timestamps):當(dāng)用戶需要在掃描結(jié)果中對版本進(jìn)行細(xì)粒度的控制時,可以使用該過濾器
- 列計數(shù)過濾器:ColumnCountGetFilter(int limit,int offset):限制每行最多取回多少列,不太適合掃描操作,適合get()方法
- 列分頁過濾器:ColumnPaginationFilter(int limit,int offset):可以對一行的所有列進(jìn)行分頁,它將跳過所有偏移量小于offset的列,并包含之后所有偏移量在limit之前(包含limit)的列
- 列前綴過濾器:ColumnPrefixFilter(byte[] prefix)
- 隨機(jī)行過濾器:RandomRowFilter(float chance)change在0到1之間
1.5 附加過濾器(應(yīng)用在其他過濾器上) 跳轉(zhuǎn)過濾器:SkipFilter(Filter filter):當(dāng)被包裝的過濾器遇到一個需要過濾的KeyValue時,用戶可以擴(kuò)展并過濾整行數(shù)據(jù) 全匹配過濾器:WhileMatchFilter
1.6 FilterList 需要多個過濾器共同限制返回到客戶端的結(jié)果 FilterList(List<Filter> rowFilters) FilterList(Operator op) FilterList(List<Filter> rowFilters,Operator op) 參數(shù)rowFilters以列表的形式組合過濾器,參數(shù)operator決定了組合它們的結(jié)果,默認(rèn)是為MUST_PASS_ALL,使用ArrayList可以保證過濾器的執(zhí)行順序與它們添加到列表中的順序一致
1.7 自定義過濾器 用戶可以實現(xiàn)Filter接口或者直接繼承FilterBase類
用戶自定義過濾器部署 編寫代碼-->打成jar包-->把文件發(fā)送到每個region服務(wù)器上-->修改hbase-env.sh文件如下 export HBASE_CLASSPATH="/hbase-book/target.aa.jar"-->重啟hbase
2 計數(shù)器 2.1 簡介 許多收集統(tǒng)計信息的應(yīng)用有點擊流和在線廣告意見,這些需要被收集到日志文件中用戶后續(xù)的分析,用戶可以使用計數(shù)器做實時統(tǒng)計,從而放棄延遲較高的批處理操作 雖然用戶可以一次更新多個計數(shù)器,但是它們必須屬于同一行,更新多個計數(shù)器需要通過獨立的API調(diào)用,即多個RPC請求 初始化計數(shù)器:用戶不用初始化計數(shù)器,當(dāng)用戶第一次使用計數(shù)器時,計數(shù)器自動設(shè)置為0,即當(dāng)用戶創(chuàng)建一個新列時,計數(shù)器的值是0 在shell中操作計數(shù)器使用incr '<table>','<row>','<column>',[increment-value]與get_counter '<table>','<row>','<column>' 客戶端API操作計數(shù)器 1)單計數(shù)器 只能操作一個計數(shù)器:用戶需要自己設(shè)定列,方法由HTable提供的 long incrementColumnValue(row,family,qualifier,long amount) long incrementColumnValue(row,family,qualifier,long amount,boolean writeToWAL) 2)多計數(shù)器 Result increment(Increment increment) 需要創(chuàng)建一個Increment實例,構(gòu)造方法如下 Increment() Increment(row) Increment(row,RowLock rowLock) 向其中加入實際的計數(shù)器:addColumn(family,qualifier,long maxStamp)
3.協(xié)處理器 協(xié)處理器允許用戶在region服務(wù)器上運行自己的代碼,也就是允許用戶執(zhí)行region級的操作,并可以使用如觸發(fā)器類似的功能 另一類適合使用協(xié)處理器的場景就是權(quán)限控制 協(xié)處理器框架提供了一些類,用戶可以通過繼承這些類擴(kuò)展自己的功能,主要有兩類,即observer和endpoint observer:回調(diào)函數(shù)(也被稱為鉤子函數(shù),hook)在一些特定時間發(fā)生時。這些事件包括用戶產(chǎn)生的事件和服務(wù)器內(nèi)部自動產(chǎn)生的事件 RegionObserver:用戶可以用這種處理器處理數(shù)據(jù)修改事件,它們與表的region聯(lián)系緊密 MasterObserver:可以被用作管理或DDL類型的操作,這些是集群級事件 WALObserver:提供控制WAL的鉤子函數(shù)
endpoint:通過添加一些遠(yuǎn)程調(diào)用來動態(tài)擴(kuò)展RPC協(xié)議,可以把它理解為與RDBMS中類似的存儲過程。endpoint可以與observer的實現(xiàn)組合起來直接作用于服務(wù)器的狀態(tài)
Coprocesspor類 所有協(xié)處理器的類都必須實現(xiàn)這個接口,它定義了協(xié)處理器的基本預(yù)定。提供了兩個被應(yīng)用于框架的枚舉類Priority(SYSTEM,USER)和State 待續(xù)!!!!
4.HtablePool 為Hbase集群提供一個客戶端連接池,用戶可以通過以下任意一個構(gòu)造器來創(chuàng)建池: HTablePool() HtablePool(Configuration conf,int maxSize) HtablePool(Configuration conf,int maxSize,HTableInterfaceFactory fac) HTableInterfaceFactory:用戶可以創(chuàng)建自定義的工廠類,例如,為Htable實例使用特定的配置,或可以讓實例完成一些初始化操作。如果用戶想自己擴(kuò)展HtableInterfaceFactory,則必須實現(xiàn)兩個方法createHTableInterface(conf,tableName)和releaseHtableInterface 使用表實例池方式:getTable(String tableName);getTable(byte[] tableName);void putTable(HtableInterface table)
5.連接管理 每個HTable實例都需要建立和遠(yuǎn)程主機(jī)的連接,這些連接在內(nèi)部使用HConnection類表示,被HConnectionManager類管理并共享。用戶沒必要和這兩個類打交道,只需要創(chuàng)建一個Configuration實例,然后利用客戶端API使用這些類。 Hbase內(nèi)部使用鍵值映射來存儲連接,使用Configuration實例作為鍵值映射的鍵。 HtablePool類,所有連接池中的Htable實例都自動共用一個提供的Configuration實例,共享它們的連接。 共享連接的缺點在于釋放,如果用戶不顯示關(guān)閉連接,它將一直存在,直到客戶端退出,建議用戶不在需要使用Htable時主動調(diào)用其close(),釋放資源,以下是顯式清理連接方法 deleteConnection(Configuration conf,boolean stop); deleteAllConnection(boolean stop)
四、客戶端API:管理功能 1.模式定義 1)表:使用表的主要原因是控制表中的所有列以達(dá)到共享表內(nèi)的某些特性的目的 表描述符的構(gòu)造函數(shù): HTableDescriptor(); HTableDescriptor(String name); HTableDescriptor(byte[] name); HTableDescriptor(HTableDescriptor desc);
任意不相交的系統(tǒng)間的遠(yuǎn)程通信都使用到了Hadoop RPC框架,需要遠(yuǎn)程方法中參數(shù)都實現(xiàn)Writeable接口,進(jìn)而能夠序列化對象并遠(yuǎn)程傳輸
2)表屬性 表名一定不能以".","-"開頭,表名只能包含拉丁字母或數(shù)字、下劃線、".","-"
列族: void addFamily(HColumnDescriptor family) boolean hasFamily(byte[] c) HColumnDescriptor[] getColumnFamilies() HColumnDescriptor getFamily(byte[] column)
文件大小限制: long getMaxFileSize() void setMaxFileSize(long maxFileSize) 如果一個列族的存儲單元已使用的存儲空間超過了大小限制,region將發(fā)生拆分,maxFileSize默認(rèn)值是256M 這個參數(shù)只是大致的預(yù)期值,而在某些特殊條件下,文件大小可能超過這個預(yù)期值(一行數(shù)據(jù)不能跨region存儲)
只讀:默認(rèn)所有的表都可寫,對于特殊的表來說,只讀參數(shù)有特殊的用途。調(diào)用setReadOnly(boolean readOnly)設(shè)置
memstore刷寫大小:寫操作會寫入到寫緩沖區(qū),人后按照合適的條件順序?qū)懭氲揭粋€新的存儲文件(磁盤)中,可以通過setMemStoreFlushSize(long memstoreFlushSize),這個memstoreFlushSize的默認(rèn)值是64MB
延遲日志刷寫: Hbase有兩種將WAL保存到磁盤的方式,一種是延遲日志刷寫,另一種不是,通過setDeferredLogFlush(boolean isDeferredLogFlush),isDeferredLogFlush的默認(rèn)值為false
3)列族 列族定義了所有列的共享信息,并且可以通過客戶端創(chuàng)建任意數(shù)量的列。定位到某個具體的列需要列族名和列名合并在一起,以:分隔,如family:qualifier 構(gòu)造方法: 列族名:getName()或getNameAsString() 不能被重命名,通常的做法是新建一個列族,然后使用API從舊列族中復(fù)制數(shù)據(jù)到新列族 列族名不能以"."開頭,也不能包含":"、"\"或ISO控制符
最大版本數(shù):所有列族都限定了每個值能夠保留的最大版本數(shù),Hbase會移除超過最大版本數(shù)的數(shù)據(jù),通過setMaxVersions(int maxVersion)設(shè)置,這個maxVersion默認(rèn)為3.
壓縮: Hbase支持插件式的壓縮算法,允許用戶選擇最合適的壓縮算法 塊大小: 在Hbase中,所有的存儲文件都被劃分為若干個小存儲塊,這些小存儲塊在get或scan操作時會加載到內(nèi)存中,通過setBlockSize(int size)設(shè)置,默認(rèn)大小是64KB 注:HFile的不同于HDFS中的塊,HDFS提到的塊是用于拆分大文件以提供分布式存儲,且便于MapReduce框架進(jìn)行并行計算的存儲單元;而HBase中的塊主要用于高效加載和緩沖數(shù)據(jù)
緩存塊: Hbase順序的讀取一個數(shù)據(jù)塊到內(nèi)存緩存中,這個參數(shù)默認(rèn)是為true,每次讀取的塊都會緩存到內(nèi)存中,但是如果順序讀取某個特定的列族,最好將這個屬性設(shè)置為false,通過setBlockCacheEnabled(boolean blockCacheEnabled)方法設(shè)置
生存期TTL: Hbase支持版本數(shù)據(jù)保存的時間,TTL設(shè)置了一個基于時間戳的臨界值,內(nèi)部管理會自動檢查TTL的值是否達(dá)到上限,在major合并過程中時間戳被判定為超過TTL的數(shù)據(jù)會被刪掉,可以通過setTimeToLive(int timestamp)方法設(shè)置,TTL的參數(shù)為秒,默認(rèn)值是Integer.MAX_VALUE,理解為永久保留
在內(nèi)存中:setInMemory(boolean inMemory) 將inMemory設(shè)置為true只是一種承諾,或者說高優(yōu)先級。在正常數(shù)據(jù)讀取過程中,塊數(shù)據(jù)被加載到緩沖區(qū)中并長期駐留在內(nèi)存中,除非堆壓力過大,這個時候才會強(qiáng)制從內(nèi)存中卸載這部分?jǐn)?shù)據(jù)
布隆過濾器: 能夠減少特定訪問模式下的查詢時間,由于這種模式增加了內(nèi)存和存儲的負(fù)擔(dān),這個模式默認(rèn)為關(guān)閉狀態(tài) 復(fù)制范圍:Hbase提供跨集群同步的功能,本地集群的數(shù)據(jù)更新可以及時同步到其他集群,復(fù)制范圍參數(shù)默認(rèn)為0,即這個功能處于關(guān)閉狀態(tài)。可以通過setScope(int scope)設(shè)置,1表示開啟實時同步
2.HBaseAdmin HBaseAdmin提供了創(chuàng)建表、列族、檢查表是否存在,修改表結(jié)構(gòu)和列族結(jié)構(gòu)、以及刪除表功能 構(gòu)造方法:HbaseAdmin(Configuration conf)
1)表操作 建表: void createTable(HTableDescriptor desc) void createTable(HTableDescriptor desc,byte[] startKey,byte[] endKey,int numRegions) void createTable(HTableDescriptor desc,byte[][] splitKeys) void createTableAsync(HTableDescriptor desc,byte[][] splitKeys) HTable類中的方法getStartEndKey()來獲取所有region的邊界
獲取所有表的列表,以及判斷是否存在 boolean tableExists(String tableName) boolean tableExists(byte[] tableName) HTableDescriptor[] listTables() HTableDescriptor getTableDescriptor(byte[] tableName)
刪除表: void deleteTable(String tableName) void deleteTable(byte[] tableName)
在刪除表之前需要將表禁用,region服務(wù)器會先將內(nèi)存中近期內(nèi)還未提交的已修改的數(shù)據(jù)刷寫到磁盤,然后關(guān)閉所有region,并更新這樣表的元數(shù)據(jù),將所有region標(biāo)記為下線狀態(tài)。
2)集群管理 允許用戶查看集群當(dāng)前的狀態(tài): static void checkHBaseAvailable(Configuration) ClusterStatus getClusterStatus() void closeRegion(String regionname,String hostAndport) 注:所有可用表的region都應(yīng)該是在線狀態(tài) void majorCompact(String tableNameOrRegionName)
五、可用的客戶端 1.REST、Thrift,Avro介紹 它們都支持大量的語言,Protocol Buffer與Thrift和Avro最大的不同是它沒有自己的RPC堆,而它生成的RPC定義需要被后來其他的RPC庫使用,Hbase提供了REST、Thrift、Avro的輔助服務(wù),它們可以實現(xiàn)成專門的網(wǎng)關(guān)服務(wù),這些服務(wù)運行在共享或?qū)S玫臋C(jī)器上。Thrift和Avro都有各自的RPC實現(xiàn),所以網(wǎng)關(guān)服務(wù)僅是在它們的基礎(chǔ)上進(jìn)行了封裝,至于REST,HBase則采用了自己的實現(xiàn),并提供了訪問存儲數(shù)據(jù)的路徑。 每個請求使用一個服務(wù)而非建立一個連接的優(yōu)勢在于用戶可以復(fù)用連接來獲得最優(yōu)性能。 2.交互 1)使用原生Java:直接使用HTable并通過原生的RPC調(diào)用與HBase服務(wù)器進(jìn)行交互。 2)REST: 操作:基于REST服務(wù)的客戶端是在能夠與HBase通信之前需要先啟動REST網(wǎng)關(guān)服務(wù),使用hbase-daemon.sh start rest命令。REST服務(wù)提供了HBase表提供的所有操作,REST服務(wù)器返回的值都經(jīng)過了base64Binary編碼。 支持的格式:通過使用HTTP Content-Type和Accept頭,調(diào)用者可以自動選擇發(fā)送和接收信息的數(shù)據(jù)格式 Plain(text/plain): XML(text/xml):默認(rèn)的存儲和查詢格式是XML JSON(application/json):curl -H "Accept:application/json" http://<servername>:testtable/%01%02%03/colfam1:col1
REST的java客戶端: REST服務(wù)器同樣具有全面的java客戶端API,位于org.apache.hadoop.hbase.rest.client包中,其中核心類為RemoteHTable和RemoteAdmin
3)Thrift 在使用Thrift之前需要安裝Thrift,并且需要啟動HBase提供的Thrift Server 啟動Thrift命令:hbase-daemon.sh start thrift
4)Avro 在使用Thrift之前需要安裝Avro,并且需要啟動HBase提供的Avro Server 啟動Avro命令:hbase-daemon.sh start Avro
3.批量處理客戶端 1)Mapreduce:兩種方式,原生java API或Clojure 2)Hive Hive與Hbase之前的版本需要匹配,細(xì)微的RPC變化可能影響交互 3)pig 4)Cascading
4.shell 1)命令 引用名:命令行要求在使用表名和列名時需要通過單引號或雙引號對其進(jìn)行引用。 引用值:命令行支持二進(jìn)制、八進(jìn)制、十六進(jìn)制的輸入和輸出,用戶在引用時必須使用雙引號 使用逗號分隔參數(shù) Ruby散列屬性: 一些命令中需要設(shè)置鍵值對屬性,使用Ruby散列按照以下方式來完成 {'key1'=>'val1','key2'=>'val2',...}
DDL命令 alter 使用modifyTable()修改現(xiàn)有表結(jié)構(gòu)
DML命令:
工具命令: assgn 分配一個region到一臺region服務(wù)器中
復(fù)制命令:
腳本: 可以使用Nagios或其他監(jiān)控工具發(fā)送腳本 用戶還以使用管道的形式運行命令
5.基于Web UI 1)master的web默認(rèn)端口是60010,region服務(wù)默認(rèn)端口是60030
六、與Mapreduce集成 1.類 InputFormat InputFormat負(fù)責(zé):拆分輸入數(shù)據(jù),同時返回一個RecordReader實例,定義了鍵值對象的類,并提供了next()遍歷數(shù)據(jù) 就HBase而言,它提供了一組專用的實現(xiàn),叫TableInputFormatBase,該實現(xiàn)的子類是TableInputFormat mapper HBase提供了一個TableMapper類,將鍵的類型強(qiáng)制轉(zhuǎn)換為ImmutableBytesWritable類,同時將改制的類型強(qiáng)制轉(zhuǎn)換為Result類型,TableMapper類沒有實現(xiàn)具體的功能,它只是添加了鍵值對的簽名 Reducer HBase提供了一個TableReducer類 OutputFormat Hbase提供了一個TableOutputFormat
2.支撐類 Mapreduce的支撐類與TableMapReduceUtil類一同協(xié)作在HBase上執(zhí)行Mapreduce任務(wù),它有一個靜態(tài)方法能配置作業(yè),病并使作業(yè)可以使用Hbase作為數(shù)據(jù)源或目標(biāo)
3.在HBase上的Mapreduce 當(dāng)運行Mapreduce作業(yè)所需庫中的文件不是綁定在Hadoop或Mapreduce框架中時,用戶就必須確保這些庫文在作業(yè)之前已經(jīng)可用,用戶一般兩個選擇:在所有的任務(wù)節(jié)點上準(zhǔn)備靜態(tài)的庫或直接提供作業(yè)所需的所有庫 1)靜態(tài)配置: 將jar文件復(fù)制到所有節(jié)點的常用路徑中 將這些jar文件的完整路徑寫入hadoop-env.sh配置文件中,按照如右方式編輯HADOOP-CLASSPATH變量:HADOOP-CLASSPATH="<extra-entries>":HADOOP-CLASSPATH 重啟所有的任務(wù)的NodeManager使變更生效 2)動態(tài)配置:Hadoop有一個特殊的功能,它可以讀取操作目錄中/lib目錄下所包含的所有庫的jar文件,用戶可以使用此功能生成所謂的胖jar文件,胖jar文件使用maven的Maven Assembly插件
七、架構(gòu) 1.數(shù)據(jù)查找和傳輸 1)B+樹:它的葉節(jié)點項目鏈接并且有序,能夠通過主鍵對記錄進(jìn)行高效的插入、查找以及刪除,它表能為一個動態(tài)、多層并由上下界的索引,同時要注意維護(hù)每一段所包含的鍵數(shù)目
2)LSM樹(log-structured merge-tree):輸入數(shù)據(jù)首先存儲在日志文件,這些文件內(nèi)的數(shù)據(jù)完全有序,當(dāng)有日志文件被修改時,對應(yīng)的更新會被保存在內(nèi)存中加速查詢,修改數(shù)據(jù)文件的操作通過滾動合并完成。
2.存儲 1)概覽 注:HBase主要處理兩種文件:一種是WAL文件,另一種是實際的數(shù)據(jù)文件,這兩種文件都是由HRegionServer管理
2)讀取數(shù)據(jù)流程
- 聯(lián)系ZooKeeper子集群(quorum),通過ZooKeeper獲取含有-ROOT-表的region服務(wù)器來查找行健
- 通過含有-ROOT-的region服務(wù)器可以查詢到含有.meta.表中對應(yīng)region服務(wù)器名,其中包內(nèi)含請求的行健信息
- 以上信息都會緩存下來,只查找一次
- 通過查詢.META.服務(wù)器來獲取客戶端查詢的行健數(shù)據(jù)所在的region服務(wù)器,HBase會存儲這次查詢的信息
HRegionServer負(fù)責(zé)打開region,并創(chuàng)建一個對應(yīng)的HRegion實例,它會為每個表的HColumnFamily創(chuàng)建一個Store實例,每個Store實例包含多個StoreFile(HFile的輕量級封裝)和一個MemStore,一個HRegionServer共享一個HLog實例
3)寫路徑
- 用戶發(fā)送HTable.put()請求到HRegion實例來大處理
- 決定數(shù)據(jù)是否需要寫到HLog類實現(xiàn)的預(yù)寫日志中,其中WAL是標(biāo)準(zhǔn)的Hadoop SequenceFile,并且存儲了HLogKey實例,這些鍵包含序列號和實際數(shù)據(jù)
- 一旦數(shù)據(jù)寫入到WAL中,數(shù)據(jù)就會放到MemStore中,同時檢查MemStore是否已經(jīng)滿了,如果滿了就刷寫到磁盤中去。書寫請求由另一個HRegionServer的線程處理,生成一個新的HFile
4)region拆分
- 當(dāng)region的存儲文件大于hbase.hregion.max.filesize大小或嫘祖層面的配置的大小時,region會被一分為二
- 為新region創(chuàng)建兩個對應(yīng)的文件,每個region為原region的一半,通過在父region中創(chuàng)建split目錄來完成。
- 關(guān)閉該region,此后該region不再接受任何請求。
- region服務(wù)器通過split目錄中設(shè)立必需的文件接受來準(zhǔn)備新的子region,包括新region的目錄和參考文件。
- 把這兩個新region目錄移動表目錄
- .META.表中父region的狀態(tài)會被更新,以表示其現(xiàn)在拆分的節(jié)點和子節(jié)點是什么
- 兩個子region準(zhǔn)備好后,將會被同一個服務(wù)器并行打開,打開的過程包括更新.META.表,同時也會初始化為兩個region并對region中的內(nèi)容進(jìn)行合并,合并過程中替換引用文件之前會把父region的存儲文件異步重寫到兩個子region中,在region的.tmp目錄進(jìn)行
- 最終父region被清理,master被告知查分的情況,并且可以由于負(fù)載均衡而把新region移動到其他的HRegionServer上
5)合并 minor合并:負(fù)責(zé)重寫最后生成的幾個文件到一個更大的文件中,文件數(shù)量有hbase.hstore.compaction.min決定,默認(rèn)值是3,minor合并處理的最大文件數(shù)默認(rèn)為10,用戶可以通過hbase.hstore.compaction.max來配置 major合并:把所有文件壓縮成一個單獨的文件,在memstore被刷寫到磁盤后出發(fā)檢查,或shell命令major-compact后觸發(fā),配置相關(guān)參數(shù) hbase.hregion.majorcompaction(默認(rèn)為24小時)和hbase.hregion.majorcompaction.jitter(默認(rèn)為0.2)
6)HFile 注:文件長度可變,唯一固定的塊是File Info和Trailer,Trailer是指向其他快遞的指針,塊大小是由HColumnDescriptor配置的,該配置可以在創(chuàng)建表的時候由用戶指定,默認(rèn)大小時64K,每一個塊都包含一個magic頭部和一定數(shù)量的序列化的KeyValue實例
7)WAL WAL存儲了對數(shù)據(jù)的所有更改,實現(xiàn)了WAL的類叫HLog類,HLog類的一個特性就是跟蹤修改,通過使用序列號來實現(xiàn)
3.ZooKeeper HBase使用ZooKeeper作為其協(xié)同服務(wù)組件,其主要功能包括跟蹤region服務(wù)器、保存root region的地址等 HBase建立的znode列表,默認(rèn)為/hbase,這個znode的名稱由zookeeper.znode.parent屬性決定, 以下是znode的列表以及他們的作用 /hbase/hbaseid:包括clusterID,與存儲在HDFS上的hbase.id文件內(nèi)容相同。 /hbase/master:包含服務(wù)器名稱 /hbase/replication:包含副本信息 /hbase/root-region-server:包含-ROOT-region所在的region服務(wù)器的機(jī)器名,這個經(jīng)常在region定位中使用 /hbase/rs:所偶region服務(wù)器的根節(jié)點,集群使用它來跟蹤服務(wù)器異常 /hbase/shutdown:集群的啟動事假和關(guān)閉時間 /hbase/table:當(dāng)表被禁用,信息會被添加到這個znode之下
4.復(fù)制 HBase復(fù)制可以作為一種災(zāi)難恢復(fù)的方法,并且可以提供HBase層的高可用性 HBase復(fù)制中最基本的機(jī)構(gòu)模式是"主推送",因為每個region服務(wù)器都有自己的WAL,所以很容易保存現(xiàn)在正在復(fù)制的位置 注:參與復(fù)制的集群可以不相等,主機(jī)群會通過隨機(jī)分配盡量均衡從集群的負(fù)載
1)常規(guī)處理 客戶端發(fā)送Put、Delete、或Increment到region服務(wù)器,這些請求包含的鍵值對會被region服務(wù)器轉(zhuǎn)化為WALEdit,同時WALEdit會被復(fù)制程序檢查,并以列族為單元復(fù)制數(shù)據(jù)。修改被添加到WAL中,并把實際數(shù)據(jù)添加到Memstore。 2)沒有反饋的從集群 如果從集群的region服務(wù)器沒有響應(yīng)rpc請求,主集群的region服務(wù)器將會睡眠并按照配置的次數(shù)重試。如果從集群的region服務(wù)器還是不可用,主機(jī)全會重新選擇一臺其他的機(jī)器來提交修改 3)挑選要復(fù)制的目標(biāo)集群 主集群的region服務(wù)器連接從集群的ZooKeeper群組,然后掃描/hbase/rs目錄來發(fā)現(xiàn)所有可用的并隨機(jī)選擇一部分服務(wù)器來復(fù)制數(shù)據(jù)(默認(rèn)是10%)
八、高級用法 1.rowkey設(shè)計 1)高表與寬表 HBase中的表可以設(shè)計為高表和寬表,前者指表中列少兒行多,后者則正好相反。用戶應(yīng)當(dāng)盡量將需要查詢的維度或信息存儲在行健中,應(yīng)為用它篩選的效率最高 此外,HBase只能按行分片,因此高表更有優(yōu)勢
2)時間序列:當(dāng)處理流式事件時,最常用的就是按時間序列組織數(shù)據(jù),這些數(shù)據(jù)會被有序的存儲在一個特定的范圍內(nèi),到時系統(tǒng)產(chǎn)生讀寫熱點,解決這個問題的方法就是想辦法將數(shù)據(jù)分散到所有的region服務(wù)器上,有很多中方法,例如在行鍵前價格,通常情況下如下選擇
- salting方式:prefix=Long.hashCode(timestamp) % <number of regionservers>
- 字段變換/提升字段:如果用戶設(shè)計的行鍵包含多個字段則可以調(diào)整它們的位置
- 隨機(jī)化:rowkey=MD5(timestamp),隨機(jī)化很適合每次只讀取一行數(shù)據(jù)的應(yīng)用,如果用戶不需要連續(xù)掃描而只需要隨機(jī)讀取,可以考慮這種策略
時間順序關(guān)系 每個列族下的列可以作為輔助索引單獨進(jìn)行排序,主要內(nèi)容在主要的列族下,索引放在另外一個列族下,為了編碼創(chuàng)建太多的列族,可以把所有輔助索引存儲在有一個單獨的列族下,同時列鍵的最左端使用索引ID這個前綴來表示不同的順序
2.輔助索引 輔助索引存儲了新坐標(biāo)和現(xiàn)有坐標(biāo)之間的映射關(guān)系,一些為可行的解決方案 由客戶端管理索引: 把責(zé)任完全轉(zhuǎn)移到應(yīng)用層的典型做法是把一個數(shù)據(jù)表和一個查找/映射表結(jié)合起來,每當(dāng)程序?qū)憯?shù)據(jù)表的時候,它也同時更新映射表(輔助索引表)。讀數(shù)據(jù)時可以直接在主表進(jìn)行查詢,從輔助索引表中先查找原表的行鍵,再在原表中讀取實際數(shù)據(jù)。優(yōu)點:用戶可以按照需求設(shè)計映射表。缺點:Hbase不能保證跨行操作的原子性 用戶可以自由設(shè)計主索引和輔助索引之間的映射關(guān)系時,必須接受的缺點是用戶需要實現(xiàn)所有存儲和查找數(shù)據(jù)必需的方法
帶索引的事務(wù)型HBase 開源的ITHBase,擴(kuò)展了HBase,最核心的擴(kuò)展是增加了保證所有輔助索引,提供了一個IndexedTableDescriptor,提供了數(shù)據(jù)表的輔助索引操作支持,大多數(shù)類被添加了索引支持功能的類替換了
帶索引的HBase IHBase是完全在內(nèi)存中維護(hù)索引,索引永遠(yuǎn)都是同步的,不需要額外的事務(wù)控制,索引的定義由IdxIndexDescriptor類完成
3.搜索集成 使用任意關(guān)鍵字來搜索數(shù)據(jù),滿足這種需要往往是集成一個完整的搜索引擎 Lucene:獨立于HBase使用的Lucene或其他派生類的解決方案可以通過Mapreduce建立索引。 HBasene:選擇的方法是直接在HBase內(nèi)部建立搜索索引,同時為用戶提供Lucene的API,它把每個文檔的字段、詞存儲在一個單獨的行,同時包含這個詞的文檔儲存在這一行的列中
九、監(jiān)控集群 1.監(jiān)控框架 每個HBase進(jìn)程都會提供一系列監(jiān)控指標(biāo),這些監(jiān)控指標(biāo)可以被各種監(jiān)控API和工具使用,包括JMX和Ganglia。每種服務(wù)器都有多組監(jiān)控指標(biāo),這些監(jiān)控指標(biāo)按子系統(tǒng)分組并隸屬于一種服務(wù)器 HBase使用Hadoop的監(jiān)控框架,并繼承了其所有類和特性,這個框架基于MetricsContext接口來處理監(jiān)控數(shù)據(jù)點的生成,并使用這些數(shù)據(jù)點監(jiān)控和繪圖 1)可用的實現(xiàn)列表: GangliaContext:用來推送監(jiān)控指標(biāo)到Ganglia FileContext:將監(jiān)控指標(biāo)寫入磁盤上一個文件中 TimeStampingFileContext:將監(jiān)控指標(biāo)寫入磁盤上一個文件中,但是為每個監(jiān)控指標(biāo)添加一個時間戳前綴 CompositeContext:允許為監(jiān)控指標(biāo)生成不止一個上下文 NullContext:監(jiān)控指標(biāo)框架的關(guān)閉選項,使用這個上下文時,不生成也不聚合監(jiān)控指標(biāo) NullContextWithUpdateThread:不生成任何監(jiān)控指標(biāo),但是啟動聚合統(tǒng)計線程。這種上下文在通過JMX檢索監(jiān)控指標(biāo)時使用
多重監(jiān)控指標(biāo)使用MetricsRecored分組,來描述一個具體的子系統(tǒng)。HBase使用這些組分別來保存master、region機(jī)器,以及其他服務(wù)器的統(tǒng)計信息,每個組都有唯一的名字:<context-name>.<record-name>.<metrics-name>。上下文有內(nèi)置的定時器來觸發(fā)并將監(jiān)控指標(biāo)推送至目標(biāo)
2)各種指標(biāo)類型: 整型值:(IV) 長整型值:(LV) 速率(R):一個代表速率的浮點型值,可以是每秒操作或者消息數(shù) 字符串:存儲靜態(tài)的,基于文本的信息。并用來報告HBase版本信息和構(gòu)建時間 時間變化整型(TVI):上下文會維護(hù)一個單調(diào)遞增累加計數(shù)器。框架使用這個方法對各種消息進(jìn)行技術(shù) 時間變化長整型(TVL):用于增速較快的計數(shù)器 時間變化率(TVR):需要追蹤操作數(shù)或消息的數(shù)量,以及完成操作所用的時間,通常用來計算一次操作完成的平均時間 持續(xù)型時間變化率(PTVR):添加了對持續(xù)的周期性的監(jiān)控指標(biāo)的必要的支持。 3)master提供的監(jiān)控指標(biāo)
4)region服務(wù)器監(jiān)控指標(biāo): 塊緩存監(jiān)控指標(biāo) 塊緩存用來保存底層HFile從HDFS讀取的存儲塊。count(LV)監(jiān)控指標(biāo)反映了當(dāng)前緩存中保存的塊數(shù)目,size(LV)監(jiān)控指標(biāo)時占用java堆空間大小,free(LV)監(jiān)控指標(biāo)時堆空間為緩存保留的可用空間,evicted(LV)反映了命中緩存總數(shù)與請求緩存總數(shù)的關(guān)系 塊緩存追蹤追蹤緩存命中hit(LV)和緩存失效miss(LV)的數(shù)目,以及命中率hit radio(LV),其反映了命中緩存總數(shù)與請求緩存總數(shù)的關(guān)系。所有讀操作使用緩存,不管用戶是否制定過將使用的塊保留在緩存中。使用setCacheBlocks()僅僅影響塊的保留策略 合并監(jiān)控 compaction size(PTVR)和compaction time(PTVR)分別代表需要合并的存儲文件總大小和操作花費時間 compaction queue size:用來監(jiān)測一個region服務(wù)器有多少文件當(dāng)前正在排隊等待合并
memstore監(jiān)控指標(biāo) memstore size MB(IV):服務(wù)器上所有memstore總共占用的堆大小 flush queue zie(IV):將要被刷寫的region的數(shù)目
存儲監(jiān)控指標(biāo): store files(IV):所有存儲文件的數(shù)目 store file index MB(IV):所有存儲文件的塊索引和元數(shù)據(jù)的總和大小
I/O監(jiān)控指標(biāo): fs read latency(TVR):文件系統(tǒng)的讀延遲 fs write latency:寫延遲 fs sync latency:統(tǒng)計了預(yù)寫日志記錄同步到文件系統(tǒng)的延遲
RPC監(jiān)控指標(biāo) Ganglia 組成: Ganglia監(jiān)控守護(hù)進(jìn)程(gmond):監(jiān)控守護(hù)進(jìn)程需要在每臺需要監(jiān)控的機(jī)器上運行,它搜集本地數(shù)據(jù),準(zhǔn)備統(tǒng)計,然后被其他系統(tǒng)拉取。通過單一或組播方網(wǎng)絡(luò)消息傳播的主機(jī)變化情況,使用組播方式,每個監(jiān)控守護(hù)進(jìn)程可以獲取集群完整狀態(tài),所有的服務(wù)器擁有同樣的組播地址 Ganglia元數(shù)據(jù)守護(hù)進(jìn)程(gmetad):元數(shù)據(jù)守護(hù)進(jìn)程安裝在一個中心節(jié)點上,作為整個集群的管理節(jié)點。元數(shù)據(jù)守護(hù)進(jìn)程從一個或多個監(jiān)控守護(hù)進(jìn)程拉去數(shù)據(jù)來獲取整個集群的狀態(tài),然后使用RDTool將這些信息存放在一個用于輪詢的時間序列數(shù)據(jù)庫中。 GangliaPHP:展示統(tǒng)計信息
十、性能優(yōu)化 1.垃圾回收優(yōu)化 垃圾回收時master通常不會產(chǎn)生問題,只需要添加到region服務(wù)器的啟動參數(shù)中。 用戶可以通過向hbase-env.sh配置文件中添加HBASE_OPTS或者HBASE_REGIONSERVER_OPTS變量來設(shè)置垃圾回收的相關(guān)選項。后者僅影響region服務(wù)器進(jìn)程,也是推薦的修改方式 指定新生代的方式:-XX:MaxNewSize=128m -XX:NewSize=128m或-Xmn128m 注意:默認(rèn)值對于多數(shù)region服務(wù)器面對的負(fù)載還是太小,所以她必須增大
建議在JRE日志中輸入垃圾回收的詳細(xì)信息,通過添加以下JRE選項: -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:$HBASE-HOME/logs/gc-hbase.log 該日志不會按日期定時滾動,需要手動處理(例如:使用基于crontab的每日滾動轉(zhuǎn)存任務(wù))
通過不同的JRE參數(shù)來指定不同的垃圾回收實現(xiàn)策略,推薦的值是: -XX:+UseParNewGC and -XX:+UseConcMarkSweepGC UseParNewGC:停止運行java進(jìn)程二期清空年輕代堆 ConcMarkSweepGC:不停止java進(jìn)程的情況下異步并行的完成工作
2.預(yù)拆分region 管理接口中createTable()方法或shell中的create命令可以接受列表形式提供的拆分行健作為參數(shù)
3.負(fù)載均衡: master有一個內(nèi)置的叫做均衡器的特性,在默認(rèn)的情況下,均衡器每五分鐘運行一次,可以通過hbase.balancer.period屬性設(shè)置 均衡器有一個可以限制自身運行時間的上限,用戶可以通過hbase.balance.max.balancing屬性來設(shè)置,默認(rèn)為均衡器間隔周期的一半
4.合并region HBase集成了一個工具能夠讓用戶在集群沒有工作時河北那個兩個相鄰的region,工具為org.apache.hadoop.hbase.util.Merge
5.客戶端API:最佳實踐 1)禁止自動刷寫:當(dāng)有大量的寫入操作時,使用setAutoFlush(false)方法,確認(rèn)HTable自動刷寫的特性已經(jīng)關(guān)閉,如果禁用了自動刷寫,add(Put)操作指導(dǎo)寫緩沖區(qū)被填滿時才會被送出,可以調(diào)用HTable的flushCommits()方法顯式刷寫數(shù)據(jù),調(diào)用HTable的close()也會隱式調(diào)用flushCommits() 2)使用掃面緩存:如果HBase被用作一個MapReduce作業(yè)的輸入源,請最好將作為MapReduce作業(yè)輸入掃描器實例的緩存用setCaching()方法設(shè)置為比默認(rèn)值1大得多的值,使用默認(rèn)值意味著map任務(wù)處理每條記錄都請求region服務(wù)器 3)限定掃描范圍 當(dāng)Scan用來處理大量行時注意哪些屬性被選中了,從而限制掃描范圍 4)關(guān)閉ResultScanner 如果用戶忘記關(guān)閉由HTable.getScanner()返回的ResultScanner實例,則可能對服務(wù)器端造成影響,一定要在try/catche的finally塊中關(guān)閉ResultScanner 5)塊緩存用法 Scan實例通過setCacheBlock()方法來設(shè)置使用region服務(wù)器中的塊緩存,如果MapReduce作業(yè)中使用掃描,這個方法應(yīng)當(dāng)被設(shè)為false,對于那些頻繁訪問行的行,建議使用塊緩存 6)關(guān)閉Put上WAL 提高吞吐量方式,使用Put的writeToWAL(false)來關(guān)閉WAL,不過一旦region服務(wù)器故障就會丟失數(shù)據(jù)
6.配置 1)減少Zookeeper超時 默認(rèn)在region服務(wù)器和ZooKeeper集群之間的超時時間是3分鐘,通過zookeeper.session.timeout屬性設(shè)置,在改變值之前,確認(rèn)用戶服務(wù)器上JVM的垃圾回收機(jī)制是受控的 2)增加處理線程 hbase.regionserver.handler.count屬性定義了響應(yīng)外部用戶訪問數(shù)據(jù)表請求的線程數(shù),默認(rèn)值10有些偏小,將這個值設(shè)置的高也有可能產(chǎn)生問題,并發(fā)的寫請求造成壓力 3)增加堆大小 如果用戶使用更好的服務(wù)器,可以給HBase分配8G內(nèi)存或更大,用戶可以在hbase-env.sh文件中調(diào)整HBASE_HEAPSIZE的設(shè)置,master會默認(rèn)1GB的堆運行,region服務(wù)器則會按照用戶單獨指定的堆空間運行 4)啟動數(shù)據(jù)壓縮 用戶應(yīng)當(dāng)為存儲文件啟動壓縮,尤其推薦使用Snappy或LZO壓縮 5)增加region大小 默認(rèn)region大小為256M,用戶可以增加其大小,但是該參數(shù)的大小要仔細(xì)評估 6)調(diào)整塊緩存大小 控制堆中塊緩存大小的屬性是一個浮動點數(shù)類型的百分比,默認(rèn)值是20%,可以通過perf.hfile.block.cache.size屬性改變這個值,看看是否存在許多塊被換出的情況,如果存在,則可以考慮增加塊緩存的大小。用戶負(fù)載大多數(shù)為讀請求是另一個增加緩存大小的原因。 7)調(diào)整memstore限制 內(nèi)存存儲占用的堆大小用hbase.regionserver.global.memstore.upperLimit屬性來配置,默認(rèn)值為40%,此外hbase.regionserver.global.memstore.lowerLimit屬性(默認(rèn)為35%)用戶控制當(dāng)服務(wù)器清空memstore之后剩余的大小,當(dāng)用戶主要在處理讀請求時,可以考慮通知減少memstore的上線限來增加塊緩存的空間 8)增加阻塞時存儲文件數(shù)目 這個值通過hbase.hstore.blockingStoreFiles屬性來設(shè)置的,它決定了當(dāng)存儲文件的數(shù)據(jù)達(dá)到閾值時,更新操作將會被阻塞,當(dāng)應(yīng)用經(jīng)常遇到大負(fù)載的突發(fā)寫請求時,用戶可以稍微增加這個值來應(yīng)對這種情況,其默認(rèn)值是7 9)增加阻塞倍率 屬性hbase.hregion.memstore.block.multiplier的默認(rèn)值是2,當(dāng)memstore達(dá)到屬性multiplier乘以flush的大小限制時會阻止進(jìn)一步更新 10)減少最大日志文件的限制 設(shè)置hbase.regionserver.maxlogs屬性使得用戶能夠控制基于磁盤的WAL文件數(shù)目,進(jìn)而控制刷寫頻率,該參數(shù)的默認(rèn)值是32
負(fù)載測試 Hbase有自己的性能評價工具,名為PE,使用命令:hbase org.apache.hadoop.hbase.PerformanceEvaluation YCSB:Yahoo的云服務(wù)基準(zhǔn)測試系統(tǒng)也可用于對HBase集群進(jìn)行超負(fù)荷測試
十一、集群管理 1.運維任務(wù) 1)減少節(jié)點 使用hbase-daemon.sh stop regionserver停止region服務(wù)器 如果關(guān)閉節(jié)點時負(fù)載均衡還在運行,則在復(fù)雜均衡和master恢復(fù)下線的region服務(wù)器之間可能存在競爭,要避免這種情況,使用shell命令:balance_switch false禁用負(fù)載均衡 HBase0.90.2之后引入了一種可以讓region服務(wù)器逐漸減少其負(fù)載并停止服務(wù)的方法,使用graceful_stop.sh腳本來完成 用戶也可以用graceful_stop.sh腳本來重啟服務(wù)器,并將之前屬于它的region移回原味(用戶可能選擇后者以保持?jǐn)?shù)據(jù)的局部性),最簡單的滾動重啟可以使用如下命令(確認(rèn)之前已經(jīng)關(guān)閉負(fù)載均衡): for i in 'cat conf/regionservers|sort; do ./bin/graceful_stop.sh --restart --reload --debug $i; done $> /tmp/log.txt &
2.數(shù)據(jù)任務(wù) 1)導(dǎo)入/導(dǎo)出 HBase發(fā)布了一些有用的工具,其中兩個支持導(dǎo)入和導(dǎo)出MapReduce作業(yè)。這些工具包含在HBase的JAR文件中,用戶可以通過hadoop jar命令來獲得這些工具,使用格式:hadoop jar $HBASE_HOME/HBASE-0.91.0-SNAPSHOT.jar <command>
總結(jié)
以上是生活随笔為你收集整理的hbase权威指南学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。