HBase 資料庫應用

Post on 24-Feb-2016

114 views 0 download

description

Hadoop 進階課程. HBase 資料庫應用 . < V 0.20 >. 王耀聰 陳威宇 Jazz@nchc.org.tw waue@nchc.org.tw. HBase 資料庫應用 . 一、導論. 原本我們使用關聯式資料庫好好的,為何又要有新資料庫的儲存架構型態,是有其必要?或新技術可完全取而代之?還是只是一個等待泡沫化新技術的濫觴?. Adapted From http://hbase.apache.org. 海量資料緒論. Hadoop 能運算海量資料,然後呢? 其實 Hadoop 運算出來的結果也不少 - PowerPoint PPT Presentation

Transcript of HBase 資料庫應用

HBase 資料庫應用 王耀聰 陳威宇

Jazz@nchc.org.twwaue@nchc.org.tw

< V 0.20 >

Hadoop 進階課程

2

一、導論原本我們使用關聯式資料庫好好的,為何又要有新資料庫的儲存架構型態,是有其必要?或新技術可完全取而代之?還是只是一個等待泡沫化新技術的濫觴?

HBase 資料庫應用

Adapted From http://hbase.apache.org

3

海量資料緒論 Hadoop 能運算海量資料,然後呢?

其實 Hadoop 運算出來的結果也不少 如何處理 Hadoop 運算出來的資料?

再用 Hadoop 運算一次 ?? 海量資料也需要整理

排序 搜尋 選擇

4

RDBMS / 資料庫 Relational DataBase Management System = 關聯式資料庫管理系統

Oracle 、 IBM DB2 、 SQL Server 、 MySQL…

5

RDBMS 碰上大資料 RDBMS 的好處

提供了很多而且很豐富的操作方式 SQL 語法普遍被使用

但當資料量愈來愈大時,會遇到單台機器的 ”囧”境 網路頻寬有限 空間有限

走向多台機器架構

6

跨足多台機器的 RDBMS

讀取的 query 比寫入的 query 多 Replication

slave 過多時,造成每台記憶體內重複 cache 相同元素

Memcached 寫入的 query 超過單台可以負荷的量時, replication 技術則導致每台 Slave 一起掛

Sharding 依照 id ,把資料拆散到各台 (如 Flickr)

7

多台機器的 RDBMS 的缺點 需要 application server 或是 library 配合,否則第三方程式找不到資料放在哪個 node 無法隨意使用 JOIN 及 transaction ,即使可以硬要使用效能也很差 設計 schema 時必須注意,當一個 cluster 愈來愈大時要 rebalance

8

是否非 RDBMS 不可? Web 2.0 網站很多時候

不需要 transaction 減少 JOIN 次數 多次 SELECT 拉資料

一開始寫在一台 DB 主機的 SQL 程式無法再套用於後來多台 SQL 主機的架構上 程式有可能全部重寫

9

將 RDBMS 簡化吧 RDBMS -> key-value DataBase

簡化掉不需要的功能,到只剩下 key-value 的架構 GET(key) SET(key, value) DELETE(key)

類似 Excel

10

Distributed key-value System

key-value DataBase -> Distributed key-value DataBase

加強 key-value 架構的 scalability ,使得增加機器就可以增加容量與頻寬 適合管理大量分散於不同主機的資料 通稱為 NoSQL DataBase

11

常見的 NoSQL OpenSource HBase (Yahoo!) Cassandra (Facebook) MongoDB CouchDB (IBM) SimpleDB (Amazon)Commercial BigTable (Google)

12

2010 年 NoSQL 職缺排行榜1. Cassandra 2. HBase 3. CouchDB 4. MongoDB

5. SimpleDB

(2010-07-25)

13

一、 HBase 介紹介紹 HBase 如何而來,它的 Why, What,

How …. ,以及它的架構

HBase 資料庫應用

HBase, Hadoop database, is an open-source, distributed, versioned, column-oriented store modeled after Google' Bigtable. Use it when you need random,

realtime read/write access to your Big Data.

Adapted From http://hbase.apache.org

14

BigTable ?

Bigtable: 一個結構化數據的分佈式存儲系統 Google Style 的數據庫,使用結構化的文件來存儲數據 不支持關聯或是類似於 SQL 的高級查詢。 大規模處理、高容錯性 PB 級的存儲能力 每秒數百萬的讀寫操作

15

HBase 設計概念與結構類似 Bigtable HBase 以 Hadoop 分散式檔案系統 (HDFS) 為基礎, 提供類 Bigtable 功能 HBase 是具有以下特點的儲存系統:

類似表格的資料結構 (Multi-Dimensional Map) 分散式 高可用性、高效能 很容易擴充容量及效能

HBase 適用於利用數以千計的一般伺服器上,來儲存 Petabytes 級的資料。 HBase 同時提供 Hadoop MapReduce 程式設計。

16

開發歷程 Started toward by Chad Walters and Jim 2006.11

Google releases paper on BigTable 2007.2

Initial HBase prototype created as Hadoop contrib. 2007.10

First useable HBase 2008.1

Hadoop become Apache top-level project and HBase becomes subproject

2010.3 HBase graduates from Hadoop sub-project to Apache Top Level Project

2010.7 HBase 0.20.6 released

17

誰使用 HBase Adobe

內部使用 (Structure data) Kalooga

圖片搜尋引擎 http://www.kalooga.com/ Meetup

社群聚會網站 http://www.meetup.com/ Streamy

成功從 MySQL 移轉到 Hbase http://www.streamy.com/ Trend Micro

雲端掃毒架構 http://trendmicro.com/ Yahoo!

儲存文件 fingerprint 避免重複 http://www.yahoo.com/ More

http://wiki.apache.org/hadoop/Hbase/PoweredBy

18

為什麼使用 HBase? 不是關聯式 (Relational) 資料庫系統

表格 (Table) 只有一個主要索引 (primary index) 即 row key. 不提供 join 不提供 SQL 語法。

提供 Java函式庫 , 與 REST 與 Thrift 等介面。 提供 getRow(), Scan() 存取資料。

getRow() 可以取得一筆 row range 的資料,同時也可以指定版本 (timestamp) 。 Scan() 可以取得整個表格的資料或是一組 row range

( 設定 start key, end key) 有限的單元性 (Atomicity) 與交易 (transaction) 功能 . 只有一種資料型態 (bytes) 可以配合 MapReduce框架,進行複雜的分析與查詢

19

Data Model Table 依 row key 來自動排序 Table schema 只要定義 column families .

