天天看點

HBase詳細介紹及優化

1-Hbase的安裝

HBase是什麼?

HBase是Apache Hadoop中的一個子項目,Hbase依托于Hadoop的HDFS作為最基本存儲基礎單元,通過使用hadoop的DFS工具就可以看到這些這些資料 存儲檔案夾的結構,還可以通過Map/Reduce的架構(算法)對HBase進行操作,如右側的圖所示:

HBase詳細介紹及優化

HBase在産品中還包含了Jetty,在HBase啟動時采用嵌入式的方式來啟動Jetty,是以可以通過web界面對HBase進行管理和檢視目前運作的一些狀态,非常輕巧。

為什麼采用HBase?

HBase 不同于一般的關系資料庫,它是一個适合于非結構化資料存儲的資料庫.所謂非結構化資料存儲就是說HBase是基于列的而不是基于行的模式,這樣方面讀寫你的大資料内容。

HBase是介于Map Entry(key & value)和DB Row之間的一種資料存儲方式。就點有點類似于現在流行的Memcache,但不僅僅是簡單的一個key對應一個 value,你很可能需要存儲多個屬性的資料結構,但沒有傳統資料庫表中那麼多的關聯關系,這就是所謂的松散資料。

簡單來說,你在HBase中的表建立的可以看做是一張很大的表,而這個表的屬性可以根據需求去動态增加,在HBase中沒有表與表之間關聯查詢。你隻需要 告訴你的資料存儲到Hbase的那個column families 就可以了,不需要指定它的具體類型:char,varchar,int,tinyint,text等等。但是你需要注意HBase中不包含事務此類的功 能。

Apache HBase 和Google Bigtable 有非常相似的地方,一個資料行擁有一個可選擇的鍵和任意數量的列。表是疏松的存儲的,是以使用者可以給行定義各種不同的列,對于這樣的功能在大項目中非常實用,可以簡化設計和更新的成本。

如何運作HBase?

從 Apache的HBase的鏡像網站上下載下傳一個穩定版本的HBase http://mirrors.devlib.org/apache/hbase/stable/hbase-0.20.6.tar.gz, 下載下傳完成後,對其進行解壓縮。确定你的機器中已經正确的安裝了Java SDK、SSH,否則将無法正常運作。

$ cd /work/hbase

進入此目錄

$ vim conf/hbase-env.sh

export JAVA_HOME=/JDK_PATH

編輯 conf/hbase-env.sh 檔案,将JAVA_HOME修改為你的JDK安裝目錄

$ vim conf/regionservers

輸入你的所有HBase伺服器名,localhost,或者是ip位址

$ bin/start-hbase.sh

啟動hbase, 中間需要你輸入兩次密碼,也可以進行設定不需要輸入密碼,啟動成功,如圖所示:

HBase詳細介紹及優化

$ bin/hbase rest start

啟動hbase REST服務後就可以通過對uri: http://localhost:60050/api/ 的通用REST操作(GET/POST/PUT/DELETE)實作對hbase的REST形式資料操作.

也可以輸入以下指令進入HQL指令模式

$ bin/hbase shell

$ bin/stop-hbase.sh

關閉HBase服務

啟動時存在的問題

由于Linux系統的主機名配置不正确,在運作HBase伺服器中可能存在的問題,如圖所示:

HBase詳細介紹及優化

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

表示你的主機名不正确,你可以先檢視一下 /etc/hosts/中名稱是什麼,再用 hostname 指令進行修改, hostname you_server_name

檢視運作狀态

  1. 如果你需要對HBase的日志進行監控你可以檢視 hbase.x.x./logs/下的日志檔案,可以使用tail -f 來檢視。
  2. 通過 web方式檢視運作在 HBase 下的zookeeper http://localhost:60010/zk.jsp
  3. 如果你需要檢視目前的運作狀态可以通過web的方式對HBase伺服器進行檢視,如圖所示:
HBase詳細介紹及優化

擴充閱讀1:

Apach 的 Hadoop的項目中包含了那些産品,如圖所示:

HBase詳細介紹及優化

Pig 是在MapReduce上建構的查詢語言(SQL-like),适用于大量并行計算。

Chukwa 是基于Hadoop叢集中監控系統,簡單來說就是一個“看門狗” (WatchDog)

