1-HBase的安裝
HBase是什么?
HBase是Apache Hadoop中的一個(gè)子項(xiàng)目,Hbase依托于Hadoop的HDFS作為最基本存儲基礎(chǔ)單元,通過使用hadoop的DFS工具就可以看到這些這些數(shù)據(jù) 存儲文件夾的結(jié)構(gòu),還可以通過Map/Reduce的框架(算法)對HBase進(jìn)行操作,如右側(cè)的圖所示:
HBase在產(chǎn)品中還包含了Jetty,在HBase啟動(dòng)時(shí)采用嵌入式的方式來啟動(dòng)Jetty,因此可以通過web界面對HBase進(jìn)行管理和查看當(dāng)前運(yùn)行的一些狀態(tài),非常輕巧。
為什么采用HBase?
HBase 不同于一般的關(guān)系數(shù)據(jù)庫,它是一個(gè)適合于非結(jié)構(gòu)化數(shù)據(jù)存儲的數(shù)據(jù)庫.所謂非結(jié)構(gòu)化數(shù)據(jù)存儲就是說HBase是基于列的而不是基于行的模式,這樣方面讀寫你的大數(shù)據(jù)內(nèi)容。
HBase是介于Map Entry(key & value)和DB Row之間的一種數(shù)據(jù)存儲方式。就點(diǎn)有點(diǎn)類似于現(xiàn)在流行的Memcache,但不僅僅是簡單的一個(gè)key對應(yīng)一個(gè) value,你很可能需要存儲多個(gè)屬性的數(shù)據(jù)結(jié)構(gòu),但沒有傳統(tǒng)數(shù)據(jù)庫表中那么多的關(guān)聯(lián)關(guān)系,這就是所謂的松散數(shù)據(jù)。
簡單來說,你在HBase中的表創(chuàng)建的可以看做是一張很大的表,而這個(gè)表的屬性可以根據(jù)需求去動(dòng)態(tài)增加,在HBase中沒有表與表之間關(guān)聯(lián)查詢。你只需要 告訴你的數(shù)據(jù)存儲到Hbase的那個(gè)column families 就可以了,不需要指定它的具體類型:char,varchar,int,tinyint,text等等。但是你需要注意HBase中不包含事務(wù)此類的功 能。
Apache HBase 和Google Bigtable 有非常相似的地方,一個(gè)數(shù)據(jù)行擁有一個(gè)可選擇的鍵和任意數(shù)量的列。表是疏松的存儲的,因此用戶可以給行定義各種不同的列,對于這樣的功能在大項(xiàng)目中非常實(shí)用,可以簡化設(shè)計(jì)和升級的成本。
如何運(yùn)行HBase?
從 Apache的HBase的鏡像網(wǎng)站上下載一個(gè)穩(wěn)定版本的HBase http://mirrors.devlib.org/apache/hbase/stable/hbase-0.20.6.tar.gz, 下載完成后,對其進(jìn)行解壓縮。確定你的機(jī)器中已經(jīng)正確的安裝了Java SDK、SSH,否則將無法正常運(yùn)行。
$ cd /work/hbase
進(jìn)入此目錄
$ vim conf/hbase-env.sh
export JAVA_HOME=/JDK_PATH
編輯 conf/hbase-env.sh 文件,將JAVA_HOME修改為你的JDK安裝目錄
$ vim conf/regionservers
輸入你的所有HBase服務(wù)器名,localhost,或者是ip地址
$ bin/start-hbase.sh
啟動(dòng)hbase, 中間需要你輸入兩次密碼,也可以進(jìn)行設(shè)置不需要輸入密碼,啟動(dòng)成功,如圖所示:
$ bin/hbase rest start
啟動(dòng)hbase REST服務(wù)后就可以通過對uri: http://localhost:60050/api/ 的通用REST操作(GET/POST/PUT/DELETE)實(shí)現(xiàn)對hbase的REST形式數(shù)據(jù)操作.
也可以輸入以下指令進(jìn)入HQL指令模式
$ bin/hbase shell
$ bin/stop-hbase.sh
關(guān)閉HBase服務(wù)
啟動(dòng)時(shí)存在的問題
由于linux系統(tǒng)的主機(jī)名配置不正確,在運(yùn)行HBase服務(wù)器中可能存在的問題,如圖所示:
2010-11-05 11:10:20,189 ERROR org.apache.hadoop.hbase.master.HMaster: Can not start master
java.net.UnknownHostException: ubuntu-server216: ubuntu-server216
表示你的主機(jī)名不正確,你可以先查看一下 /etc/hosts/中名稱是什么,再用 hostname 命令進(jìn)行修改, hostname you_server_name
查看運(yùn)行狀態(tài)
如果你需要對HBase的日志進(jìn)行監(jiān)控你可以查看 hbase.x.x./logs/下的日志文件,可以使用tail -f 來查看。
通過 web方式查看運(yùn)行在 HBase 下的zookeeper http://localhost:60010/zk.jsp
如果你需要查看當(dāng)前的運(yùn)行狀態(tài)可以通過web的方式對HBase服務(wù)器進(jìn)行查看,如圖所示:
擴(kuò)展閱讀1:
Apach 的 Hadoop的項(xiàng)目中包含了那些產(chǎn)品,如圖所示:
Pig 是在MapReduce上構(gòu)建的查詢語言(SQL-like),適用于大量并行計(jì)算。
Chukwa 是基于Hadoop集群中監(jiān)控系統(tǒng),簡單來說就是一個(gè)“看門狗” (WatchDog)
Hive 是DataWareHouse 和 Map Reduce交集,適用于ETL方面的工作。
HBase 是一個(gè)面向列的分布式數(shù)據(jù)庫。
Map Reduce 是Google提出的一種算法,用于超大型數(shù)據(jù)集的并行運(yùn)算。
HDFS 可以支持千萬級的大型分布式文件系統(tǒng)。
Zookeeper 提供的功能包括:配置維護(hù)、名字服務(wù)、分布式同步、組服務(wù)等,用于分布式系統(tǒng)的可靠協(xié)調(diào)系統(tǒng)。
Avro 是一個(gè)數(shù)據(jù)序列化系統(tǒng),設(shè)計(jì)用于支持大批量數(shù)據(jù)交換的應(yīng)用。
擴(kuò)展閱讀2:
什么是列存儲?列存儲不同于傳統(tǒng)的關(guān)系型數(shù)據(jù)庫,其數(shù)據(jù)在表中是按行存儲的,列方式所帶來的重要好處之一就是,由于查詢中的選擇規(guī)則是通過列來定義的,因 此整個(gè)數(shù)據(jù)庫是自動(dòng)索引化的。按列存儲每個(gè)字段的數(shù)據(jù)聚集存儲,在查詢只需要少數(shù)幾個(gè)字段的時(shí)候,能大大減少讀取的數(shù)據(jù)量,一個(gè)字段的數(shù)據(jù)聚集存儲,那就 更容易為這種聚集存儲設(shè)計(jì)更好的壓縮/解壓算法。這張圖講述了傳統(tǒng)的行存儲和列存儲的區(qū)別:
擴(kuò)展閱讀3:
對系統(tǒng)海量的Log4J日志可以存放在一個(gè)集中式的機(jī)器上,在此機(jī)器上安裝 splunk 可以方便對所有日志查看,安裝方法可以參考:
http://www.splunk.com/base/Documentation/latest/Installation/InstallonLinux
2-Java操作HBase例子
本篇文章講述用HBase Shell命令 和 HBase Java API 對HBase 服務(wù)器 進(jìn)行操作。在此之前需要對HBase的總體上有個(gè)大概的了解。比如說HBase服務(wù)器內(nèi)部由哪些主要部件構(gòu)成?HBase的內(nèi)部工作原理是什么?我想學(xué)習(xí)任何一項(xiàng)知識、技術(shù)的態(tài)度不能只是知道如何使用,對產(chǎn)品的內(nèi)部構(gòu)建一點(diǎn)都不去關(guān)心,那樣出了問題,很難讓你很快的找到答案,甚至我們希望最后能對該項(xiàng)技術(shù)的領(lǐng)悟出自己的心得,為我所用,借鑒該項(xiàng)技術(shù)其中的設(shè)計(jì)思想創(chuàng)造出自己的解決方案,更靈活的去應(yīng)對多變的計(jì)算場景與架構(gòu)設(shè)計(jì)。以我目前的對HBase的了解還不夠深入,將來不斷的學(xué)習(xí),我會把我所知道的點(diǎn)滴分享到這個(gè)Blog上。
先來看一下讀取一行記錄HBase是如何進(jìn)行工作的,首先HBase Client端會連接Zookeeper Qurom(從下面的代碼也能看出來,例如:HBASE_CONFIG.set('hbase.zookeeper.quorum', '192.168.50.216') )。通過Zookeeper組件Client能獲知哪個(gè)Server管理-ROOT- Region。那么Client就去訪問管理-ROOT-的Server,在META中記錄了HBase中所有表信息,(你可以使用 scan '.META.' 命令列出你創(chuàng)建的所有表的詳細(xì)信息),從而獲取Region分布的信息。一旦Client獲取了這一行的位置信息,比如這一行屬于哪個(gè)Region,Client將會緩存這個(gè)信息并直接訪問HRegionServer。久而久之Client緩存的信息漸漸增多,即使不訪問.META.表也能知道去訪問哪個(gè)HRegionServer。HBase中包含兩種基本類型的文件,一種用于存儲WAL的log,另一種用于存儲具體的數(shù)據(jù),這些數(shù)據(jù)都通過DFS Client和分布式的文件系統(tǒng)HDFS進(jìn)行交互實(shí)現(xiàn)存儲。
如圖所示:
再來看看HBase的一些內(nèi)存實(shí)現(xiàn)原理:
HMaster— HBase中僅有一個(gè)Master server。
HRegionServer—負(fù)責(zé)多個(gè)HRegion使之能向client端提供服務(wù),在HBase cluster中會存在多個(gè)HRegionServer。
ServerManager—負(fù)責(zé)管理Region server信息,如每個(gè)Region server的HServerInfo(這個(gè)對象包含HServerAddress和startCode),已load Region個(gè)數(shù),死亡的Region server列表
RegionManager—負(fù)責(zé)將region分配到region server的具體工作,還監(jiān)視r(shí)oot和meta 這2個(gè)系統(tǒng)級的region狀態(tài)。
RootScanner—定期掃描root region,以發(fā)現(xiàn)沒有分配的meta region。
MetaScanner—定期掃描meta region,以發(fā)現(xiàn)沒有分配的user region。
HBase基本命令
下面我們再看看看HBase的一些基本操作命令,我列出了幾個(gè)常用的HBase Shell命令,如下:
名稱
命令表達(dá)式
創(chuàng)建表create '表名稱', '列名稱1','列名稱2','列名稱N'
添加記錄put '表名稱', '行名稱', '列名稱:', '值'
查看記錄get '表名稱', '行名稱'
查看表中的記錄總數(shù)count '表名稱'
刪除記錄delete '表名' ,'行名稱' , '列名稱'
刪除一張表先要屏蔽該表,才能對該表進(jìn)行刪除,第一步 disable '表名稱' 第二步 drop '表名稱'
查看所有記錄scan '表名稱'
查看某個(gè)表某個(gè)列中所有數(shù)據(jù)scan '表名稱' , ['列名稱:']
更新記錄就是重寫一遍進(jìn)行覆蓋
如果你是一個(gè)新手隊(duì)HBase的一些命令還不算非常熟悉的話,你可以進(jìn)入 hbase 的shell 模式中你可以輸入 help 命令查看到你可以執(zhí)行的命令和對該命令的說明,例如對scan這個(gè)命令,help中不僅僅提到有這個(gè)命令,還詳細(xì)的說明了scan命令中可以使用的參數(shù)和作用,例如,根據(jù)列名稱查詢的方法和帶LIMIT 、STARTROW的使用方法:
scan Scan a table; pass table name and optionally a dictionary of scanner specifications. Scanner specifications may include one or more of the following: LIMIT, STARTROW, STOPROW, TIMESTAMP, or COLUMNS. If no columns are specified, all columns will be scanned. To scan all members of a column family, leave the qualifier empty as in 'col_family:'. Examples: hbase> scan '.META.' hbase> scan '.META.', {COLUMNS => 'info:regioninfo'} hbase> scan 't1', {COLUMNS => ['c1', 'c2'], LIMIT => 10, STARTROW => 'xyz'}
使用Java API對HBase服務(wù)器進(jìn)行操作
需要下列jar包
hbase-0.20.6.jar hadoop-core-0.20.1.jar commons-logging-1.1.1.jar zookeeper-3.3.0.jar log4j-1.2.91.jar import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.io.BatchUpdate; @SuppressWarnings('deprecation') public class HBaseTestCase { static HBaseConfiguration cfg = null; static { Configuration HBASE_CONFIG = new Configuration(); HBASE_CONFIG.set('hbase.zookeeper.quorum', '192.168.50.216'); HBASE_CONFIG.set('hbase.zookeeper.property.clientPort', '2181'); cfg = new HBaseConfiguration(HBASE_CONFIG); } /** * 創(chuàng)建一張表 */ public static void creatTable(String tablename) throws Exception { HBaseAdmin admin = new HBaseAdmin(cfg); if (admin.tableExists(tablename)) { System.out.println('table Exists!!!'); } else{ HTableDescriptor tableDesc = new HTableDescriptor(tablename); tableDesc.addFamily(new HColumnDescriptor('name:')); admin.createTable(tableDesc); System.out.println('create table ok .'); } } /** * 添加一條數(shù)據(jù) */ public static void addData (String tablename) throws Exception{ HTable table = new HTable(cfg, tablename); BatchUpdate update = new BatchUpdate('Huangyi'); update.put('name:java', 'http://www.javabloger.com'.getBytes()); table.commit(update); System.out.println('add data ok .'); } /** * 顯示所有數(shù)據(jù) */ public static void getAllData (String tablename) throws Exception{ HTable table = new HTable(cfg, tablename); Scan s = new Scan(); ResultScanner ss = table.getScanner(s); for(Result r:ss){ for(KeyValue kv:r.raw()){ System.out.print(new String(kv.getColumn())); System.out.println(new String(kv.getValue() )); } } } public static void main (String [] agrs) { try { String tablename='tablename'; HBaseTestCase.creatTable(tablename); HBaseTestCase.addData(tablename); HBaseTestCase.getAllData(tablename); } catch (Exception e) { e.printStackTrace(); } } }
3-HBase優(yōu)化技巧
這篇文章淺顯的從幾個(gè)方面談?wù)凥Base的一些優(yōu)化技巧,只能作為我學(xué)習(xí)筆記的一部分,因?yàn)閷W(xué)多了怕忘,留給自己以后看看。
1 修改 linux 系統(tǒng)參數(shù)
Linux系統(tǒng)最大可打開文件數(shù)一般默認(rèn)的參數(shù)值是1024,如果你不進(jìn)行修改并發(fā)量上來的時(shí)候會出現(xiàn)“Too Many Open Files”的錯(cuò)誤,導(dǎo)致整個(gè)HBase不可運(yùn)行,你可以用ulimit -n 命令進(jìn)行修改,或者修改/etc/security/limits.conf 和/proc/sys/fs/file-max 的參數(shù),具體如何修改可以去Google 關(guān)鍵字 “l(fā)inux limits.conf ”
2 JVM 配置
修改 hbase-env.sh 文件中的配置參數(shù),根據(jù)你的機(jī)器硬件和當(dāng)前操作系統(tǒng)的JVM(32/64位)配置適當(dāng)?shù)膮?shù)
HBASE_HEAPSIZE 4000 HBase使用的 JVM 堆的大小
HBASE_OPTS '‐server ‐XX: UseConcMarkSweepGC'JVM GC 選項(xiàng)
HBASE_MANAGES_ZKfalse 是否使用Zookeeper進(jìn)行分布式管理
3 HBase持久化
重啟操作系統(tǒng)后HBase中數(shù)據(jù)全無,你可以不做任何修改的情況下,創(chuàng)建一張表,寫一條數(shù)據(jù)進(jìn)行,然后將機(jī)器重啟,重啟后你再進(jìn)入HBase的shell中使用 list 命令查看當(dāng)前所存在的表,一個(gè)都沒有了。是不是很杯具?沒有關(guān)系你可以在hbase/conf/hbase-default.xml中設(shè)置hbase.rootdir的值,來設(shè)置文件的保存位置指定一個(gè)文件夾 ,例如:<value>file:///you/hbase-data/path</value>,你建立的HBase中的表和數(shù)據(jù)就直接寫到了你的磁盤上,如圖所示:
同樣你也可以指定你的分布式文件系統(tǒng)HDFS的路徑例如: hdfs://NAMENODE_SERVER:PORT/HBASE_ROOTDIR,這樣就寫到了你的分布式文件系統(tǒng)上了。
4 配置HBase運(yùn)行參數(shù)
其次就需要對hbase/conf/hbase-default.xml 文件進(jìn)行配置,以下是我認(rèn)為比較重要的配置參數(shù)
hbase.client.write.buffer
描述:這個(gè)參數(shù)可以設(shè)置寫入數(shù)據(jù)緩沖區(qū)的大小,當(dāng)客戶端和服務(wù)器端傳輸數(shù)據(jù),服務(wù)器為了提高系統(tǒng)運(yùn)行性能開辟一個(gè)寫的緩沖區(qū)來處理它, 這個(gè)參數(shù)設(shè)置如果設(shè)置的大了,將會對系統(tǒng)的內(nèi)存有一定的要求,直接影響系統(tǒng)的性能。
hbase.master.meta.thread.rescanfrequency
描述:多長時(shí)間 HMaster對系統(tǒng)表 root 和 meta 掃描一次,這個(gè)參數(shù)可以設(shè)置的長一些,降低系統(tǒng)的能耗。
hbase.regionserver.handler.count
描述:由于HBase/Hadoop的Server是采用Multiplexed, non-blocking I/O方式而設(shè)計(jì)的,所以它可以透過一個(gè)Thread來完成處理,但是由于處理Client端所呼叫的方法是Blocking I/O,所以它的設(shè)計(jì)會將Client所傳遞過來的物件先放置在Queue,并在啟動(dòng)Server時(shí)就先產(chǎn)生一堆Handler(Thread),該Handler會透過Polling的方式來取得該物件并執(zhí)行對應(yīng)的方法,默認(rèn)為25,根據(jù)實(shí)際場景可以設(shè)置大一些。
hbase.regionserver.thread.splitcompactcheckfrequency
描述:這個(gè)參數(shù)是表示多久去RegionServer服務(wù)器運(yùn)行一次split/compaction的時(shí)間間隔,當(dāng)然split之前會先進(jìn)行一個(gè)compact操作.這個(gè)compact操作可能是minor compact也可能是major compact.compact后,會從所有的Store下的所有StoreFile文件最大的那個(gè)取midkey.這個(gè)midkey可能并不處于全部數(shù)據(jù)的mid中.一個(gè)row-key的下面的數(shù)據(jù)可能會跨不同的HRegion。
hbase.hregion.max.filesize
描述:HRegion中的HStoreFile最大值,任何表中的列族一旦超過這個(gè)大小將會被切分,而HStroeFile的默認(rèn)大小是256M。
hfile.block.cache.size
描述:指定 HFile/StoreFile 緩存在JVM堆中分配的百分比,默認(rèn)值是0.2,意思就是20%,而如果你設(shè)置成0,就表示對該選項(xiàng)屏蔽。
hbase.zookeeper.property.maxClientCnxns
描述: 這項(xiàng)配置的選項(xiàng)就是從zookeeper中來的,表示ZooKeeper客戶端同時(shí)訪問的并發(fā)連接數(shù),ZooKeeper對于HBase來說就是一個(gè)入口這個(gè)參數(shù)的值可以適當(dāng)放大些。
hbase.regionserver.global.memstore.upperLimit
描述:在Region Server中所有memstores占用堆的大小參數(shù)配置,默認(rèn)值是0.4,表示40%,如果設(shè)置為0,就是對選項(xiàng)進(jìn)行屏蔽。
hbase.hregion.memstore.flush.size
描述:Memstore中緩存的內(nèi)容超過配置的范圍后將會寫到磁盤上,例如:刪除操作是先寫入MemStore里做個(gè)標(biāo)記,指示那個(gè)value, column 或 family等下是要?jiǎng)h除的,HBase會定期對存儲文件做一個(gè)major compaction,在那時(shí)HBase會把MemStore刷入一個(gè)新的HFile存儲文件中。如果在一定時(shí)間范圍內(nèi)沒有做major compaction,而Memstore中超出的范圍就寫入磁盤上了。
5 HBase中l(wèi)og4j的日志
HBase中日志輸出等級默認(rèn)狀態(tài)下是把debug、 info 級別的日志打開的,可以根據(jù)自己的需要調(diào)整log級別,HBase的log4j日志配置文件在 hbase\conf\log4j.properties 目錄下。
4–存儲
在HBase中創(chuàng)建的一張表可以分布在多個(gè)Hregion,也就說一張表可以被拆分成多塊,每一塊稱我們呼為一個(gè)Hregion。每個(gè)Hregion會保 存一個(gè)表里面某段連續(xù)的數(shù)據(jù),用戶創(chuàng)建的那個(gè)大表中的每個(gè)Hregion塊是由Hregion服務(wù)器提供維護(hù),訪問Hregion塊是要通過 Hregion服務(wù)器,而一個(gè)Hregion塊對應(yīng)一個(gè)Hregion服務(wù)器,一張完整的表可以保存在多個(gè)Hregion 上。HRegion Server 與Region的對應(yīng)關(guān)系是一對多的關(guān)系。每一個(gè)HRegion在物理上會被分為三個(gè)部分:Hmemcache(緩存)、Hlog(日志)、HStore(持久層)。
上述這些關(guān)系在我腦海中的樣子,如圖所示:
1.HRegionServer、HRegion、Hmemcache、Hlog、HStore之間的關(guān)系,如圖所示:
2.HBase表中的數(shù)據(jù)與HRegionServer的分布關(guān)系,如圖所示:
HBase讀數(shù)據(jù)
HBase讀取數(shù)據(jù)優(yōu)先讀取HMemcache中的內(nèi)容,如果未取到再去讀取Hstore中的數(shù)據(jù),提高數(shù)據(jù)讀取的性能。
HBase寫數(shù)據(jù)
HBase寫入數(shù)據(jù)會寫到HMemcache和Hlog中,HMemcache建立緩存,Hlog同步Hmemcache和Hstore的事務(wù)日志,發(fā)起Flush Cache時(shí),數(shù)據(jù)持久化到Hstore中,并清空HMemecache。
客戶端訪問這些數(shù)據(jù)的時(shí)候通過Hmaster ,每個(gè) Hregion 服務(wù)器都會和Hmaster 服務(wù)器保持一個(gè)長連接,Hmaster 是HBase分布式系統(tǒng)中的管理者,他的主要任務(wù)就是要告訴每個(gè)Hregion 服務(wù)器它要維護(hù)哪些Hregion。用戶的這些都數(shù)據(jù)可以保存在Hadoop 分布式文件系統(tǒng)上。 如果主服務(wù)器Hmaster死機(jī),那么整個(gè)系統(tǒng)都會無效。下面我會考慮如何解決Hmaster的SPFO的問題,這個(gè)問題有點(diǎn)類似Hadoop的SPFO 問題一樣只有一個(gè)NameNode維護(hù)全局的DataNode,HDFS一旦死機(jī)全部掛了,也有人說采用Heartbeat來解決這個(gè)問題,但我總想找出 其他的解決方案,多點(diǎn)時(shí)間,總有辦法的。
昨天在hadoop-0.21.0、hbase-0.20.6的環(huán)境中折騰了很久,一直報(bào)錯(cuò),錯(cuò)誤信息如下:
Exception in thread 'main' java.io.IOException: Call to localhost/serv6:9000 failed on local exception: java.io.EOFException 10/11/10 15:34:34 ERROR master.HMaster: Can not start master java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at org.apache.hadoop.hbase.master.HMaster.doMain(HMaster.java:1233) at org.apache.hadoop.hbase.master.HMaster.main(HMaster.java:1274)
死活連接不上HDFS,也無法連接HMaster,郁悶啊。
我想想啊,慢慢想,我眼前一亮 java.io.EOFException 這個(gè)異常,是不是有可能是RPC 協(xié)定格式不一致導(dǎo)致的?也就是說服務(wù)器端和客戶端的版本不一致的問題?換了一個(gè)HDFS的服務(wù)器端以后,一切都好了,果然是版本的問題,最后采用 hadoop-0.20.2 搭配hbase-0.20.6 比較穩(wěn)當(dāng)。
最后的效果如圖所示:
上圖的一些文字說明:
hadoop版本是0.20.2 ,
hbase版本是0.20.6,
在hbase中創(chuàng)建了一張表 tab1,退出hbase shell環(huán)境,
用hadoop命令查看,文件系統(tǒng)中的文件果然多了一個(gè)剛剛創(chuàng)建的tab1目錄,以上這張圖片說明HBase在分布式文件系統(tǒng)Apache HDFS中運(yùn)行了。
5(集群) -壓力分載與失效轉(zhuǎn)發(fā)
在上一篇關(guān)于HBase的文章中曾經(jīng)講述過HBase在分布式中的架構(gòu),這篇文章將會講述HBase在分布式環(huán)境中是如何排除單點(diǎn)故障的(SPFO),做一個(gè)小實(shí)驗(yàn)講述HBase在分布式環(huán)境中的高可用性,親眼看到一些現(xiàn)象,延伸一些思考的話題。
先來回顧一下HBase主要部件:
HBaseMaster
HRegionServer
HBase Client
HBase Thrift Server
HBase REST Server
HBaseMaster
HMaster 負(fù)責(zé)給HRegionServer分配區(qū)域,并且負(fù)責(zé)對集群環(huán)境中的HReginServer進(jìn)行負(fù)載均衡,HMaster還負(fù)責(zé)監(jiān)控集群環(huán)境中的HReginServer的運(yùn)行狀況,如果某一臺HReginServer down機(jī),HBaseMaster將會把不可用的HReginServer來提供服務(wù)的HLog和表進(jìn)行重新分配轉(zhuǎn)交給其他HReginServer來提供,HBaseMaster還負(fù)責(zé)對數(shù)據(jù)和表進(jìn)行管理,處理表結(jié)構(gòu)和表中數(shù)據(jù)的變更,因?yàn)樵?META 系統(tǒng)表中存儲了所有的相關(guān)表信息。并且HMaster實(shí)現(xiàn)了ZooKeeper的Watcher接口可以和zookeeper集群交互。
HRegionServer
HReginServer負(fù)責(zé)處理用戶的讀和寫的操作。HReginServer通過與HBaseMaster通信獲取自己需要服務(wù)的數(shù)據(jù)表,并向HMaster反饋?zhàn)约旱倪\(yùn)行狀況。當(dāng)一個(gè)寫的請求到來的時(shí)候,它首先會寫到一個(gè)叫做HLog的write-ahead log中。HLog被緩存在內(nèi)存中,稱為Memcache,每一個(gè)HStore只能有一個(gè)Memcache。當(dāng)Memcache到達(dá)配置的大小以后,將會創(chuàng)建一個(gè)MapFile,將其寫到磁盤中去。這將減少HReginServer的內(nèi)存壓力。當(dāng)一起讀取的請求到來的時(shí)候,HReginServer會先在Memcache中尋找該數(shù)據(jù),當(dāng)找不到的時(shí)候,才會去在MapFiles 中尋找。
HBase Client
HBase Client負(fù)責(zé)尋找提供需求數(shù)據(jù)的HReginServer。在這個(gè)過程中,HBase Client將首先與HMaster通信,找到ROOT區(qū)域。這個(gè)操作是Client和Master之間僅有的通信操作。一旦ROOT區(qū)域被找到以后,Client就可以通過掃描ROOT區(qū)域找到相應(yīng)的META區(qū)域去定位實(shí)際提供數(shù)據(jù)的HReginServer。當(dāng)定位到提供數(shù)據(jù)的HReginServer以后,Client就可以通過這個(gè)HReginServer找到需要的數(shù)據(jù)了。這些信息將會被Client緩存起來,當(dāng)下次請求的時(shí)候,就不需要走上面的這個(gè)流程了。
HBase服務(wù)接口
HBase Thrift Server和HBase REST Server是通過非Java程序?qū)Base進(jìn)行訪問的一種途徑。
進(jìn)入正題
先來看一個(gè)HBase集群的模擬環(huán)境,此環(huán)境中一共有4臺機(jī)器,分別包含 zookeeper、HBaseMaster、HReginServer、HDSF 4個(gè)服務(wù),為了展示失效轉(zhuǎn)發(fā)的效果HBaseMaster、HReginServer各有2臺,只是在一臺機(jī)器上即運(yùn)行了HBaseMaster,也運(yùn)行了HReginServer。
注意,HBase的集群環(huán)境中HBaseMaster只有失效轉(zhuǎn)發(fā)沒有壓力分載的功能,而HReginServer即提供失效轉(zhuǎn)發(fā)也提供壓力分載。
服務(wù)器清單如下:
zookeeper 192.168.20.214
HBaseMaster 192.168.20.213/192.168.20.215
HReginServer 192.168.20.213/192.168.20.215
HDSF 192.168.20.212
整個(gè)模擬環(huán)境的架構(gòu)如圖所示:
注意,這里只是做了一個(gè)模擬環(huán)境,因?yàn)檫@個(gè)環(huán)境的重點(diǎn)是HBase,所以zookeeper和HDFS服務(wù)都是單臺。
雖然說在整個(gè)HBase的集群環(huán)境中只能有一個(gè)HMaster,可是在集群環(huán)境中HMaster可以啟動(dòng)多個(gè),但真正使用到的HMaster Server只有一個(gè),他不down掉的時(shí)候,其他啟動(dòng)的HMaster Server并不會工作,直到與ZooKeeper服務(wù)器判斷與當(dāng)前運(yùn)行的HMaster通訊超時(shí),認(rèn)為這個(gè)正在運(yùn)行的HMaster服務(wù)器down掉了,Zookeeper才會去連接下一臺HMaster Server。
簡單來說,如果運(yùn)行中HMaster服務(wù)器down掉了,那么zookeeper會從列表中選擇下一個(gè)HMaster 服務(wù)器進(jìn)行訪問,讓他接管down掉的HMaster任務(wù),換而言之,用Java客戶端對HBase進(jìn)行操作是通過ZooKeeper的,也就是說如果zookeeper集群中的節(jié)點(diǎn)全掛了 那么HBase的集群也掛了。本身HBase并不存儲中的任何數(shù)據(jù) 真正的數(shù)據(jù)是保存在HDFS上,所以HBase的數(shù)據(jù)是一致的,但是HDFS文件系統(tǒng)掛了,HBase的集群也掛。
在一臺HMaster失敗后,客戶端對HBase集群環(huán)境訪問時(shí),客戶端先會通過zookeeper識別到HMaster運(yùn)行異常,直到確認(rèn)多次后,才連接到下一個(gè)HMaster,此時(shí),備份的HMaster服務(wù)才生效,在IDE環(huán)境中的效果,如圖所示:
上圖中能看見拋出的一些異常和name:javahttp://www.javabloger.com和name:javahttp://www.javabloger.com1的結(jié)果集,因?yàn)槲以趕erv215機(jī)器上用killall java命令把 HMaster和HReginServer都關(guān)掉,并且立刻用Java客戶端對HBase的集群環(huán)境進(jìn)行訪問有異常拋出,但是retry到一定次數(shù)后查詢出結(jié)果,前面已經(jīng)說了訪問HBase是通過zookeeper再和真正的數(shù)據(jù)打交道,也就是說zookeeper接管了一個(gè)standby 的 HMaster,讓原先Standby的HMaster接替了失效的HMaster任務(wù),而被接管的HBaseMaster再對HReginServer的任務(wù)進(jìn)行分配,當(dāng) HReginServer失敗后zookeeper會通知 HMaster對HReginServer的任務(wù)進(jìn)行分配。這樣充分的說明了HBase做到了實(shí)效轉(zhuǎn)發(fā)的功能。
如圖所示:
口水:
1、HBase的失效轉(zhuǎn)發(fā)的效率比較慢了,不指望能在1-2秒切換和恢復(fù)完畢,也許是我暫時(shí)沒有發(fā)現(xiàn)有什么參數(shù)可以提高失效轉(zhuǎn)發(fā)和恢復(fù)過程的速度,將來會繼續(xù)關(guān)注這個(gè)問題。
2、在官方網(wǎng)站上看見HBase0.89.20100924的版本有篇講述關(guān)于數(shù)據(jù)同步的文章,我嘗試了一下在一臺機(jī)器上可以運(yùn)行所謂的HBase虛擬集群環(huán)境,但是切換到多臺機(jī)器的分布式環(huán)境中,單點(diǎn)失效轉(zhuǎn)發(fā)的速度很慢比HBase0.20.6還要慢,我又檢查了是否存在網(wǎng)絡(luò)的問題,目前尚未找到正確的答案,對與HBase0.89.20100924 新版中的數(shù)據(jù)同步的原理,如圖所示:(更多信息)
6 -白話MySQL(RDBMS)與HBase之間
我的廢話1:
任何一項(xiàng)新技術(shù)并非救命稻草,一抹一擦立馬藥到病除的百寶箱,并非使用Spring或者NOSQL的產(chǎn)品就神乎其神 五光十色,如果那樣基本是扯淡。同類 型產(chǎn)品中不管那種技術(shù)最終要達(dá)到的目的是一樣的,通過新的技術(shù)手段你往往可能避諱了當(dāng)前你所需要面對的問題,但過后新的問題又來了。也許回過頭來看看還不 如在原來的基礎(chǔ)上多動(dòng)動(dòng)腦筋 想想辦法 做些改良可以得到更高的回報(bào)。
傳統(tǒng)數(shù)據(jù)庫是以數(shù)據(jù)塊來存儲數(shù)據(jù),簡單來說,你的表字段越多,占用的數(shù)據(jù)空間就越多,那么查詢有可能就要跨數(shù)據(jù)塊,將會導(dǎo)致查詢的速度變慢。在大型系統(tǒng)中一張表上百個(gè)字段,并且表中的數(shù)據(jù)上億條這是完全是有可能的。因此會帶來數(shù)據(jù)庫查詢的瓶頸。我們都知道一個(gè)常識數(shù)據(jù)庫中表記錄的多少對查詢的性能有非常大的影響,此時(shí)你很有可能想到分表、分庫的做法來分載數(shù)據(jù)庫運(yùn)算的壓力,那么又會帶來新的問題,例如:分布式事務(wù)、全局唯一ID的生成、跨數(shù)據(jù)庫查詢 等,依舊會讓你面對棘手的問題。如果打破這種按照行存儲的模式,采用一種基于列存儲的模式,對于大規(guī)模數(shù)據(jù)場景這樣情況有可能發(fā)生一些好轉(zhuǎn)。由于查詢中的選擇規(guī)則是通過列來定義的,因此整個(gè)數(shù)據(jù)庫是自動(dòng)索引化的。按列存儲每個(gè)字段的數(shù)據(jù)聚集存儲, 可以動(dòng)態(tài)增加,并且列為空就不存儲數(shù)據(jù),節(jié)省存儲空間。 每個(gè)字段的數(shù)據(jù)按照聚集存儲,能大大減少讀取的數(shù)據(jù)量,查詢時(shí)指哪打哪,來的更直接。無需考慮分庫、分表 Hbase將對存儲的數(shù)據(jù)自動(dòng)切分?jǐn)?shù)據(jù),并支持高并發(fā)讀寫操作,使得海量數(shù)據(jù)存儲自動(dòng)具有更強(qiáng)的擴(kuò)展性。
Java中的HashMap是Key/Value的結(jié)構(gòu),你也可以把HBase的數(shù)據(jù)結(jié)構(gòu)看做是一個(gè)Key/Value的體系,話說HBase的區(qū)域由表名和行界定的。在HBase區(qū)域每一個(gè)'列族'都由一個(gè)名為HStore的對象管理。每個(gè)HStore由一個(gè)或多個(gè)MapFiles(Hadoop中的一個(gè)文件類型)組成。MapFiles的概念類似于Google的SSTable。 在Hbase里面有以下兩個(gè)主要的概念,Row key 和 Column Family,其次是Cell qualifier和Timestamp tuple,Column family我們通常稱之為“列族”,訪問控制、磁盤和內(nèi)存的使用統(tǒng)計(jì)都是在列族層面進(jìn)行的。列族Column family是之前預(yù)先定義好的數(shù)據(jù)模型,每一個(gè)Column Family都可以根據(jù)“限定符”有多個(gè)column。在HBase每個(gè)cell存儲單元對同一份數(shù)據(jù)有多個(gè)版本,根據(jù)唯一的時(shí)間戳來區(qū)分每個(gè)版本之間的差異,最新的數(shù)據(jù)版本排在最前面 。
口水:Hbase將table水平劃分成N個(gè)Region,region按column family劃分成Store,每個(gè)store包括內(nèi)存中的memstore和持久化到disk上的HFile。
上述可能我表達(dá)的還不夠到位,下面來看一個(gè)實(shí)踐中的場景,將原來是存放在MySQL中Blog中的數(shù)據(jù)遷移到HBase中的過程:
MySQL中現(xiàn)有的表結(jié)構(gòu):
遷移HBase中的表結(jié)構(gòu):
原來系統(tǒng)中有2張表blogtable和comment表,采用HBase后只有一張blogtable表,如果按照傳統(tǒng)的RDBMS的話,blogtable表中的列是固定的,比如schema 定義了Author,Title,URL,text等屬性,上線后表字段是不能動(dòng)態(tài)增加的。但是如果采用列存儲系統(tǒng),比如Hbase,那么我們可以定義blogtable表,然后定義info 列族,User的數(shù)據(jù)可以分為:info:title ,info:author ,info:url 等,如果后來你又想增加另外的屬性,這樣很方便只需要 info:xxx 就可以了。
對于Row key你可以理解row key為傳統(tǒng)RDBMS中的某一個(gè)行的主鍵,Hbase是不支持條件查詢以及Order by等查詢,因此Row key的設(shè)計(jì)就要根據(jù)你系統(tǒng)的查詢需求來設(shè)計(jì)了額。 Hbase中的記錄是按照rowkey來排序的,這樣就使得查詢變得非常快。
具體操作過程如下:
============================創(chuàng)建blogtable表========================= create 'blogtable', 'info','text','comment_title','comment_author','comment_text' ============================插入概要信息========================= put 'blogtable', '1', 'info:title', 'this is doc title' put 'blogtable', '1', 'info:author', 'javabloger' put 'blogtable', '1', 'info:url', 'http://www.javabloger.com/index.php' put 'blogtable', '2', 'info:title', 'this is doc title2' put 'blogtable', '2', 'info:author', 'H.E.' put 'blogtable', '2', 'info:url', 'http://www.javabloger.com/index.html' ============================插入正文信息========================= put 'blogtable', '1', 'text:', 'what is this doc context ?' put 'blogtable', '2', 'text:', 'what is this doc context2?' ==========================插入評論信息=============================== put 'blogtable', '1', 'comment_title:', 'this is doc comment_title ' put 'blogtable', '1', 'comment_author:', 'javabloger' put 'blogtable', '1', 'comment_text:', 'this is nice doc' put 'blogtable', '2', 'comment_title:', 'this is blog comment_title ' put 'blogtable', '2', 'comment_author:', 'H.E.' put 'blogtable', '2', 'comment_text:', 'this is nice blog'
HBase的數(shù)據(jù)查詢\讀取,可以通過單個(gè)row key訪問,row key的range和全表掃描,大致如下:
注意:HBase不能支持where條件、Order by 查詢,只支持按照Row key來查詢,但是可以通過HBase提供的API進(jìn)行條件過濾。
例如:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/ColumnPrefixFilter.html
scan 'blogtable' ,{COLUMNS => ['text:','info:title'] } —> 列出 文章的內(nèi)容和標(biāo)題
scan 'blogtable' , {COLUMNS => 'info:url' , STARTROW => '2'} —> 根據(jù)范圍列出 文章的內(nèi)容和標(biāo)題
get 'blogtable','1' —> 列出 文章id 等于1的數(shù)據(jù)
get 'blogtable','1', {COLUMN => 'info'} —> 列出 文章id 等于1 的 info 的頭(Head)內(nèi)容
get 'blogtable','1', {COLUMN => 'text'} —> 列出 文章id 等于1 的 text 的具體(Body)內(nèi)容
get 'blogtable','1', {COLUMN => ['text','info:author']} —> 列出 文章id 等于1 的內(nèi)容和作者(Body/Author)內(nèi)容
我的廢話2:
有人會問Java Web服務(wù)器中是Tomcat快還是GlassFish快?小型數(shù)據(jù)庫中是MySQL效率高還是MS-SQL效率高?我看是關(guān)鍵用在什么場景和怎么使用這 個(gè)產(chǎn)品(技術(shù)),所以我漸漸的認(rèn)為是需要對產(chǎn)品、技術(shù)本身深入的了解,而并非一項(xiàng)新的技術(shù)就是絕佳的選擇。試問:Tomcat的默認(rèn)的運(yùn)行參數(shù)能和我們線 上正在使用的GlassFish性能相提并論嗎?我不相信GlassFishv2和GlassFishv3在默認(rèn)的配置參數(shù)下有顯著的差別。我們需要對產(chǎn) 品本身做到深入的了解才能發(fā)揮他最高的性能,而并非感觀聽從廠家的廣告和自己的感性認(rèn)識 迷信哪個(gè)產(chǎn)品的優(yōu)越性。
我的廢話3:
對于NOSQL這樣的新技術(shù),的的確確是可以解決過去我們所需要面對的問題,但也并非適合每個(gè)應(yīng)用場景,所以在使用新產(chǎn)品的同時(shí)需要切合當(dāng)前的產(chǎn)品需要, 是需求在引導(dǎo)新技術(shù)的投入,而并非為了趕時(shí)髦去使用他。你的產(chǎn)品是否過硬不是你使用了什么新技術(shù),用戶關(guān)心的是速度和穩(wěn)定性,不會關(guān)心你是否使用了 NOSQL。相反Google有著超大的數(shù)據(jù)量,能給全世界用戶帶來了驚人的速度和準(zhǔn)確性,大家才會回過頭來好奇Google到底是怎么做到的。所以根據(jù) 自己的需要千萬別太勉強(qiáng)自己使用了某項(xiàng)新技術(shù)。
我的廢話4:
總之一句話,用什么不是最關(guān)鍵,最關(guān)鍵是怎么去使用!
7 -安全&權(quán)限
我的廢話:
大年三十夜,看春晚實(shí)在是太無聊了,整個(gè)《新聞聯(lián)播》的電視劇版本,還不如上上網(wǎng),看看資料,喝喝老酒,寫點(diǎn)東西來的快活。
近2年來云計(jì)算的話題到目前為止風(fēng)風(fēng)火火從來沒有平靜過,一直是大家嘴邊討論的熱門話題,人們期望運(yùn)用云計(jì)算提供可靠、穩(wěn)定、高速的計(jì)算,在云計(jì)算中Google是目前最大的云計(jì)算供應(yīng)商,例如:Google GAE(Google App Engine)和Google的Docs在線文章服務(wù),這些SaaS上線產(chǎn)品的數(shù)據(jù)存儲(datastore)是由BigTable提供存儲服務(wù)的,在次之前我提到過Yahoo貢獻(xiàn)給Apache的那些山寨版本(Google與Yahoo的那些利器),其中Apache的HBase就是山寨了Google的BigTable。
我們知道在云計(jì)算的技術(shù)話題中Apache的Hadoop項(xiàng)目是一塊基石,利用Hadoop項(xiàng)目中的產(chǎn)品可以建立云計(jì)算平臺和超大型的計(jì)算。不知道你是否有想過如果將HBase作為Google GAE上的數(shù)據(jù)存儲(datastore),那么每個(gè)用戶之間的數(shù)據(jù)訪問權(quán)限怎么辦?如果使用HBase提供對大客戶提供“私有云”(private cloud)或者另一種可能一個(gè)公司內(nèi)部的集群上運(yùn)行HBase,公司的內(nèi)部可能有幾個(gè)部門,某幾個(gè)部門之間的數(shù)據(jù)都是獨(dú)立分離但又運(yùn)行在一個(gè)平臺上,那么你就會發(fā)現(xiàn)HBase不具備這樣的功能,貌似目前HBase的最高版本0.90.0還沒有這樣的功能對用戶的表、Row、Cell的訪問權(quán)限。但是我們知道Google的GAE上每個(gè)用戶訪問的數(shù)據(jù)肯定是有權(quán)限劃分的,不然我只要有權(quán)限登錄GEA就能看見所有用戶存放的數(shù)據(jù)了。這樣的問題你有可能沒有想過,但趨勢公司的工程師們卻為此想到了這點(diǎn),并且把他們的設(shè)想和設(shè)計(jì)提交了HBase項(xiàng)目組,并且提出了以下主要的設(shè)計(jì)思想:
Client access to HBase is authenticated
User data is private unless access has been granted
Access to data can be granted at a table or per column family basis.
對HBase中的表和數(shù)據(jù)劃分權(quán)限等級和身份驗(yàn)證后,操作權(quán)限被分為3大類,每類中包含的操作權(quán)限如下所示:
對于方案中涉及到存儲的權(quán)限的是指整個(gè)表或表中的列族,也就是說只考慮在表這個(gè)級別的權(quán)限,表與表之間的所屬關(guān)系是存放在 .META. 系統(tǒng)表中,以regioninfo:owner 的格式進(jìn)行存放,例如:系統(tǒng)中table1這個(gè)表是有權(quán)限的,這個(gè)表權(quán)限的存根保存在3個(gè)地方 :
The row in .META. for the first region of table1
The node /hbase/acl/table1 of Zookeeper
The in-memory Permissions Mirror of every regionserver that serves table1
如圖所示,圖中的箭頭表示了數(shù)據(jù)流向的順序:
方案中HBase在分布式、集群環(huán)境下,而權(quán)限一致性的問題交給了Zookeeper來處理,在多個(gè)regionservers中,每個(gè)服務(wù)器的HRegion中存放著多個(gè)表,并且實(shí)現(xiàn)了(implement)ZKPermissionWatcher接口的nodeCreated() 和 nodeChanged() 方法,這2個(gè)方法對Zookeeper 的節(jié)點(diǎn)進(jìn)行監(jiān)控, 節(jié)點(diǎn)的狀態(tài)發(fā)生相應(yīng)的變化時(shí)會ZooKeeper刷新鏡像中的權(quán)限。
如圖所示:
HBase的這一關(guān)于權(quán)限的功能正在設(shè)計(jì)和研討當(dāng)中,讓我們繼續(xù)對他保持關(guān)注,看看今后將會發(fā)生的變化能給我們帶來什么樣的效果,非常期待這個(gè)功能早日正式發(fā)布。
轉(zhuǎn)自:作者:奧特man,發(fā)布于2012-12-14,來源:CSDN