每個 column family 可有無限數量的 columns 每個 column 的值可有無限數量的時間版本 (timestamp) Column 可以動態新增,每個 row 可有不同數量的 columns 。 同一個 column family 的 columns 會群聚在一個實體儲存單元上,且依 column 的名稱排序。 byte[] 是唯一的資料型態 (Row, Family: Column, Timestamp)

Value

Row key

Column Family

valueTimeStamp

20

Data Model

HBase 實際上儲存 Table 時,是以 column family 為單位來存放

21

HTable 成員Contents Department

news bid sport

t1

com.yahoo.news.tw

“撿到學雜費,硬要分三成” “tech”

t2 “科研論文評比 5校進500 大” “tech”

t3 “罰蹲立 300 下!班長「住院」 師懊悔” “tech”

t1 com.yahoo.bid.tw “… iphone 4G 9/17 日上市” “ 3C ”

t1com.yahoo.sport.t

w “Nadal 大滿貫” “MBA”

Table, Family, Column, Qualifier , Row, TimeStamp

22

Regions 表格是由一或多個 region 所構成

Region 是由其 startKey 與 endKey 所指定 每個 region 可能會存在於多個不同節點上,而且是由數個 HDFS 檔案與區塊所構成,這類

region 是由 Hadoop 負責複製

23

HBase 與 Hadoop 搭配的架構From: http://www.larsgeorge.com/2009/10/hbase-architecture-101-storage.html

24

HBase 0.20 特色 解決單點失效問題( single point of

failure ) Ex: Hadoop NameNode failure

設定檔改變或小版本更新會重新啟動 隨機讀寫( Random access )效能如同

MySQL

25

Zookeeper ?

From: http://www.spnguru.com/?p=211

Hadoop 的正式子項目 針對大型分散式系統的可靠協調系統 Google 的 Chubby 存儲一些配置信息 ,確保文件寫入的一致性等 Master / Client 架構,

Master 可由選舉而得

26

二、 HBase 安裝說明

HBase 資料庫應用

27

安裝

$ wget http://ftp.twaren.net/Unix/Web/apache/hadoop/hbase/hbase-0.20.6/hbase-0.20.6.tar.gz$ sudo tar -zxvf hbase-*.tar.gz -C /opt/$ sudo ln -sf /opt/hbase-0.20.6 /opt/hbase$ sudo chown -R $USER:$USER /opt/hbase

需先安裝過 Hadoop…

28

系統環境設定 $ vim /opt/hbase/conf/hbase-env.sh

# 基本設定export JAVA_HOME=/usr/lib/jvm/java-6-sunexport HADOOP_HOME=/opt/hadoopexport HBASE_HOME=/opt/hbaseexport HBASE_LOG_DIR=/var/hadoop/hbase-logsexport HBASE_PID_DIR=/var/hadoop/hbase-pidsexport HBASE_CLASSPATH=$HBASE_CLASSPATH:/opt/hadoop/conf

# 叢集選項export HBASE_MANAGES_ZK=true

服務參數設定 <configuration> <property>    <name> name </name>   <value> value </value>  </property>

</configuration>

Name valuehbase.rootdir hdfs://localhost:9000/hbase

hbase.tmp.dir /var/hadoop/hbase-${user.name} hbase.cluster.distributed true hbase.zookeeper.property.clientPort

2222

hbase.zookeeper.quorum Host1, Host2hbase.zookeeper.property.dataDir

/var/hadoop/hbase-data

29

30

停止與啟動服務 全部啟動 / 關閉

$ bin/start-hbase.sh$ bin/stop-hbase.sh

個別啟動 / 關閉$ bin/hbase-daemon.sh start/stop zookeeper$ bin/hbase-daemon.sh start/stop master$ bin/hbase-daemon.sh start/stop regionserver$ bin/hbase-daemon.sh start/stop thrif$ bin/hbase-daemon.sh start/stop rest

需先啟動 Hadoop…

31

測試 $ hbase shell> create 'test', 'data'0 row(s) in 4.3066 seconds> listtest1 row(s) in 0.1485 seconds> put 'test', 'row1', 'data:1', 'value1'0 row(s) in 0.0454 seconds> put 'test', 'row2', 'data:2', 'value2'0 row(s) in 0.0035 seconds> put 'test', 'row3', 'data:3', 'value3'0 row(s) in 0.0090 seconds

> scan 'test'ROW COLUMN+CELLrow1 column=data:1, timestamp=1240148026198,

value=value1row2 column=data:2, timestamp=1240148040035,

value=value2row3 column=data:3, timestamp=1240148047497,

value=value33 row(s) in 0.0825 seconds> disable 'test'09/04/19 06:40:13 INFO client.HBaseAdmin: Disabled test0 row(s) in 6.0426 seconds> drop 'test'09/04/19 06:40:17 INFO client.HBaseAdmin: Deleted test0 row(s) in 0.0210 seconds> list0 row(s) in 2.0645 seconds

32

連線到 HBase 的方法 Java client

get(byte [] row, byte [] column, long timestamp, int versions);

Non-Java clients Thrift server hosting HBase client instance

Sample ruby, c++, & java (via thrift) clients REST server hosts HBase client

TableInput/OutputFormat for MapReduce HBase as MR source or sink

HBase Shell JRuby IRB with “DSL” to add get, scan, and admin ./bin/hbase shell YOUR_SCRIPT

33

三、 HBase 程式設計3.1 程式編譯方法3.2 Coding & API

3.2.1 常用的 API 說明3.2.2 實做 I/O 操作

3.2.3 搭配 Map Reduce 運算3.2.4 進階補充

3.3 案例演練

HBase 資料庫應用

34

3.1 HBase 程式編譯方法此篇介紹兩種編譯與執行 HBase 程式的方法:

Method A – 使用 Java JDK 1.6 Method B – 使用 Eclipse 套件

三、 HBase 程式設計

3535

A. Java 之編譯與執行1. 將 hbase_home目錄內的 .jar 檔全部拷貝至

hadoop_home/lib/ 資料夾內2. 編譯

javac Δ -classpath Δ hadoop-*-core.jar:hbase-*.jar Δ -d Δ

MyJava Δ MyCode.java3. 封裝

jar Δ -cvf Δ MyJar.jar Δ -C Δ MyJava Δ .4. 執行

bin/hadoop Δ jar Δ MyJar.jar Δ MyCode Δ {Input/ Δ Output/ }

•所在的執行目錄為 Hadoop_Home•./MyJava = 編譯後程式碼目錄•Myjar.jar = 封裝後的編譯檔

•先放些文件檔到 HDFS 上的 input目錄•./input; ./ouput 不一定為 hdfs的輸入、輸出目錄

36