Hive 是DataWareHouse 和 Map Reduce交集,适用于ETL方面的工作。

HBase 是一個面向列的分布式資料庫。

Map Reduce 是Google提出的一種算法,用于超大型資料集的并行運算。

HDFS 可以支援千萬級的大型分布式檔案系統。

Zookeeper 提供的功能包括:配置維護、名字服務、分布式同步、組服務等,用于分布式系統的可靠協調系統。

Avro 是一個資料序列化系統,設計用于支援大批量資料交換的應用。

擴充閱讀2:

什麼是列存儲?列存儲不同于傳統的關系型資料庫,其資料在表中是按行存儲的,列方式所帶來的重要好處之一就是,由于查詢中的選擇規則是通過列來定義的,因 此整個資料庫是自動索引化的。按列存儲每個字段的資料聚集存儲,在查詢隻需要少數幾個字段的時候,能大大減少讀取的資料量,一個字段的資料聚集存儲,那就 更容易為這種聚集存儲設計更好的壓縮/解壓算法。這張圖講述了傳統的行存儲和列存儲的差別:

HBase詳細介紹及優化

擴充閱讀3:

對系統海量的Log4J日志可以存放在一個集中式的機器上,在此機器上安裝 splunk 可以友善對所有日志檢視,安裝方法可以參考:

http://www.splunk.com/base/Documentation/latest/Installation/InstallonLinux

2-Java操作HBase例子

本篇文章講述用HBase Shell指令 和 HBase Java API 對HBase 伺服器 進行操作。在此之前需要對HBase的總體上有個大概的了解。比如說HBase伺服器内部由哪些主要部件構成?HBase的内部工作原理是什麼?我想學習任何一項知識、技術的态度不能隻是知道如何使用,對産品的内部建構一點都不去關心,那樣出了問題,很難讓你很快的找到答案,甚至我們希望最後能對該項技術的領悟出自己的心得,為我所用,借鑒該項技術其中的設計思想創造出自己的解決方案,更靈活的去應對多變的計算場景與架構設計。以我目前的對HBase的了解還不夠深入,将來不斷的學習,我會把我所知道的點滴分享到這個Blog上。

先來看一下讀取一行記錄HBase是如何進行工作的,首先HBase Client端會連接配接Zookeeper Qurom(從下面的代碼也能看出來,例如:HBASE_CONFIG.set("hbase.zookeeper.quorum", "192.168.50.216") )。通過Zookeeper元件Client能獲知哪個Server管理-ROOT- Region。那麼Client就去通路管理-ROOT-的Server,在META中記錄了HBase中所有表資訊,(你可以使用 scan '.META.' 指令列出你建立的所有表的詳細資訊),進而擷取Region分布的資訊。一旦Client擷取了這一行的位置資訊,比如這一行屬于哪個Region,Client将會緩存這個資訊并直接通路HRegionServer。久而久之Client緩存的資訊漸漸增多,即使不通路.META.表也能知道去通路哪個HRegionServer。HBase中包含兩種基本類型的檔案,一種用于存儲WAL的log,另一種用于存儲具體的資料,這些資料都通過DFS Client和分布式的檔案系統HDFS進行互動實作存儲。

如圖所示:

HBase詳細介紹及優化

再來看看HBase的一些記憶體實作原理:

  • HMaster— HBase中僅有一個Master server。
  • HRegionServer—負責多個HRegion使之能向client端提供服務,在HBase cluster中會存在多個HRegionServer。
  • ServerManager—負責管理Region server資訊,如每個Region server的HServerInfo(這個對象包含HServerAddress和startCode),已load Region個數,死亡的Region server清單
  • RegionManager—負責将region配置設定到region server的具體工作,還監視root和meta 這2個系統級的region狀态。
  • RootScanner—定期掃描root region,以發現沒有配置設定的meta region。
  • MetaScanner—定期掃描meta region,以發現沒有配置設定的user region。

HBase基本指令

下面我們再看看看HBase的一些基本操作指令,我列出了幾個常用的HBase Shell指令,如下:

