2012年12月9日 星期日

HBase 新手常見問題與客戶端API


  1. Hbase 是甚麼
    Hbase 是 Apache Hadoop 的資料庫, 能夠對大型資料提供隨機、即時的讀寫存取. 目前已經是Apache眾多開放原始碼項目中的一個頂級專案.[HBase 實戰技術手冊]

    是用Java語言編寫的一個開源的、高可靠性、高性能、可伸縮、非關聯式的資料庫,用以存儲大規模結構化數據。
     
  2. HBase 用在哪裡
    HBase 的目標是儲存並處理大型的資料, 僅須使用普通的硬體, 就能夠處理成千上萬的行和列所組成的大型資料.[HBase 實戰技術手冊]
  3. HBase 的基本操作
  4. HBase 邏輯資料模型與實體資料模型
  5. HBase 用戶端管理功能 API
    HBase 提供了一系列定義資料的API, 這些API類似於關聯式資料庫中DDL(CREATE, ALTER, DROP...)和DML(SELECT, INSERT, UPDATE, DELETE...),
    1. Schema 的定義
      • Tables
      • 所有貯存在HBase上的Column最終會被群組到一個或多個Table裡, 主要的理由是讓Table可以控制Table裡面Column所共享的特殊設定. (舉例來說, 通常都會在Table中定義Column Families.)

        使用 Java 語言定義Table Descriptor的語法如下:

        HTableDescriptor();
        HTableDescriptor(String name);
        HTableDescriptor(byte[] name);
        HTableDescriptor(HTableDescriptor desc);


        在建立 Table 時, 可以指派一個name或使用現有的descriptor.
        不帶任何參數的建構方法僅供反序列化目的運用, 不能夠直接使用之.
        此外, Table的名字可使用Stringbyte[](位元組陣列)等兩種型別.
        這是因為byte[]是HBase唯一的資料型別, 因此, HBase的Java API大都提供Stringbyte[]兩種選擇. 使用String比較單純而方便, Hbase 會在內部自動將String轉成byte[]形式.

        透過Java的 Byte class 也可以自己把String轉成byte[]形式, 並運用其建構Table Descriptor:

        byte[] name = Bytes.toBytes("test");
        HTableDescriptor desc = new HTableDescriptor(name);

        Table的命名必須符合HBase的規範, 在透過HBase建立Table的時候, HBase會呼叫isLegalTableName來檢查命名是否符合規範, 具體的規範如下:不得為空不得以"."和"-"作為開頭命名只能包含英數字及".", "_", "-"
        http://www.oratea.net/?p=959

        直欄導向式資料庫(Column-oriented databases)可以在同一張資料表中貯存許多詳細資料, 同樣的資料在關聯式資料庫中則會被拆成好幾張表。
        因此HBase資料庫中的Table 數量通常會低於關聯式資料庫。

        過去在關聯式資料庫中所學的正規化原則在HBase中是不合適的。HBase資料庫適用反正規化原則

      出自 HBase: The Definitive Guide




      • Table 屬性(Table Properties)
        在上一個段落裡提到的Table Descriptor建構子提供了getters和setters讓我們可以針對Table的建構做更多設定。雖然不常用,但是在微調的時候會需要知道, 所以我們以下對這些屬性做一些簡單的介紹。

        Name
        在上一段落中我們已經提到在建構子的參數中可以自訂Table的Name, 然而API還提供了以下的Methods讓我們可以取得或變更Table的Name屬性。

        byte[] getName();
        String getNameAsString();
        void setName(byte[] name);

        另外要注意,Table的命名必須符合HBase的規範, 在透過HBase建立Table的時候, HBase會呼叫isLegalTableName來檢查命名是否符合規範,具體的規範如下:不得為空、不得以"."和"-"作為開頭、命名只能包含英數字及".", "_", "-"。

        Column families
        這是定義Table時最重要的設定, 必須定義Table中所要使用的Column Families。再次注意, Table中使用的Column Family 在設定之後是不能變動的。

        void addFamily(HColumnDescriptor family); //增加family
        boolean hasFamily(byte[] c);  //以name檢查family是否存在
        HColumnDescriptor[] getColumnFamilies();  //取得現有Column列表
        HColumnDescriptor getFamily(byte[]column);  //以name取得特定family
        HColumnDescriptor removeFamily(byte[] column);  //以name移除特定family

        Maximum file size

        這個參數可以定義Table中的Region最大可以成長到的大小。當Region成長到這個限制時系統就會對Region進行分割。其get與set方法如下:

        long getMaxFileSize();
        void setMaxFileSize(long maxFileSize);


        all the files belonging to each column family. If one single column family exceeds this maximum size, the region is split.


        Read-only
        所有的Table預設都是可寫入的(Writable), 但也可以依照需要, 將Table設定成為讀, 設定方式如下:

        boolean isReadOnly();
        void setReadOnly(boolean readOnly);


        Memstore flush size
        抵達 regionserver的寫入請求會先寫入到commit log中, 然後存放在記憶體中的memorystore。當memorystore滿了的時候, 才會將其中的內容真正寫入(flush)檔案系統。設定memstore flush的大小方式如下:

        long getMemStoreFlushSize();
        void setMemStoreFlushSize(long memstoreFlushSize);

        這個大小設定越大可以讓寫入檔案系統的次數減少, 藉此提昇效能, 但同時也會增加系統的風險。舉例來說, 若系統存了一堆資料在記憶體裡, 這時候卻死當, 存在記憶體裡還沒寫入檔案系統的資料就報銷了。

        Deferred log flush
        Java API提供設定是否使用deferred log的功能, 設定方式如下:
        (預設是不啟用)

        synchronized boolean isDeferredLogFlush();
        void setDeferredLogFlush(boolean isDeferredLogFlush);


        Miscellaneous options
        也可以在Table的定義裡儲存自己定義的Key/Value資料, 設定和存取的方式如下:

        byte[] getValue(byte[] key) {
        String getValue(String key)
        Map<ImmutableBytesWritable, ImmutableBytesWritable> getValues()
        void setValue(byte[] key, byte[] value)
        void setValue(String key, String value)
        void remove(byte[] key)
      • Column Families
        上面我們在介绍運用HTableDescriptor添加Column Family到Table裡面時,  約略談到了HColumnDescriptor, 其實HColumnDescriptor這個名字照理來講應該要取做HColumnFamilyDescriptor才能正確的表示是用來建構Column Family的功用, 這是在命名時的一個錯誤, 但是沒辦法, 軟體上太多這樣的將錯就錯。所以要記得, HColumnDescriptor是用來建構Column Family的喔。



        Name

        Maximum versions

        Compression

        Block size

        Block cache

        Time-to-live

        In-memory

        Bloom filter

        Replication scope
    2. HbaseAdmin
      • 基本操作 Basic Operations
      • 資料表操作 Table Operations
        範例:

        HBaseAdmin admin = new HBaseAdmin(conf);
        HTableDescriptor desc = new HTableDescriptor( Bytes.toBytes("testtable"));
        HColumnDescriptor coldef = new HColumnDescriptor(
        Bytes.toBytes("colfam1"));
        desc.addFamily(coldef);
        admin.createTable(desc);
        try {
                 admin.deleteTable(Bytes.toBytes("testtable"));
             }
        catch (IOException e) {
                 System.err.println("Error deleting table: " + e.getMessage());
        }
        admin.disableTable(Bytes.toBytes("testtable"));
        boolean isDisabled = admin.isTableDisabled(Bytes.toBytes("testtable"));
        System.out.println("Table is disabled: " + isDisabled);
        boolean avail1 = admin.isTableAvailable(Bytes.toBytes("testtable"));
        System.out.println("Table available: " + avail1);
        admin.deleteTable(Bytes.toBytes("testtable"));
        boolean avail2 = admin.isTableAvailable(Bytes.toBytes("testtable"));
        System.out.println("Table available: " + avail2);
        admin.createTable(desc);
        boolean isEnabled = admin.isTableEnabled(Bytes.toBytes("testtable"));
        System.out.println("Table is enabled: " + isEnabled);
      • Schema Operations
      • 叢集操作 Cluster Operations
      • 叢集狀態資訊 Cluster Status Information
  6. 結語
    API這種東西就是要用到的時候才會想要查, 參考書上在這個章節裡劈頭就說, 這張談到的參數很多都很少用到, 大概了解一下要用的時候在查就好。
  7. 參考資料


1 則留言:

  1. 您好,我想請問撰寫及執行API程式碼的平台或軟體為何?謝謝
    (在下初學,問的問題較為粗淺,敬請見諒)

    回覆刪除