B Eclipse 之編譯與執行 HBase 已可以於 Hadoop 上正常運作 請先設定好 Eclipse 上得 Hadoop 開發環境

可參考附錄 Hadoop更詳細說明請參考另一篇 Hadoop

0.20 程式設計 建立一個 hadoop 的專案

37

B.1 設定專案的細部屬性1

2

在建立好的專案上點選右鍵,並選擇 properties

38

B.2 增加 專案的 Classpath

1

2

3

39

B.3 選擇 classpath 的 library

重複 2.2 的步驟來選取 hbase-0.20.* .jar 與 lib/ 資料夾內的所有 jar 檔

40

B.4 為函式庫增加原始碼、說明檔的配置

41

三、 HBase 程式設計

3.2.1 常用的HBase API 說明

此篇列出用 Java 寫 HBase 程式,常用到的 API 與說明

HTable 成員

Contents Department

news bid sport

t1

com.yahoo.news.tw

“我研發水下 6千公尺機器人” “tech”

t2 “蚊子怎麼搜尋人肉” “tech”

t3 “用腦波「發聲」 ” “tech”

t1 com.yahoo.bid.tw “… ipad …” “ 3C ”

t1 com.yahoo.sport.tw “… Wang 40…” “MBA”42

Table, Family, Column, Qualifier , Row, TimeStamp

43

HBase 常用函式 HBaseAdmin HBaseConfiguration HTable HTableDescriptor Put Get Scanner

Database

TableFamily

Column Qualifier

44

HBaseConfiguration Adds HBase configuration files to a

Configuration = new HBaseConfiguration ( ) = new HBaseConfiguration (Configuration c)

繼承自 org.apache.hadoop.conf.Configuration

回傳值 函數 參數void addResource (Path file)void clear ()String get (String name)String getBoolean (String name, boolean defaultValue )void set (String name, String value)void setBoolean (String name, boolean value)

<property> <name> name </name> <value> value </value></property>

45

HBaseAdmin HBase 的管理介面

= new HBaseAdmin( HBaseConfiguration conf ) Ex:

回傳值 函數 參數

void

addColumn (String tableName, HColumnDescriptor column)

checkHBaseAvailable (HBaseConfiguration conf)

createTable (HTableDescriptor desc)deleteTable (byte[] tableName)deleteColumn (String tableName, String columnName)enableTable (byte[] tableName)disableTable (String tableName)

HTableDescriptor[] listTables ()void modifyTable (byte[] tableName, HTableDescriptor htd)boolean tableExists (String tableName)

HBaseAdmin admin = new HBaseAdmin(config);admin.disableTable (“tablename”);

46

HTableDescriptor HTableDescriptor contains the name of an HTable, and its column families.

= new HTableDescriptor() = new HTableDescriptor(String name)

Constant-values org.apache.hadoop.hbase.HTableDescriptor.TABLE_DESCRIPTOR_VERSION

Ex:

回傳值 函數 參數void addFamily (HColumnDescriptor family) HColumnDescriptor removeFamily (byte[] column)byte[] getName ( ) = Table namebyte[] getValue (byte[] key) = 對應 key 的 valuevoid setValue (String key, String value)

HTableDescriptor htd = new HTableDescriptor(tablename);htd.addFamily ( new HColumnDescriptor (“Family”));

47

HColumnDescriptor An HColumnDescriptor contains information about a column family

= new HColumnDescriptor(String familyname) Constant-values

org.apache.hadoop.hbase.HTableDescriptor.TABLE_DESCRIPTOR_VERSION Ex:

回傳值 函數 參數byte[] getName ( ) = Family namebyte[] getValue (byte[] key) = 對應 key 的 valuevoid setValue (String key, String value)

HTableDescriptor htd = new HTableDescriptor(tablename);HColumnDescriptor col = new HColumnDescriptor("content:");htd.addFamily(col);

48

HTable Used to communicate with a single HBase table.

= new HTable(HBaseConfiguration conf, String tableName) Ex:

回傳值 函數 參數void checkAndPut (byte[] row, byte[] family, byte[] qualifier, byte[]

value, Put put) void close ()boolean exists (Get get)Result get (Get get)byte[][] getEndKeys ()ResultScanner getScanner (byte[] family)HTableDescriptor getTableDescriptor ()byte[] getTableName ()static boolean isTableEnabled (HBaseConfiguration conf, String tableName)void put (Put put)

HTable table = new HTable (conf, Bytes.toBytes ( tablename ));ResultScanner scanner = table.getScanner ( family );

49

Put Used to perform Put operations for a single row.

= new Put(byte[] row) = new Put(byte[] row, RowLock rowLock)

Ex:

Put add (byte[] family, byte[] qualifier, byte[] value)Put add (byte[] column, long ts, byte[] value)byte[] getRow ()RowLock getRowLock ()long getTimeStamp ()boolean isEmpty ()Put setTimeStamp (long timestamp)

HTable table = new HTable (conf, Bytes.toBytes ( tablename ));Put p = new Put ( brow );p.add (family, qualifier, value);table.put ( p );

50

Get Used to perform Get operations on a single row.

= new Get (byte[] row) = new Get (byte[] row, RowLock rowLock)

Ex:

Get addColumn (byte[] column)Get addColumn (byte[] family, byte[] qualifier)Get addColumns (byte[][] columns)Get addFamily (byte[] family)TimeRange getTimeRange ()Get setTimeRange (long minStamp, long maxStamp)Get setFilter (Filter filter)

HTable table = new HTable(conf, Bytes.toBytes(tablename));Get g = new Get(Bytes.toBytes(row));

51

Result Single row result of a Get or Scan query.

= new Result() Ex:

boolean containsColumn (byte[] family, byte[] qualifier)NavigableMap <byte[],byte[]> getFamilyMap (byte[] family)

byte[] getValue (byte[] column)byte[] getValue (byte[] family, byte[] qualifier)int Size ()

HTable table = new HTable(conf, Bytes.toBytes(tablename));Get g = new Get(Bytes.toBytes(row));Result rowResult = table.get(g);Bytes[] ret = rowResult.getValue( (family + ":"+ column ) );

52

Scanner All operations are identical to Get

Rather than specifying a single row, an optional startRow and stopRow may be defined.

If rows are not specified, the Scanner will iterate over all rows. = new Scan () = new Scan (byte[] startRow, byte[] stopRow) = new Scan (byte[] startRow, Filter filter)

Get addColumn (byte[] column)Get addColumn (byte[] family, byte[] qualifier)Get addColumns (byte[][] columns)Get addFamily (byte[] family)TimeRange getTimeRange ()Get setTimeRange (long minStamp, long maxStamp)Get setFilter (Filter filter)