名稱 指令表達式
建立表 create '表名稱', '列名稱1','列名稱2','列名稱N'
添加記錄 put '表名稱', '行名稱', '列名稱:', '值'
檢視記錄 get '表名稱', '行名稱'
檢視表中的記錄總數 count '表名稱'
删除記錄 delete '表名' ,'行名稱' , '列名稱'
删除一張表 先要屏蔽該表,才能對該表進行删除,第一步 disable '表名稱' 第二步 drop '表名稱'
檢視所有記錄 scan "表名稱"
檢視某個表某個列中所有資料 scan "表名稱" , ['列名稱:']
更新記錄 就是重寫一遍進行覆寫

如果你是一個新手隊HBase的一些指令還不算非常熟悉的話,你可以進入 hbase 的shell 模式中你可以輸入 help 指令檢視到你可以執行的指令和對該指令的說明,例如對scan這個指令,help中不僅僅提到有這個指令,還詳細的說明了scan指令中可以使用的參數和作用,例如,根據列名稱查詢的方法和帶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伺服器進行操作

需要下列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);
     }
    
    /**
      * 建立一張表
     */
     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 .");
         }
         
     }
     
    /**
      * 添加一條資料
     */
     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 .");
     }
     
    /**
      * 顯示所有資料
     */
     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優化技巧

這篇文章淺顯的從幾個方面談談HBase的一些優化技巧,隻能作為我學習筆記的一部分,因為學多了怕忘,留給自己以後看看。

1 修改 linux 系統參數

Linux系統最大可打開檔案數一般預設的參數值是1024,如果你不進行修改并發量上來的時候會出現“Too Many Open Files”的錯誤,導緻整個HBase不可運作,你可以用ulimit -n 指令進行修改,或者修改/etc/security/limits.conf 和/proc/sys/fs/file-max 的參數,具體如何修改可以去Google 關鍵字 “linux limits.conf ”

2 JVM 配置

修改 hbase-env.sh 檔案中的配置參數,根據你的機器硬體和目前作業系統的JVM(32/64位)配置适當的參數

HBASE_HEAPSIZE 4000 HBase使用的 JVM 堆的大小

HBASE_OPTS "‐server ‐XX:+UseConcMarkSweepGC"JVM GC 選項

HBASE_MANAGES_ZKfalse 是否使用Zookeeper進行分布式管理

3 HBase持久化

重新開機作業系統後HBase中資料全無,你可以不做任何修改的情況下,建立一張表,寫一條資料進行,然後将機器重新開機,重新開機後你再進入HBase的shell中使用 list 指令檢視目前所存在的表,一個都沒有了。是不是很杯具?沒有關系你可以在hbase/conf/hbase-default.xml中設定hbase.rootdir的值,來設定檔案的儲存位置指定一個檔案夾 ,例如:<value>file:///you/hbase-data/path</value>,你建立的HBase中的表和資料就直接寫到了你的磁盤上,如圖所示:

HBase詳細介紹及優化

同樣你也可以指定你的分布式檔案系統HDFS的路徑例如: hdfs://NAMENODE_SERVER:PORT/HBASE_ROOTDIR,這樣就寫到了你的分布式檔案系統上了。

4 配置HBase運作參數

其次就需要對hbase/conf/hbase-default.xml 檔案進行配置,以下是我認為比較重要的配置參數

hbase.client.write.buffer

描述:這個參數可以設定寫入資料緩沖區的大小,當用戶端和伺服器端傳輸資料,伺服器為了提高系統運作性能開辟一個寫的緩沖區來處理它, 這個參數設定如果設定的大了,将會對系統的記憶體有一定的要求,直接影響系統的性能。

hbase.master.meta.thread.rescanfrequency

描述:多長時間 HMaster對系統表 root 和 meta 掃描一次,這個參數可以設定的長一些,降低系統的能耗。

hbase.regionserver.handler.count

描述:由于HBase/Hadoop的Server是采用Multiplexed, non-blocking I/O方式而設計的,是以它可以透過一個Thread來完成處理,但是由于處理Client端所呼叫的方法是Blocking I/O,是以它的設計會将Client所傳遞過來的物件先放置在Queue,并在啟動Server時就先産生一堆Handler(Thread),該Handler會透過Polling的方式來取得該物件并執行對應的方法,預設為25,根據實際場景可以設定大一些。

hbase.regionserver.thread.splitcompactcheckfrequency

