hbase java api 介紹 (1)

在之前, 我們介紹如何編譯hbase-client程式時,
曾經放上一段程式碼作為範例,
然而, 該程式碼需要預先建立好一個hbase table (myHBaseTable),
並且在myHBaseTable中, 建立一個column: myFamily,
在今天的範例中, 我們將擴展這個例子,
從建立table開始, 都由hbase java api負責, 以下是程式:

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.*;

import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.*;
import org.apache.hadoop.conf.Configuration;

public class hbasetest {
    public static Configuration conf;
    static {
        conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.property.clientPort", "2222");
        conf.set("hbase.zookeeper.quorum", "hbasemaster");
    }
    public static void main(String[] args) throws IOException {

        HBaseAdmin admin = new HBaseAdmin(conf);

        // create a hbase table
        String tablename = "myHBaseTable";
        String[] families = {"myFamily"};
        HTableDescriptor htd = new HTableDescriptor(tablename);
        for(String fmly :families)
{
HColumnDescriptor col = new HColumnDescriptor(fmly.getBytes());
htd.addFamily(col);
}
        if (admin.tableExists(tablename))
{
System.out.println("Table: " + tablename + "Existed.");
System.out.println("dropTable "+ tablename);
//drop the existing table
admin.disableTable(tablename);
admin.deleteTable(tablename);
}
        admin.createTable(htd);
System.out.println( tablename + " created.");

// Put
        HTable table = new HTable(conf, "myHBaseTable");
        Put p = new Put(Bytes.toBytes("myRow"));
        p.add(Bytes.toBytes("myFamily"), Bytes.toBytes("someQualifier"),
                Bytes.toBytes("Some Value"));
        table.put(p);

        // Get
        Get g = new Get(Bytes.toBytes("myRow"));
        Result r = table.get(g);
        byte[] value = r.getValue(Bytes.toBytes("myFamily"),
                Bytes.toBytes("someQualifier"));
        String valueStr = Bytes.toString(value);
        System.out.println("GET: " + valueStr);

        // Scan
        Scan s = new Scan();
        s.addColumn(Bytes.toBytes("myFamily"), Bytes.toBytes("someQualifier"));
        ResultScanner scanner = table.getScanner(s);
        try {
            for (Result rr : scanner) {
                System.out.println("Found row: " + rr);
            }
        } finally {
            scanner.close();
        }
    }
}


在程式的一開始, 先import要使用的java和hbase物件:

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.*;

import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.*;
import org.apache.hadoop.conf.Configuration;

接著宣告物件名稱(hbasetest),
hbase 連接的設定, 在這裡設定至少要包含zookeeper的位址(hbasemaster),
以及zookeeper的通訊埠(2222),

public class hbasetest {
    public static Configuration conf;
    static {
        conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.property.clientPort", "2222");
        conf.set("hbase.zookeeper.quorum", "hbasemaster");
    }

public static void main(String[] args) throws IOException {

在程式的一開始, 我們先用剛剛宣告的hbase資訊建立一個admin物件,
在hbase中, admin物件將能夠讀取hbase叢集的狀況,
並負責多數屬於master的操作:
[2016/05/21更新]
若是對於hbase叢集, 擁有多個zookeeper, 可以直接設定:
        conf.set("hbase.zookeeper.quorum", "hbasemaster,slave01,slave02");
程式在建立連線時, 會隨機分配建立的zookeeper查詢連線, 減低zookeeper負擔,

        HBaseAdmin admin = new HBaseAdmin(conf);

接著, 我們宣告hbase table的名稱(myHBaseTable),
column family的string array(families), 在範例中只有一個column(myFamily),
並把column family加入要創建的table中,

        // create a hbase table
        String tablename = "myHBaseTable";
        String[] families = {"myFamily"};
        HTableDescriptor htd = new HTableDescriptor(tablename);
        for(String fmly :families)
{
HColumnDescriptor col = new HColumnDescriptor(fmly.getBytes());
htd.addFamily(col);
}

確認是否有相同名稱的table存在, 若有則刪除,
注意, 在hbase中, table必須先disable, 才能夠drop,

        if (admin.tableExists(tablename))
{
System.out.println("Table: " + tablename + "Existed.");
System.out.println("dropTable "+ tablename);
//drop the existing table
admin.disableTable(tablename);
admin.deleteTable(tablename);
}

由於創建table是master的工作,
因此由admin來進行.

        admin.createTable(htd);
System.out.println( tablename + " created.");

當需要存入table時, 使用put這個指令,
在hbase中, 可以同時對一個row-key的多個column family進行儲存,
並在table.put時一次存入,

// Put
        HTable table = new HTable(conf, "myHBaseTable");
        Put p = new Put(Bytes.toBytes("myRow"));
        p.add(Bytes.toBytes("myFamily"), Bytes.toBytes("someQualifier"),
                Bytes.toBytes("Some Value"));
        table.put(p);

get指令則是從table中讀取特定列(row),特定行(column),特定限定(qualifier)的資料,
在hbase中, 限定(qualifier)的功用像是sub-column,
允許使用者對資料結構進行更詳細的分割,

        // Get
        Get g = new Get(Bytes.toBytes("myRow"));
        Result r = table.get(g);
        byte[] value = r.getValue(Bytes.toBytes("myFamily"),
                Bytes.toBytes("someQualifier"));
        String valueStr = Bytes.toString(value);
        System.out.println("GET: " + valueStr);

若是要大量讀取資料, 或是想要獲得row-key的數值, 則可以使用Scan,
進階的Scan功能可以搭配filter使用, 讀取某一區段的row-key範圍,
完成Scan後記得要關閉Scan物件(scanner.close()),

        // Scan
        Scan s = new Scan();
        s.addColumn(Bytes.toBytes("myFamily"), Bytes.toBytes("someQualifier"));
        ResultScanner scanner = table.getScanner(s);
        try {
            for (Result rr : scanner) {
                System.out.println("Found row: " + rr);
            }
        } finally {
            scanner.close();
        }
    }
}

以下是執行後的結果:
Table: myHBaseTableExisted.
dropTable myHBaseTable
15/03/23 13:35:29 INFO client.HBaseAdmin: Started disable of myHBaseTable
15/03/23 13:35:31 INFO client.HBaseAdmin: Disabled myHBaseTable
15/03/23 13:35:33 INFO client.HBaseAdmin: Deleted myHBaseTable
myHBaseTable created.
GET: Some Value
Found row: keyvalues={myRow/myFamily:someQualifier/1427117737305/Put/vlen=10/ts=0}

留言

熱門文章

LTE筆記: RSRP, RSSI and RSRQ

[WiFi] WiFi 網路的識別: BSS, ESS, SSID, ESSID, BSSID

LTE筆記: 波束成型 (beamforming) 和天線陣列