53

Interface ResultScanner Interface for client-side scanning. Go to HTable to

obtain instances. HTable.getScanner (Bytes.toBytes(family));

Ex:

void close ()Result next ()

ResultScanner scanner = table.getScanner (Bytes.toBytes(family));for (Result rowResult : scanner) {

Bytes[] str = rowResult.getValue ( family , column );}

54

HBase Key/Value 的格式 org.apache.hadoop.hbase.KeyValue getRow(), getFamily(), getQualifier(), getTimestamp(),

and getValue(). The KeyValue blob format inside the byte array is:

Key 的格式 :

Rowlength 最大值為 Short.MAX_SIZE, column family length 最大值為 Byte.MAX_SIZE, column qualifier + key length 必須小於 Integer.MAX_SIZE.

<keylength> <valuelength> <key> <value>

< row- length > < row>

< column-family-

length >

< column-family >

< column-qualifier >

< time-stamp >

< key-type >

55

三、 HBase 程式設計

3.2.2 實做 I/O 操作HBase 的 I/O 操作 範例程式碼

56

範例一:新增 Table

$ hbase shell> create ‘tablename', ‘family1', 'family2', 'family3‘0 row(s) in 4.0810 seconds> Listtablename1 row(s) in 0.0190 seconds

< 指令 > create < 表名 >, {<family>, ….}

57

範例一:新增 Table public static void createHBaseTable ( String tablename, String

familyname ) throws IOException {

HBaseConfiguration config = new HBaseConfiguration();HBaseAdmin admin = new HBaseAdmin(config);

HTableDescriptor htd = new HTableDescriptor( tablename ); HColumnDescriptor col = new HColumnDescriptor( familyname ); htd.addFamily ( col ); if( admin.tableExists(tablename)) { return () } admin.createTable(htd); }

< 程式碼 >

58

範例二: Put 資料進 Column< 指令>

> put 'tablename','row1', 'family1:qua1', 'value' 0 row(s) in 0.0030 seconds

put ‘ 表名’ , ‘列’ , ‘column’, ‘值’ , [‘ 時間’ ]

59

範例二: Put 資料進 Columnstatic public void putData(String tablename, String row, String family,

String column, String value) throws IOException {HBaseConfiguration config = new HBaseConfiguration();HTable table = new HTable(config, tablename);byte[] brow = Bytes.toBytes(row);byte[] bfamily = Bytes.toBytes(family);byte[] bcolumn = Bytes.toBytes(column);byte[] bvalue = Bytes.toBytes(value);Put p = new Put(brow);p.add(bfamily, bcolumn, bvalue);table.put(p);table.close();

}

< 程式碼 >

60

範例三: Get Column Value< 指令>

> get 'tablename', 'row1' COLUMN CELL family1:column1 timestamp=1265169495385, value=value1 row(s) in 0.0100 seconds

get ‘ 表名’ , ‘列’

61

範例三: Get Column ValueString getColumn ( String tablename, String row, String

family, String column ) throws IOException {HBaseConfiguration conf = new HBaseConfiguration();HTable table;table = new HTable( conf, Bytes.toBytes( tablename));Get g = new Get(Bytes.toBytes(row));Result rowResult = table.get(g);return Bytes.toString( rowResult.getValue ( Bytes.toBytes (family + “:” + column)));}

< 程式碼 >

62

範例四: Scan all Column

> scan 'tablename'ROW COLUMN+CELL row1 column=family1:column1, timestamp=1265169415385, value=value1row2 column=family1:column1, timestamp=1263534411333, value=value2row3 column=family1:column1, timestamp=1263645465388, value=value3row4 column=family1:column1, timestamp=1264654615301, value=value4row5 column=family1:column1, timestamp=1265146569567, value=value55 row(s) in 0.0100 seconds

< 指令>

scan ‘ 表名’

63

範例四: Scan all Columnstatic void ScanColumn(String tablename, String family, String

column) throws IOException {HBaseConfiguration conf = new HBaseConfiguration();HTable table = new HTable ( conf,

Bytes.toBytes(tablename));ResultScanner scanner = table.getScanner(

Bytes.toBytes(family));int i = 1;for (Result rowResult : scanner) {

byte[] by = rowResult.getValue( Bytes.toBytes(family),

Bytes.toBytes(column) );String str = Bytes.toString ( by );System.out.println("row " + i + " is \"" + str

+"\"");i++;

}}}

< 程式碼 >

64

範例五: 刪除資料表

> disable 'tablename'0 row(s) in 6.0890 seconds> drop 'tablename' 0 row(s) in 0.0090 seconds0 row(s) in 0.0090 seconds0 row(s) in 0.0710 seconds

< 指令>

disable ‘ 表名’ drop ‘ 表名’

65