描述:這個參數是表示多久去RegionServer伺服器運作一次split/compaction的時間間隔,當然split之前會先進行一個compact操作.這個compact操作可能是minor compact也可能是major compact.compact後,會從所有的Store下的所有StoreFile檔案最大的那個取midkey.這個midkey可能并不處于全部資料的mid中.一個row-key的下面的資料可能會跨不同的HRegion。

hbase.hregion.max.filesize

描述:HRegion中的HStoreFile最大值,任何表中的列族一旦超過這個大小将會被切分,而HStroeFile的預設大小是256M。

hfile.block.cache.size

描述:指定 HFile/StoreFile 緩存在JVM堆中配置設定的百分比,預設值是0.2,意思就是20%,而如果你設定成0,就表示對該選項屏蔽。

hbase.zookeeper.property.maxClientCnxns

描述: 這項配置的選項就是從zookeeper中來的,表示ZooKeeper用戶端同時通路的并發連接配接數,ZooKeeper對于HBase來說就是一個入口這個參數的值可以适當放大些。

hbase.regionserver.global.memstore.upperLimit

描述:在Region Server中所有memstores占用堆的大小參數配置,預設值是0.4,表示40%,如果設定為0,就是對選項進行屏蔽。

hbase.hregion.memstore.flush.size

描述:Memstore中緩存的内容超過配置的範圍後将會寫到磁盤上,例如:删除操作是先寫入MemStore裡做個标記,訓示那個value, column 或 family等下是要删除的,HBase會定期對存儲檔案做一個major compaction,在那時HBase會把MemStore刷入一個新的HFile存儲檔案中。如果在一定時間範圍内沒有做major compaction,而Memstore中超出的範圍就寫入磁盤上了。

5 HBase中log4j的日志

HBase中日志輸出等級預設狀态下是把debug、 info 級别的日志打開的,可以根據自己的需要調整log級别,HBase的log4j日志配置檔案在 hbase\conf\log4j.properties 目錄下。

4–存儲

在HBase中建立的一張表可以分布在多個Hregion,也就說一張表可以被拆分成多塊,每一塊稱我們呼為一個Hregion。每個Hregion會保 存一個表裡面某段連續的資料,使用者建立的那個大表中的每個Hregion塊是由Hregion伺服器提供維護,通路Hregion塊是要通過 Hregion伺服器,而一個Hregion塊對應一個Hregion伺服器,一張完整的表可以儲存在多個Hregion 上。HRegion Server 與Region的對應關系是一對多的關系。每一個HRegion在實體上會被分為三個部分:Hmemcache(緩存)、Hlog(日志)、HStore(持久層)。

上述這些關系在我腦海中的樣子,如圖所示:

1.HRegionServer、HRegion、Hmemcache、Hlog、HStore之間的關系,如圖所示:

HBase詳細介紹及優化

2.HBase表中的資料與HRegionServer的分布關系,如圖所示:

HBase詳細介紹及優化

HBase讀資料

HBase讀取資料優先讀取HMemcache中的内容,如果未取到再去讀取Hstore中的資料,提高資料讀取的性能。

HBase寫資料

HBase寫入資料會寫到HMemcache和Hlog中,HMemcache建立緩存,Hlog同步Hmemcache和Hstore的事務日志,發起Flush Cache時,資料持久化到Hstore中,并清空HMemecache。

用戶端通路這些資料的時候通過Hmaster ,每個 Hregion 伺服器都會和Hmaster 伺服器保持一個長連接配接,Hmaster 是HBase分布式系統中的管理者,他的主要任務就是要告訴每個Hregion 伺服器它要維護哪些Hregion。使用者的這些都資料可以儲存在Hadoop 分布式檔案系統上。 如果主伺服器Hmaster當機,那麼整個系統都會無效。下面我會考慮如何解決Hmaster的SPFO的問題,這個問題有點類似Hadoop的SPFO 問題一樣隻有一個NameNode維護全局的DataNode,HDFS一旦當機全部挂了,也有人說采用Heartbeat來解決這個問題,但我總想找出 其他的解決方案,多點時間,總有辦法的。

昨天在hadoop-0.21.0、hbase-0.20.6的環境中折騰了很久,一直報錯,錯誤資訊如下:

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 這個異常,是不是有可能是RPC 協定格式不一緻導緻的?也就是說伺服器端和用戶端的版本不一緻的問題?換了一個HDFS的伺服器端以後,一切都好了,果然是版本的問題,最後采用 hadoop-0.20.2 搭配hbase-0.20.6 比較穩當。

最後的效果如圖所示:

HBase詳細介紹及優化

上圖的一些文字說明:

  1. hadoop版本是0.20.2 ,
  2. hbase版本是0.20.6,
  3. 在hbase中建立了一張表 tab1,退出hbase shell環境,
  4. 用hadoop指令檢視,檔案系統中的檔案果然多了一個剛剛建立的tab1目錄,以上這張圖檔說明HBase在分布式檔案系統Apache HDFS中運作了。

5(叢集) -壓力分載與失效轉發

在上一篇關于HBase的文章中曾經講述過HBase在分布式中的架構,這篇文章将會講述HBase在分布式環境中是如何排除單點故障的(SPFO),做一個小實驗講述HBase在分布式環境中的高可用性,親眼看到一些現象,延伸一些思考的話題。

先來回顧一下HBase主要部件:

  1. HBaseMaster
  2. HRegionServer
  3. HBase Client
  4. HBase Thrift Server
  5. HBase REST Server

HBaseMaster

HMaster 負責給HRegionServer配置設定區域,并且負責對叢集環境中的HReginServer進行負載均衡,HMaster還負責監控叢集環境中的HReginServer的運作狀況,如果某一台HReginServer down機,HBaseMaster将會把不可用的HReginServer來提供服務的HLog和表進行重新配置設定轉交給其他HReginServer來提供,HBaseMaster還負責對資料和表進行管理,處理表結構和表中資料的變更,因為在 META 系統表中存儲了所有的相關表資訊。并且HMaster實作了ZooKeeper的Watcher接口可以和zookeeper叢集互動。

HRegionServer

HReginServer負責處理使用者的讀和寫的操作。HReginServer通過與HBaseMaster通信擷取自己需要服務的資料表,并向HMaster回報自己的運作狀況。當一個寫的請求到來的時候,它首先會寫到一個叫做HLog的write-ahead log中。HLog被緩存在記憶體中,稱為Memcache,每一個HStore隻能有一個Memcache。當Memcache到達配置的大小以後,将會建立一個MapFile,将其寫到磁盤中去。這将減少HReginServer的記憶體壓力。當一起讀取的請求到來的時候,HReginServer會先在Memcache中尋找該資料,當找不到的時候,才會去在MapFiles 中尋找。

HBase Client

HBase Client負責尋找提供需求資料的HReginServer。在這個過程中,HBase Client将首先與HMaster通信,找到ROOT區域。這個操作是Client和Master之間僅有的通信操作。一旦ROOT區域被找到以後,Client就可以通過掃描ROOT區域找到相應的META區域去定位實際提供資料的HReginServer。當定位到提供資料的HReginServer以後,Client就可以通過這個HReginServer找到需要的資料了。這些資訊将會被Client緩存起來,當下次請求的時候,就不需要走上面的這個流程了。

HBase服務接口

HBase Thrift Server和HBase REST Server是通過非Java程式對HBase進行通路的一種途徑。

進入正題

先來看一個HBase叢集的模拟環境,此環境中一共有4台機器,分别包含 zookeeper、HBaseMaster、HReginServer、HDSF 4個服務,為了展示失效轉發的效果HBaseMaster、HReginServer各有2台,隻是在一台機器上即運作了HBaseMaster,也運作了HReginServer。

注意,HBase的叢集環境中HBaseMaster隻有失效轉發沒有壓力分載的功能,而HReginServer即提供失效轉發也提供壓力分載。

伺服器清單如下:

  1. zookeeper 192.168.20.214
  2. HBaseMaster 192.168.20.213/192.168.20.215
  3. HReginServer 192.168.20.213/192.168.20.215
  4. HDSF 192.168.20.212

整個模拟環境的架構如圖所示:

HBase詳細介紹及優化

注意,這裡隻是做了一個模拟環境,因為這個環境的重點是HBase,是以zookeeper和HDFS服務都是單台。