範例五: 刪除資料表static void drop ( String tablename ) throws IOExceptions {

HBaseConfiguration conf = new HBaseConfiguration();HBaseAdmin admin = new HBaseAdmin (conf);if (admin.tableExists(tablename)) {

admin.disableTable(tablename);admin.deleteTable(tablename);

}else{System.out.println(" [" + tablename+ "] not

found!"); }}

< 程式碼 >

66

三、 HBase 程式設計

3.2.3 MapReduce 與HBase 的搭配HBase 的 MapReduce 範例程式碼

67

範例六: WordCountHBase說明: 此程式碼將輸入路徑的檔案內的字串取出做字數統計 再將結果塞回 HTable 內運算方法:將此程式運作在 hadoop 0.20 平台上,用 (參考 2) 的方法加入 hbase參數後,將此程式碼打包成 XX.jar 結果:

> scan 'wordcount' ROW COLUMN+CELL

am column=content:count, timestamp=1264406245488, value=1 chen column=content:count, timestamp=1264406245488, value=1 hi, column=content:count, timestamp=1264406245488, value=2注意:1. 在 hdfs 上來源檔案的路徑為 "/user/$YOUR_NAME/input"請注意必須先放資料到此 hdfs 上的資料夾內,且此資料夾內只能放檔案,不可再放資料夾2. 運算完後,程式將執行結果放在 hbase 的 wordcount 資料表內

68

範例六: WordCountHBasepublic class WordCountHBase{ public static class Map extends

Mapper<LongWritable,Text,Text, IntWritable>

{ private IntWritable i = new

IntWritable(1); public void map(LongWritable

key,Text value,Context context) throws IOException, InterruptedException

{ String s[] =

value.toString().trim().split(" "); for( String m : s) { context.write(new Text(m), i);}}}

public static class Reduce extends TableReducer<Text, IntWritable, NullWritable> {

public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {

int sum = 0; for(IntWritable i : values) { sum += i.get(); }

Put put = new Put(Bytes.toBytes(key.toString()));

put.add(Bytes.toBytes("content"), Bytes.toBytes("count"), Bytes.toBytes(String.valueOf(sum)));

context.write(NullWritable.get(), put);

} }

<1>

69

範例六: WordCountHBase public static void createHBaseTable(String

tablename)throws IOException { HTableDescriptor htd = new

HTableDescriptor(tablename); HColumnDescriptor col = new

HColumnDescriptor("content:"); htd.addFamily(col); HBaseConfiguration config = new

HBaseConfiguration(); HBaseAdmin admin = new

HBaseAdmin(config); if(admin.tableExists(tablename)) { admin.disableTable(tablename); admin.deleteTable(tablename); } System.out.println("create new table: " +

tablename); admin.createTable(htd); }

public static void main(String args[]) throws Exception { String tablename = "wordcount"; Configuration conf = new Configuration(); conf.set(TableOutputFormat.OUTPUT_TABLE,

tablename); createHBaseTable(tablename); String input = args[0]; Job job = new Job(conf, "WordCount " + input); job.setJarByClass(WordCountHBase.class); job.setNumReduceTasks(3); job.setMapperClass(Map.class); job.setReducerClass(Reduce.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(IntWritable.class); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TableOutputFormat.class); FileInputFormat.addInputPath(job, new Path(input));

System.exit(job.waitForCompletion(true)?0:1); }}

<2>

70

範例七: LoadHBaseMapper 說明: 此程式碼將 HBase 的資料取出來,再將結果塞回 hdfs 上運算方法:將此程式運作在 hadoop 0.20 平台上,用 (參考 2) 的方法加入 hbase參數後,將此程式碼打包成 XX.jar 結果: $ hadoop fs -cat <hdfs_output>/part-r-00000 ---------------------------

54 30 31GunLong54 30 32Esing54 30 33SunDon54 30 34StarBucks

---------------------------注意:1. 請注意 hbase 上必須要有 table, 並且已經有資料2. 運算完後,程式將執行結果放在你指定 hdfs 的 <hdfs_output> 內 請注意 沒有 <hdfs_output> 資料夾

71

範例七: LoadHBaseMapperpublic class LoadHBaseMapper {public static class HtMap extends

TableMapper<Text, Text> {public void

map(ImmutableBytesWritable key, Result value,

Context context) throws IOException, InterruptedException {String res = Bytes.toString(value.getValue(Bytes.toBytes("Detail"),

Bytes.toBytes("Name")));context.write(new Text(key.toString()), new Text(res));

}}

public static class HtReduce extends Reducer<Text, Text, Text, Text> {

public void reduce(Text key, Iterable<Text> values, Context context)

throws IOException, InterruptedException {String str = new String("");Text final_key = new Text(key);Text final_value = new Text();for (Text tmp : values) {

str += tmp.toString(); }final_value.set(str);context.write(final_key, final_value);

}}

<1>

72

範例七: LoadHBaseMapperpublic static void main(String args[])

throws Exception {String input = args[0];String tablename = "tcrc";Configuration conf = new

Configuration();Job job = new Job (conf, tablename +

" hbase data to hdfs");job.setJarByClass

(LoadHBaseMapper.class);TableMapReduceUtil.

initTableMapperJob(tablename, myScan,

HtMap.class,Text.class, Text.class, job);

job.setMapperClass (HtMap.class);

job.setReducerClass (HtReduce.class);job.setMapOutputKeyClass (Text.class);job.setMapOutputValueClass

(Text.class);job.setInputFormatClass

( TableInputFormat.class);job.setOutputFormatClass

( TextOutputFormat.class);job.setOutputKeyClass( Text.class);job.setOutputValueClass( Text.class);FileOutputFormat.setOutputPath ( job,

new Path(input));System.exit (job.waitForCompletion

(true) ? 0 : 1);}}

<2>

73

三、 HBase 程式設計

3.2.4 進階補充HBase 內 contrib 的項目,如

A. TrancationalB. Thrift

74

A. Transactional HBase Indexed Table = Secondary Index = Transactional

HBase 內容與原本 table 相似的另一張 table ,但 key 不同,利於排列內容

name price description

1 apple 10 xx

2 orig 5 ooo

3 banana 15 vvvv

4 tomato 8 uu

name price description

2 orig 5 ooo

4 tomato 8 uu

1 apple 10 xx

3 banana 15 vvvv

Indexed TablePrimary Table

75

A.1 Transactional HBase環境設定 <property> <name> hbase.regionserver.class </name> <value> org.apache.hadoop.hbase.ipc.IndexedRegionInterface

</value> </property> <property> <name> hbase.regionserver.impl </name> <value>org.apache.hadoop.hbase.regionserver.tableindexed.IndexedRegionServer </value> </property>

需在 $HBASE_INSTALL_DIR/conf/hbase-site.xml 檔內增加兩項內容

76

A.a Ex : 從一個原有的 Table 增加 IndexedTablepublic void addSecondaryIndexToExistingTable

(String TableName, String IndexID, String IndexColumn) throws IOException {HBaseConfiguration conf = new HBaseConfiguration();IndexedTableAdmin admin = null;admin = new IndexedTableAdmin(conf);admin.addIndex(Bytes.toBytes(TableName), new IndexSpecification(

IndexID, Bytes.toBytes(IndexColumn)));}}

77

A.b Ex : 建立一個新的 Table 附帶 IndexedTablepublic void createTableWithSecondaryIndexes(String TableName,

String IndexColumn) throws IOException {HBaseConfiguration conf = new HBaseConfiguration();conf.addResource(new Path("/opt/hbase/conf/hbase-site.xml"));HTableDescriptor desc = new HTableDescriptor(TableName);desc.addFamily(new HColumnDescriptor(“Family1"));IndexedTableDescriptor Idxdesc = new IndexedTableDescriptor(desc);Idxdesc.addIndex(new IndexSpecification(IndexColumn, Bytes

.toBytes(" Family1 :" + IndexColumn)));IndexedTableAdmin admin = new IndexedTableAdmin(conf);admin.createIndexedTable(Idxdesc);

}

78

B. Thrift 由 Facebook 所開發 提供跨語言做資料交換的平台 你可以用任何 Thrift 有支援的語言來存取

HBase PHP Perl C++ Python …..

79

B.1 安裝方法 Thrift ( 0.2 ~ 0.4 ) + PHP 5 + HBase

0.20 http://trac.nchc.org.tw/cloud/wiki/waue/20

10/HbaseThrift 請先安裝 HBase 之後,並用套件安裝工具安裝 PHP 相關套件,再用此連結內的教材安裝 Thrift

80

B.2 Thrift 的 PHP 程式碼 http://trac.nchc.org.tw/cloud/wiki/waue/20

10/HbaseThrift 連線 列出所有 table 刪除 table 寫入資料 讀取資料 Scan 一整張 table

81

三、 HBase 程式設計

3.3 案例演練利用一個虛擬的案例來運用之前的程式碼

8282

中科餐廳開張囉! 故事背景:

中科餐城即將開張,預估有大批人潮 管理局想統計餐城內所有餐廳的營運狀況

用傳統資料庫可能: 大規模資料、同時讀寫,資料分析運算、…(自行發揮)

因此員工餐廳將導入 HBase 資料庫存放資料 透過 Hadoop進行Map Reduce 分析運算

8383

3.3.1. 建立商店資料

Detail Products TurnoverName Locate P1 P2 P3 P4

T01 GunLong 01 20 40 30 50T02 ESing 02 50T03 SunDon 03 40 30

T04 StarBucks 04 50 50 20

假設:目前有四間商店進駐中科餐廳,分別為位在第 1區的 GunLong ,品項 4項單價為 <20,40,30,50>第 2區的 ESing,品項 1項單價為 <50> 第 3區的 SunDon,品項 2項單價為 <40,30> 第 4區的 StarBucks,品項 3項單價為 <50,50,20>

8484

3.3.1.a 建立初始 HTablepublic void createHBaseTable(String tablename, String[] family)

throws IOException {HTableDescriptor htd = new HTableDescriptor(tablename);for (String fa : family) {

htd.addFamily(new HColumnDescriptor(fa));}HBaseConfiguration config = new HBaseConfiguration();HBaseAdmin admin = new HBaseAdmin(config);if (admin.tableExists(tablename)) {

System.out.println("Table: " + tablename + "Existed.");} else {

System.out.println("create new table: " + tablename);

admin.createTable(htd);}}

< 程式碼>

8585

3.3.1.a 執行結果

Family Detail Products TurnoverQualifier … … …Row1 valueRow2Row3…

Table: TCRC

8686

3.3.1.b 用讀檔方式把資料匯入HTable

void loadFile2HBase(String file_in, String table_name) throws IOException {BufferedReader fi = new BufferedReader(

new FileReader(new File(file_in)));String line;while ((line = fi.readLine()) != null) {

String[] str = line.split(";");int length = str.length;PutData.putData(table_name, str[0].trim(), "Detail", "Name", str[1]

.trim());PutData.putData(table_name, str[0].trim(), "Detail", "Locate",

str[2].trim());for (int i = 3; i < length; i++) {

PutData.putData(table_name, str[0], "Products", "P" + (i - 2),str[i]);

}System.out.println();

}fi.close();}

< 程式碼>

8787

3.3.1.b 執行結果Detail Products Turnover

Name Locate P1 P2 P3 P4

T01 GunLong 01 20 40 30 50

T02 ESing 02 50

T03 SunDon 03 40 30

T04 StarBucks 04 50 50 20

8888

3.3.1. 螢幕輸出結果create new table: tcrcPut data :"GunLong" to Table: tcrc's Detail:NamePut data :"01" to Table: tcrc's Detail:LocatePut data :"20" to Table: tcrc's Products:P1Put data :"40" to Table: tcrc's Products:P2Put data :"30" to Table: tcrc's Products:P3Put data :"50" to Table: tcrc's Products:P4

Put data :"Esing" to Table: tcrc's Detail:NamePut data :"02" to Table: tcrc's Detail:LocatePut data :"50" to Table: tcrc's Products:P1

Put data :"SunDon" to Table: tcrc's Detail:NamePut data :"03" to Table: tcrc's Detail:LocatePut data :"40" to Table: tcrc's Products:P1Put data :"30" to Table: tcrc's Products:P2

Put data :"StarBucks" to Table: tcrc's Detail:NamePut data :"04" to Table: tcrc's Detail:LocatePut data :"50" to Table: tcrc's Products:P1Put data :"50" to Table: tcrc's Products:P2Put data :"20" to Table: tcrc's Products:P3

8989

3.3.2 計算單月每個品項的購買次數 刷卡購餐的系統將每人每次購餐紀錄成檔案,格式如右 讀紀錄檔並統計每天每個品項的消費次數

將檔案上傳至 hdfs 使用 Hadoop 運算

計算完後寫入 HBase Turnover:P1,P2,P3,P4

waue:T01:P1:xx jazz:T01:P2:xxx lia:T01:P3:xxxx hung:T02:P1:xx lia:T04:P1:xxxx

lia:T04:P1:xxxx hung:T04:P3:xxhung:T04:P2:xx

……

9090

3.3.2. 用 Hadoop 的 Map Reduce 運算並把結果匯入 HTable

public class tcrc2Count {public static class HtMap extends

Mapper<LongWritable, Text, Text, IntWritable> {

private IntWritable one = new IntWritable(1);

public void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {String s[] = value.toString().trim().split(":");// xxx:T01:P4:oooo => T01@P4String str = s[1] + "@" + s[2];context.write(new Text(str), one);

}}

public static class HtReduce extendsTableReducer<Text, IntWritable, LongWritable> {

public void reduce(Text key, Iterable<IntWritable> values,

Context context) throws IOException, InterruptedException {int sum = 0;for (IntWritable i : values) sum += i.get();String[] str = (key.toString()).split("@");byte[] row = (str[0]).getBytes();byte[] family = Bytes.toBytes("Turnover");byte[] qualifier = (str[1]).getBytes();byte[] summary = Bytes.toBytes(String.valueOf(sum));Put put = new Put(row);put.add(family, qualifier, summary );context.write(new LongWritable(), put);

}}

<reduce 程式碼>

<map 程式碼 >

9191

public static void main(String args[]) throws Exception {String input = "income";String tablename = "tcrc";Configuration conf = new Configuration();conf.set(TableOutputFormat.OUTPUT_TABLE, tablename);Job job = new Job(conf, "Count to tcrc");job.setJarByClass(tcrc2Count.class);job.setMapperClass(HtMap.class);job.setReducerClass(HtReduce.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(IntWritable.class);job.setInputFormatClass(TextInputFormat.class);job.setOutputFormatClass(TableOutputFormat.class);FileInputFormat.addInputPath(job, new Path(input));System.exit(job.waitForCompletion(true) ? 0 : 1);}}

3.3.2. 用 Hadoop 的 Map Reduce 運算並把結果匯入 HTable< Main 程式碼 >

9292

3.3.2 執行結果Detail Products Turnover

Name Locate P1 P2 P3 P4 P1 P2 P3 P4

T01 GunLong 01 20 40 30 50 1 1 1 1

T02 ESing 02 50 2

T03 SunDon 03 40 30 3

T04 StarBucks04 50 50 20 2 1 1

9393

> scan 'tcrc'ROW COLUMN+CELL T01 column=Detail:Locate, timestamp=1265184360616, value=01 T01 column=Detail:Name, timestamp=1265184360548, value=GunLong T01 column=Products:P1, timestamp=1265184360694, value=20 T01 column=Products:P2, timestamp=1265184360758, value=40 T01 column=Products:P3, timestamp=1265184360815, value=30 T01 column=Products:P4, timestamp=1265184360866, value=50 T01 column=Turnover:P1, timestamp=1265187021528, value=1 T01 column=Turnover:P2, timestamp=1265187021528, value=1 T01 column=Turnover:P3, timestamp=1265187021528, value=1 T01 column=Turnover:P4, timestamp=1265187021528, value=1 T02 column=Detail:Locate, timestamp=1265184360951, value=02 T02 column=Detail:Name, timestamp=1265184360910, value=Esing T02 column=Products:P1, timestamp=1265184361051, value=50 T02 column=Turnover:P1, timestamp=1265187021528, value=2 T03 column=Detail:Locate, timestamp=1265184361124, value=03 T03 column=Detail:Name, timestamp=1265184361098, value=SunDon T03 column=Products:P1, timestamp=1265184361189, value=40 T03 column=Products:P2, timestamp=1265184361259, value=30 T03 column=Turnover:P1, timestamp=1265187021529, value=3 T04 column=Detail:Locate, timestamp=1265184361311, value=04 T04 column=Detail:Name, timestamp=1265184361287, value=StarBucks T04 column=Products:P1, timestamp=1265184361343, value=50 T04 column=Products:P2, timestamp=1265184361386, value=50 T04 column=Products:P3, timestamp=1265184361422, value=20 T04 column=Turnover:P1, timestamp=1265187021529, value=2 T04 column=Turnover:P2, timestamp=1265187021529, value=1 T04 column=Turnover:P3, timestamp=1265187021529, value=1 4 row(s) in 0.0310 seconds

9494

3.3.3. 計算當天營業額 計算每間商店的營業額

Σ ( <該項商品單價 > X < 被購買的次數> )

透過 Hadoop 的 Map () 從 HBase 內的 Products:{P1,P2,P3,P4} 與 Turnover:{P1,P2,P3,P4} 調出來

經過計算後由 Hadoop 的 Reduce () 寫回HBase 內 Turnover:Sum 的 Column 內

需考慮到表格內每家的商品數量皆不同、有的品項沒有被購買

9595

3.3.3. Hadoop 來源與輸出皆為 HBasepublic class tcrc3CalculateMR {public static class HtMap extends TableMapper<Text, Text> {public void map(ImmutableBytesWritable key, Result value,

Context context) throws IOException, InterruptedException {String row = Bytes.toString(value.getValue(Bytes.toBytes("Detail"),

Bytes.toBytes("Locate")));int sum = 0;for (int i = 0; i < 4; i++) {

String v = Bytes.toString(value.getValue(Bytes.toBytes("Products"), Bytes.toBytes("P"

+ (i + 1))));String c = Bytes.toString(value.getValue(Bytes

.toBytes("Turnover"), Bytes.toBytes("P" + (i + 1))));if (v != null ) {

if(c == null) c="0";System.err.println("p=" + v);System.err.println("c=" + c);sum += Integer.parseInt(v) * Integer.parseInt(c);System.err.println("T" + row + ":" + "p[" + i + "]*"

+ "c["+ i + "] => " + v + "*" + c +

"+="+ (sum)); }}

context.write(new Text("T" + row), new Text(String.valueOf(sum))); }}

public static class HtReduce extends TableReducer<Text, Text, Text> {

public void reduce(Text key, Iterable<Text> values, Context context)throws IOException, InterruptedException {

String sum = "";for (Text i : values) {

sum += i.toString();}Put put = new

Put(Bytes.toBytes(key.toString()));

put.add(Bytes.toBytes("Turnover"), Bytes.toBytes("Sum"), Bytes

.toBytes(sum));context.write(new Text(), put);}}

<reduce 程式碼>

<map 程式碼 >

9696

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

String tablename = "tcrc";Scan myScan = new Scan();myScan.addColumn("Detail:Locate".getBytes());myScan.addColumn("Products:P1".getBytes());myScan.addColumn("Products:P2".getBytes());myScan.addColumn("Products:P3".getBytes());myScan.addColumn("Products:P4".getBytes());myScan.addColumn("Turnover:P1".getBytes());myScan.addColumn("Turnover:P2".getBytes());myScan.addColumn("Turnover:P3".getBytes());myScan.addColumn("Turnover:P4".getBytes());Configuration conf = new Configuration();

Job job = new Job(conf, "Calculating ");job.setJarByClass(tcrc3CalculateMR.class);job.setMapperClass(HtMap.class);job.setReducerClass(HtReduce.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(Text.class);job.setInputFormatClass(TableInputFormat.class);job.setOutputFormatClass(TableOutputFormat.class

);TableMapReduceUtil.initTableMapperJob(tablenam

e, myScan, HtMap.class,Text.class, Text.class, job);

TableMapReduceUtil.initTableReducerJob(tablename, HtReduce.class, job);

System.exit(job.waitForCompletion(true) ? 0 : 1);}}

3.3.3. Hadoop 來源與輸出皆為 HBase< Main 程式碼 >

9797

> scan ‘tcrc’ROW COLUMN+CELL T01 column=Detail:Locate, timestamp=1265184360616, value=01 T01 column=Detail:Name, timestamp=1265184360548, value=GunLong T01 column=Products:P1, timestamp=1265184360694, value=20 T01 column=Products:P2, timestamp=1265184360758, value=40 T01 column=Products:P3, timestamp=1265184360815, value=30 T01 column=Products:P4, timestamp=1265184360866, value=50 T01 column=Turnover:P1, timestamp=1265187021528, value=1 T01 column=Turnover:P2, timestamp=1265187021528, value=1 T01 column=Turnover:P3, timestamp=1265187021528, value=1 T01 column=Turnover:P4, timestamp=1265187021528, value=1 T01 column=Turnover:sum, timestamp=1265190421993, value=140 T02 column=Detail:Locate, timestamp=1265184360951, value=02 T02 column=Detail:Name, timestamp=1265184360910, value=Esing T02 column=Products:P1, timestamp=1265184361051, value=50 T02 column=Turnover:P1, timestamp=1265187021528, value=2 T02 column=Turnover:sum, timestamp=1265190421993, value=100 T03 column=Detail:Locate, timestamp=1265184361124, value=03 T03 column=Detail:Name, timestamp=1265184361098, value=SunDon T03 column=Products:P1, timestamp=1265184361189, value=40 T03 column=Products:P2, timestamp=1265184361259, value=30 T03 column=Turnover:P1, timestamp=1265187021529, value=3 T03 column=Turnover:sum, timestamp=1265190421993, value=120 T04 column=Detail:Locate, timestamp=1265184361311, value=04 T04 column=Detail:Name, timestamp=1265184361287, value=StarBucks T04 column=Products:P1, timestamp=1265184361343, value=50 T04 column=Products:P2, timestamp=1265184361386, value=50 T04 column=Products:P3, timestamp=1265184361422, value=20 T04 column=Turnover:P1, timestamp=1265187021529, value=2 T04 column=Turnover:P2, timestamp=1265187021529, value=1 T04 column=Turnover:P3, timestamp=1265187021529, value=1 T04 column=Turnover:sum, timestamp=1265190421993, value=170 4 row(s) in 0.0460 seconds

9898

3.3.3. 執行結果Detail Products Turnover

Name LocateP1 P2 P3 P4 P1 P2 P3 P4 Sum

T01 GunLong 01 20 40 30 50 1 1 1 1 140

T02 ESing 02 50 2 100

T03 SunDon 03 40 30 3 3 210

T04 StarBucks04 50 50 20 4 4 4 480

9999

3.3.4. 狀況來了 管理局想知道餐廳的營運狀況,因此需要產生出最後的報表

資料由小到大排序 過濾掉營業額 < 130 的資料

100100

3.3.4. 回顧 Transactional HBase

Indexed Table = Secondary Index = Transactional HBase

內容與原本 table 相似的另一張 table ,但 key 不同,利於排列內容 name price description

1 apple 10 xx

2 orig 5 ooo3 banana 15 vvvv4 tomato 8 uu

name price description

2 orig 5 ooo

4 tomato 8 uu1 apple 10 xx

3 banana 15 vvvv

Indexed TablePrimary Table

101101

3.3.4. 回顧: Transactional HBase環境設定 <property> <name> hbase.regionserver.class </name> <value> org.apache.hadoop.hbase.ipc.IndexedRegionInterface

</value> </property> <property> <name> hbase.regionserver.impl </name> <value>org.apache.hadoop.hbase.regionserver.tableindexed.IndexedRegionServer </value> </property>

需在 $HBASE_INSTALL_DIR/conf/hbase-site.xml 檔內增加兩項內容

102102

3.3.4.1 建立 Indexed Tablepublic class tcrc4SortTurnover {public void addIndexToTurnover(String OriTable, String IndexID,

String OriColumn) throws IOException {HBaseConfiguration conf = new HBaseConfiguration();conf.addResource(new Path("/opt/hbase/conf/hbase-site.xml"));IndexedTableAdmin admin = new IndexedTableAdmin(conf);admin.addIndex(Bytes.toBytes(OriTable), new IndexSpecification(IndexID,

Bytes.toBytes(OriColumn)));}public static void main(String[] args) throws IOException {tcrc4SortTurnover tt = new tcrc4SortTurnover();tt.addIndexToTurnover("tcrc", "Sum", "Turnover:Sum");tt.readSortedValGreater("130");}}

103103

3.3.4.1 Indexed Table 輸出結果> scan 'tcrc-Sum'ROW COLUMN+CELL 100T02 column=Turnover:Sum, timestamp=1265190782127, value=100 100T02 column=__INDEX__:ROW, timestamp=1265190782127, value=T02

120T03 column=Turnover:Sum, timestamp=1265190782128, value=120 120T03 column=__INDEX__:ROW, timestamp=1265190782128, value=T03

140T01 column=Turnover:Sum, timestamp=1265190782126, value=140 140T01 column=__INDEX__:ROW, timestamp=1265190782126, value=T01

170T04 column=Turnover:Sum, timestamp=1265190782129, value=170 170T04 column=__INDEX__:ROW, timestamp=1265190782129, value=T04

4 row(s) in 0.0140 seconds

104104

3.3.4.2 產生排序且篩選過的資料public void readSortedValGreater(String filter_val)

throws IOException {HBaseConfiguration conf = new

HBaseConfiguration();conf.addResource(new

Path("/opt/hbase/conf/hbase-site.xml"));// the id of the index to useString tablename = "tcrc";String indexId = "Sum";byte[] column_1 = Bytes.toBytes("Turnover:Sum");byte[] column_2 = Bytes.toBytes("Detail:Name");byte[] indexStartRow =

HConstants.EMPTY_START_ROW;byte[] indexStopRow = null;byte[][] indexColumns = null;SingleColumnValueFilter indexFilter = new

SingleColumnValueFilter(Bytes.toBytes("Turnover"),

Bytes.toBytes("Sum"),

CompareFilter.CompareOp.GREATER_OR_EQUAL, Bytes.toBytes(filter_val));

byte[][] baseColumns = new byte[][] { column_1, column_2 };

IndexedTable table = new IndexedTable(conf, Bytes.toBytes(tablename));

ResultScanner scanner = table.getIndexedScanner(indexId, indexStartRow,

indexStopRow, indexColumns, indexFilter, baseColumns);

for (Result rowResult : scanner) {String sum = Bytes.toString(rowResult.getValue(column_1));String name = Bytes.toString(rowResult.getValue(column_2));System.out.println(name + " 's turnover is " + sum + " $.");

}table.close();}

105105

3.3.4.2 列出最後結果 營業額大於 130 元者

GunLong 's turnover is 140 $.StarBucks 's turnover is 170 $.

106106

3.3.5. 狀況來了 高層嫌報表輸出

只能用 cmd 無法直接看 介面 ....

107107

3.3.5. 回顧:還記得 Thrift ?

由 Facebook 所開發 提供跨語言做資料交換的平台 支援的程式語言

PHP Perl C++ Python …..

你可以用任何 Thrift 有支援的語言來直接存取、操作 HBase

109

Conclusions

HBase 適用於巨量資料的儲存與鬆散框架應用 是 Hadoop 的開放原始碼子項目 叢集模式需 Zookeeper 介入 提供 shell 的交互操作介面 擁有豐富的 Java API 讓你能直接寫

code 存取 透過 Thrift ,你可以用你熟悉的程式語言對 HBase 作操控