雖然說在整個HBase的叢集環境中隻能有一個HMaster,可是在叢集環境中HMaster可以啟動多個,但真正使用到的HMaster Server隻有一個,他不down掉的時候,其他啟動的HMaster Server并不會工作,直到與ZooKeeper伺服器判斷與目前運作的HMaster通訊逾時,認為這個正在運作的HMaster伺服器down掉了,Zookeeper才會去連接配接下一台HMaster Server。

簡單來說,如果運作中HMaster伺服器down掉了,那麼zookeeper會從清單中選擇下一個HMaster 伺服器進行通路,讓他接管down掉的HMaster任務,換而言之,用Java用戶端對HBase進行操作是通過ZooKeeper的,也就是說如果zookeeper叢集中的節點全挂了 那麼HBase的叢集也挂了。本身HBase并不存儲中的任何資料 真正的資料是儲存在HDFS上,是以HBase的資料是一緻的,但是HDFS檔案系統挂了,HBase的叢集也挂。

在一台HMaster失敗後,用戶端對HBase叢集環境通路時,用戶端先會通過zookeeper識别到HMaster運作異常,直到确認多次後,才連接配接到下一個HMaster,此時,備份的HMaster服務才生效,在IDE環境中的效果,如圖所示:

HBase詳細介紹及優化

上圖中能看見抛出的一些異常和name:javahttp://www.javabloger.com和name:javahttp://www.javabloger.com1的結果集,因為我在serv215機器上用killall java指令把 HMaster和HReginServer都關掉,并且立刻用Java用戶端對HBase的叢集環境進行通路有異常抛出,但是retry到一定次數後查詢出結果,前面已經說了通路HBase是通過zookeeper再和真正的資料打交道,也就是說zookeeper接管了一個standby 的 HMaster,讓原先Standby的HMaster接替了失效的HMaster任務,而被接管的HBaseMaster再對HReginServer的任務進行配置設定,當 HReginServer失敗後zookeeper會通知 HMaster對HReginServer的任務進行配置設定。這樣充分的說明了HBase做到了實效轉發的功能。

如圖所示:

HBase詳細介紹及優化

口水:

1、HBase的失效轉發的效率比較慢了,不指望能在1-2秒切換和恢複完畢,也許是我暫時沒有發現有什麼參數可以提高失效轉發和恢複過程的速度,将來會繼續關注這個問題。

2、在官方網站上看見HBase0.89.20100924的版本有篇講述關于資料同步的文章,我嘗試了一下在一台機器上可以運作所謂的HBase虛拟叢集環境,但是切換到多台機器的分布式環境中,單點失效轉發的速度很慢比HBase0.20.6還要慢,我又檢查了是否存在網絡的問題,目前尚未找到正确的答案,對與HBase0.89.20100924 新版中的資料同步的原理,如圖所示:(更多資訊)

HBase詳細介紹及優化

6 -白話MySQL(RDBMS)與HBase之間

我的廢話1:

任何一項新技術并非救命稻草,一抹一擦立馬藥到病除的百寶箱,并非使用spring或者NOSQL的産品就神乎其神+五光十色,如果那樣基本是扯淡。同類 型産品中不管那種技術最終要達到的目的是一樣的,通過新的技術手段你往往可能避諱了目前你所需要面對的問題,但過後新的問題又來了。也許回過頭來看看還不 如在原來的基礎上多動動腦筋 想想辦法 做些改良可以得到更高的回報。

傳統資料庫是以資料塊來存儲資料,簡單來說,你的表字段越多,占用的資料空間就越多,那麼查詢有可能就要跨資料塊,将會導緻查詢的速度變慢。在大型系統中一張表上百個字段,并且表中的資料上億條這是完全是有可能的。是以會帶來資料庫查詢的瓶頸。我們都知道一個常識資料庫中表記錄的多少對查詢的性能有非常大的影響,此時你很有可能想到分表、分庫的做法來分載資料庫運算的壓力,那麼又會帶來新的問題,例如:分布式事務、全局唯一ID的生成、跨資料庫查詢 等,依舊會讓你面對棘手的問題。如果打破這種按照行存儲的模式,采用一種基于列存儲的模式,對于大規模資料場景這樣情況有可能發生一些好轉。由于查詢中的選擇規則是通過列來定義的,是以整個資料庫是自動索引化的。按列存儲每個字段的資料聚集存儲, 可以動态增加,并且列為空就不存儲資料,節省存儲空間。 每個字段的資料按照聚集存儲,能大大減少讀取的資料量,查詢時指哪打哪,來的更直接。無需考慮分庫、分表 Hbase将對存儲的資料自動切分資料,并支援高并發讀寫操作,使得海量資料存儲自動具有更強的擴充性。

Java中的HashMap是Key/Value的結構,你也可以把HBase的資料結構看做是一個Key/Value的體系,話說HBase的區域由表名和行界定的。在HBase區域每一個"列族"都由一個名為HStore的對象管理。每個HStore由一個或多個MapFiles(Hadoop中的一個檔案類型)組成。MapFiles的概念類似于Google的SSTable。 在Hbase裡面有以下兩個主要的概念,Row key 和 Column Family,其次是Cell qualifier和Timestamp tuple,Column family我們通常稱之為“列族”,通路控制、磁盤和記憶體的使用統計都是在列族層面進行的。列族Column family是之前預先定義好的資料模型,每一個Column Family都可以根據“限定符”有多個column。在HBase每個cell存儲單元對同一份資料有多個版本,根據唯一的時間戳來區分每個版本之間的差異,最新的資料版本排在最前面 。

口水:Hbase将table水準劃分成N個Region,region按column family劃分成Store,每個store包括記憶體中的memstore和持久化到disk上的HFile。

上述可能我表達的還不夠到位,下面來看一個實踐中的場景,将原來是存放在MySQL中Blog中的資料遷移到HBase中的過程:

MySQL中現有的表結構:

HBase詳細介紹及優化

遷移HBase中的表結構:

HBase詳細介紹及優化

原來系統中有2張表blogtable和comment表,采用HBase後隻有一張blogtable表,如果按照傳統的RDBMS的話,blogtable表中的列是固定的,比如schema 定義了Author,Title,URL,text等屬性,上線後表字段是不能動态增加的。但是如果采用列存儲系統,比如Hbase,那麼我們可以定義blogtable表,然後定義info 列族,User的資料可以分為:info:title ,info:author ,info:url 等,如果後來你又想增加另外的屬性,這樣很友善隻需要 info:xxx 就可以了。

對于Row key你可以了解row key為傳統RDBMS中的某一個行的主鍵,Hbase是不支援條件查詢以及Order by等查詢,是以Row key的設計就要根據你系統的查詢需求來設計了額。 Hbase中的記錄是按照rowkey來排序的,這樣就使得查詢變得非常快。

具體操作過程如下:

============================建立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的資料查詢\讀取,可以通過單個row key通路,row key的range和全表掃描,大緻如下:

注意:HBase不能支援where條件、Order by 查詢,隻支援按照Row key來查詢,但是可以通過HBase提供的API進行條件過濾。

例如:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/ColumnPrefixFilter.html

scan 'blogtable' ,{COLUMNS => ['text:','info:title'] } —> 列出 文章的内容和标題

scan 'blogtable' , {COLUMNS => 'info:url' , STARTROW => '2'} —> 根據範圍列出 文章的内容和标題

get 'blogtable','1' —> 列出 文章id 等于1的資料

get 'blogtable','1', {COLUMN => 'info'} —> 列出 文章id 等于1 的 info 的頭(Head)内容

get 'blogtable','1', {COLUMN => 'text'} —> 列出 文章id 等于1 的 text 的具體(Body)内容

get 'blogtable','1', {COLUMN => ['text','info:author']} —> 列出 文章id 等于1 的内容和作者(Body/Author)内容

我的廢話2:

有人會問Java Web伺服器中是Tomcat快還是GlassFish快?小型資料庫中是MySQL效率高還是MS-SQL效率高?我看是關鍵用在什麼場景和怎麼使用這 個産品(技術),是以我漸漸的認為是需要對産品、技術本身深入的了解,而并非一項新的技術就是絕佳的選擇。試問:Tomcat的預設的運作參數能和我們線 上正在使用的GlassFish性能相提并論嗎?我不相信GlassFishv2和GlassFishv3在預設的配置參數下有顯著的差别。我們需要對産 品本身做到深入的了解才能發揮他最高的性能,而并非感觀聽從廠家的廣告和自己的感性認識 迷信哪個産品的優越性。

我的廢話3:

對于NOSQL這樣的新技術,的的确确是可以解決過去我們所需要面對的問題,但也并非适合每個應用場景,是以在使用新産品的同時需要切合目前的産品需要, 是需求在引導新技術的投入,而并非為了趕時髦去使用他。你的産品是否過硬不是你使用了什麼新技術,使用者關心的是速度和穩定性,不會關心你是否使用了 NOSQL。相反Google有着超大的資料量,能給全世界使用者帶來了驚人的速度和準确性,大家才會回過頭來好奇Google到底是怎麼做到的。是以根據 自己的需要千萬别太勉強自己使用了某項新技術。

我的廢話4:

總之一句話,用什麼不是最關鍵,最關鍵是怎麼去使用!

7 -安全&權限

我的廢話:

大年三十夜,看春晚實在是太無聊了,整個《新聞聯播》的電視劇版本,還不如上上網,看看資料,喝喝老酒,寫點東西來的快活。

近2年來雲計算的話題到目前為止風風火火從來沒有平靜過,一直是大家嘴邊讨論的熱門話題,人們期望運用雲計算提供可靠、穩定、高速的計算,在雲計算中Google是目前最大的雲計算供應商,例如:Google GAE(Google App Engine)和Google的Docs線上文章服務,這些SaaS上線産品的資料存儲(datastore)是由BigTable提供存儲服務的,在次之前我提到過Yahoo貢獻給Apache的那些山寨版本(Google與Yahoo的那些利器),其中Apache的HBase就是山寨了Google的BigTable。

我們知道在雲計算的技術話題中Apache的Hadoop項目是一塊基石,利用Hadoop項目中的産品可以建立雲計算平台和超大型的計算。不知道你是否有想過如果将HBase作為Google GAE上的資料存儲(datastore),那麼每個使用者之間的資料通路權限怎麼辦?如果使用HBase提供對大客戶提供“私有雲”(private cloud)或者另一種可能一個公司内部的叢集上運作HBase,公司的内部可能有幾個部門,某幾個部門之間的資料都是獨立分離但又運作在一個平台上,那麼你就會發現HBase不具備這樣的功能,貌似目前HBase的最高版本0.90.0還沒有這樣的功能對使用者的表、Row、Cell的通路權限。但是我們知道Google的GAE上每個使用者通路的資料肯定是有權限劃分的,不然我隻要有權限登入GEA就能看見所有使用者存放的資料了。這樣的問題你有可能沒有想過,但趨勢公司的工程師們卻為此想到了這點,并且把他們的設想和設計送出了HBase項目組,并且提出了以下主要的設計思想:

  1. Client access to HBase is authenticated
  2. User data is private unless access has been granted
  3. Access to data can be granted at a table or per column family basis.

對HBase中的表和資料劃分權限等級和身份驗證後,操作權限被分為3大類,每類中包含的操作權限如下所示:

HBase詳細介紹及優化

對于方案中涉及到存儲的權限的是指整個表或表中的列族,也就是說隻考慮在表這個級别的權限,表與表之間的所屬關系是存放在 .META. 系統表中,以regioninfo:owner 的格式進行存放,例如:系統中table1這個表是有權限的,這個表權限的存根儲存在3個地方 :

  • 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

如圖所示,圖中的箭頭表示了資料流向的順序:

HBase詳細介紹及優化

方案中HBase在分布式、叢集環境下,而權限一緻性的問題交給了Zookeeper來處理,在多個regionservers中,每個伺服器的HRegion中存放着多個表,并且實作了(implement)ZKPermissionWatcher接口的nodeCreated() 和 nodeChanged() 方法,這2個方法對Zookeeper 的節點進行監控, 節點的狀态發生相應的變化時會ZooKeeper重新整理鏡像中的權限。

如圖所示:

HBase詳細介紹及優化

HBase的這一關于權限的功能正在設計和研讨當中,讓我們繼續對他保持關注,看看今後将會發生的變化能給我們帶來什麼樣的效果,非常期待這個功能早日正式釋出。

繼續閱讀