將各種類型的數(shù)據(jù)庫或者文件導入到HBase,常見有三種方法:
? (1)使用HBase的API中的Put方法
? (2)使用HBase 的bulk load工具
? (3)使用定制的MapReduce Job方式
(1)使用HBase的API中的Put是最直接的方法婉弹,但是它并非都是最高效的方式(2)Bulk load是通過一個MapReduce Job來實現(xiàn)的盼理,通過Job直接生成一個HBase的內(nèi)部HFile格式文件來形成一個特殊的HBase數(shù)據(jù)表轧飞,然后直接將數(shù)據(jù)文件加載到運行的集群中。使用bulk load功能最簡單的方式就是使用importtsv 工具吞鸭。importtsv 是從TSV文件直接加載內(nèi)容至HBase的一個內(nèi)置工具远寸。它通過運行一個MapReduce Job,將數(shù)據(jù)從TSV文件中直接寫入HBase的表或者寫入一個HBase的自有格式數(shù)據(jù)文件猛遍。(3)可以使用MapReduce向HBase導入數(shù)據(jù)馋记,但海量的數(shù)據(jù)集會使得MapReduce Job也變得很繁重。推薦使用sqoop懊烤,它的底層實現(xiàn)是mapreduce梯醒,數(shù)據(jù)并行導入的,這樣無須自己開發(fā)代碼腌紧,過濾條件通過query參數(shù)可以實現(xiàn)茸习。
通過單客戶端導入mySQL數(shù)據(jù)
從一個單獨的客戶端獲取數(shù)據(jù),然后通過HBase的API中Put方法將數(shù)據(jù)存入HBase中壁肋。這種方式適合處理數(shù)據(jù)不是太多的情況号胚。
實施:
<1>在HBase中創(chuàng)建表
<2>寫一個java程序,mySQL中的數(shù)據(jù)導入Hbase,并將其打包為JAR.
1.使用Java創(chuàng)建一個connectHBase() 方法來連接到指定的HBase表墩划。
2.使用Java創(chuàng)建一個 connectDB() 方法來 MySQL涕刚。
3.通過腳本執(zhí)行JAR文件
4.驗證導入的數(shù)據(jù)
? ? 在HBase中創(chuàng)建了目標表用于插入數(shù)據(jù)。目標表名稱為hly_temp乙帮,且只有單個列族(column family) n。我們將列族名稱設(shè)計為一個字母的原因极景,是因為列族名稱會存儲在HBase的每個鍵值對中察净。使用短名能夠讓數(shù)據(jù)的存儲和緩存更有效率。我們只需要保留一個版本的數(shù)據(jù)盼樟,所以為列族指定VERSION屬性氢卡。
? ? 首先創(chuàng)建一個配置(Configuration )對象,使用該對象創(chuàng)建一個HTable實例晨缴。
? ? 然后译秦,使用JDBC中MySQL中獲取數(shù)據(jù)之后,我們循環(huán)讀取結(jié)果集击碗,將MySQL中的一行映射為HBase表中的一行筑悴。
? ? 創(chuàng)建了Put對象,利用row key添加一行數(shù)據(jù)稍途。每小時的數(shù)據(jù)的添加需要調(diào)用Put.add()方法阁吝,傳入?yún)?shù)包括列族
? ? 最后,所有打開的資源都需要手動關(guān)閉械拍。我們在代碼中的final塊中結(jié)束了MySQL和HBase的連接突勇,這樣確保即時導入動作中拋出異常仍然會被調(diào)用到装盯。
? ? Hive是一個構(gòu)建在Hadoop基礎(chǔ)設(shè)施之上的數(shù)據(jù)倉庫。通過Hive可以使用HQL語言查詢存放在HDFS上的數(shù)據(jù)甲馋。HQL是一種類SQL語言埂奈,這種語言最終被轉(zhuǎn)化為Map/Reduce. 雖然Hive提供了SQL查詢功能,但是Hive不能夠進行交互查詢--因為它只能夠在Haoop上批量的執(zhí)行Hadoop定躏。
? ? HBase是一種Key/Value系統(tǒng)挥转,它運行在HDFS之上。和Hive不一樣共屈,Hbase的能夠在它的數(shù)據(jù)庫上實時運行绑谣,而不是運行MapReduce任務(wù)。
兩者的特點:
? ? Hive幫助熟悉SQL的人運行MapReduce任務(wù)拗引。因為它是JDBC兼容的借宵,同時,它也能夠和現(xiàn)存的SQL工具整合在一起矾削。運行Hive查詢會花費很長時間壤玫,因為它會默認遍歷表中所有的數(shù)據(jù)。但其可以設(shè)置分區(qū)查詢哼凯。
? ? HBase通過存儲key/value來工作欲间。它支持四種主要的操作:增加或者更新行,查看一個范圍內(nèi)的cell断部,獲取指定的行猎贴,刪除指定的行、列或者是列的版本蝴光。
問題:
? ? Hive目前不支持更新操作她渴,是在hadoop上的批量操作,需要花費很長時間蔑祟。HBase查詢是通過特定的語言來編寫的趁耗,這種語言需要重新學習。類SQL的功能可以通過Apache Phonenix實現(xiàn)疆虚。運行hbase苛败,zookeeper是必須的。
實時查詢的比較:
? ? Hive適合用來對一段時間內(nèi)的數(shù)據(jù)進行分析查詢径簿,例如罢屈,用來計算趨勢或者網(wǎng)站的日志。Hive不應(yīng)該用來進行實時的查詢牍帚。因為它需要很長時間才可以返回結(jié)果儡遮。
? ? Hbase非常適合用來進行大數(shù)據(jù)的實時查詢黔帕。Facebook用Hbase進行消息和實時的分析门驾。它也可以用來統(tǒng)計Facebook的連接數(shù)。
? ? 注意:IP部分改為本機IP地址或localhost。同時倦零,HBase只支持十六進制存儲中文锹漱。
Hive董饰、MySQL屈嗤、HBase
hive的操作命令和SQL基本一致
HBase的操作和SQL有些區(qū)別,使用hbase shell進入Hbase,
1.創(chuàng)建表? create 'student','Sname','Ssex','Sage','Sdept','course'绩衷,因為HBase的表中會有一個系統(tǒng)默認的屬性作為行鍵蹦魔,無需自行創(chuàng)建,默認為put命令操作中表名后第一個數(shù)據(jù)咳燕。創(chuàng)建完“student”表后勿决,可通過describe命令查看“student”表的基本信息。
2.一次只能為一個表的一行數(shù)據(jù)的一個列招盲,也就是一個單元格添加一個數(shù)據(jù)低缩,put ‘student’,’95001’,’Sname’,’LiYing’
3.delete 'student','95001','Ssex',只刪除了性別曹货,? deleteall 'student','95001'刪除了全部元素
4.get 'student','95001'? 查看學號為95001的一行數(shù)據(jù)咆繁。
5.查看表中所有數(shù)據(jù)scan 'student'
6.刪除表disable 'student'? ,? drop 'student'? 第一步先讓該表不可用顶籽,第二步刪除表
7.查詢歷史數(shù)據(jù)玩般, create 'teacher',{NAME=>'username',VERSIONS=>5} 創(chuàng)建保存版本號,插入和更新put會更新版本號礼饱。
Java對Hbase進行增刪改查:
(1)在工程中導入外部jar包:這里只需要導入hbase安裝目錄中的lib文件中的所有jar包坏为,以及hadoop的jar包。
(2)java代碼
```
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import java.io.IOException;
public class ExampleForHbase{
? ? public static Configuration configuration;
? ? public static Connection connection;
? ? public static Admin admin;
? ? //主函數(shù)中的語句請逐句執(zhí)行慨仿,只需刪除其前的//即可久脯,如:執(zhí)行insertRow時請將其他語句注釋
? ? public static void main(String[] args)throws IOException{
? ? ? ? //創(chuàng)建一個表,表名為Score镰吆,列族為sname,course
? ? ? ? createTable("Score",new String[]{"sname","course"});
? ? ? ? //在Score表中插入一條數(shù)據(jù),其行鍵為95001,sname為Mary(因為sname列族下沒有子列所以第四個參數(shù)為空)
? ? ? ? //等價命令:put 'Score','95001','sname','Mary'
? ? ? ? //insertRow("Score", "95001", "sname", "", "Mary");
? ? ? ? //在Score表中插入一條數(shù)據(jù)跑慕,其行鍵為95001,course:Math為88(course為列族万皿,Math為course下的子列)
? ? ? ? //等價命令:put 'Score','95001','score:Math','88'
? ? ? ? //insertRow("Score", "95001", "course", "Math", "88");
? ? ? ? //在Score表中插入一條數(shù)據(jù),其行鍵為95001,course:English為85(course為列族核行,English為course下的子列)
? ? ? ? //等價命令:put 'Score','95001','score:English','85'
? ? ? ? //insertRow("Score", "95001", "course", "English", "85");
? ? ? ? //1牢硅、刪除Score表中指定列數(shù)據(jù),其行鍵為95001,列族為course芝雪,列為Math
? ? ? ? //執(zhí)行這句代碼前請deleteRow方法的定義中减余,將刪除指定列數(shù)據(jù)的代碼取消注釋注釋,將刪除制定列族的代碼注釋
? ? ? ? //等價命令:delete 'Score','95001','score:Math'
? ? ? ? //deleteRow("Score", "95001", "course", "Math");
? ? ? ? //2惩系、刪除Score表中指定列族數(shù)據(jù)位岔,其行鍵為95001,列族為course(95001的Math和English的值都會被刪除)
? ? ? ? //執(zhí)行這句代碼前請deleteRow方法的定義中如筛,將刪除指定列數(shù)據(jù)的代碼注釋,將刪除制定列族的代碼取消注釋
? ? ? ? //等價命令:delete 'Score','95001','score'
? ? ? ? //deleteRow("Score", "95001", "course", "");
? ? ? ? //3抒抬、刪除Score表中指定行數(shù)據(jù)杨刨,其行鍵為95001
? ? ? ? //執(zhí)行這句代碼前請deleteRow方法的定義中,將刪除指定列數(shù)據(jù)的代碼注釋擦剑,以及將刪除制定列族的代碼注釋
? ? ? ? //等價命令:deleteall 'Score','95001'
? ? ? ? //deleteRow("Score", "95001", "", "");
? ? ? ? //查詢Score表中妖胀,行鍵為95001,列族為course惠勒,列為Math的值
? ? ? ? //getData("Score", "95001", "course", "Math");
? ? ? ? //查詢Score表中赚抡,行鍵為95001,列族為sname的值(因為sname列族下沒有子列所以第四個參數(shù)為空)
? ? ? ? //getData("Score", "95001", "sname", "");
? ? ? ? //刪除Score表
? ? ? ? //deleteTable("Score");
? ? }
? ? //建立連接
? ? public static void init(){
? ? ? ? configuration? = HBaseConfiguration.create();
? ? ? ? configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
? ? ? ? try{
? ? ? ? ? ? connection = ConnectionFactory.createConnection(configuration);
? ? ? ? ? ? admin = connection.getAdmin();
? ? ? ? }catch (IOException e){
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
? ? //關(guān)閉連接
? ? public static void close(){
? ? ? ? try{
? ? ? ? ? ? if(admin != null){
? ? ? ? ? ? ? ? admin.close();
? ? ? ? ? ? }
? ? ? ? ? ? if(null != connection){
? ? ? ? ? ? ? ? connection.close();
? ? ? ? ? ? }
? ? ? ? }catch (IOException e){
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
? ? /**
? ? * 建表纠屋。HBase的表中會有一個系統(tǒng)默認的屬性作為主鍵涂臣,主鍵無需自行創(chuàng)建,默認為put命令操作中表名后第一個數(shù)據(jù)巾遭,因此此處無需創(chuàng)建id列
? ? * @param myTableName 表名
? ? * @param colFamily 列族名
? ? * @throws IOException
? ? */
? ? public static void createTable(String myTableName,String[] colFamily) throws IOException {
? ? ? ? init();
? ? ? ? TableName tableName = TableName.valueOf(myTableName);
? ? ? ? if(admin.tableExists(tableName)){
? ? ? ? ? ? System.out.println("talbe is exists!");
? ? ? ? }else {
? ? ? ? ? ? HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
? ? ? ? ? ? for(String str:colFamily){
? ? ? ? ? ? ? ? HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
? ? ? ? ? ? ? ? hTableDescriptor.addFamily(hColumnDescriptor);
? ? ? ? ? ? }
? ? ? ? ? ? admin.createTable(hTableDescriptor);
? ? ? ? ? ? System.out.println("create table success");
? ? ? ? }
? ? ? ? close();
? ? }
? ? /**
? ? * 刪除指定表
? ? * @param tableName 表名
? ? * @throws IOException
? ? */
? ? public static void deleteTable(String tableName) throws IOException {
? ? ? ? init();
? ? ? ? TableName tn = TableName.valueOf(tableName);
? ? ? ? if (admin.tableExists(tn)) {
? ? ? ? ? ? admin.disableTable(tn);
? ? ? ? ? ? admin.deleteTable(tn);
? ? ? ? }
? ? ? ? close();
? ? }
? ? /**
? ? * 查看已有表
? ? * @throws IOException
? ? */
? ? public static void listTables() throws IOException {
? ? ? ? init();
? ? ? ? HTableDescriptor hTableDescriptors[] = admin.listTables();
? ? ? ? for(HTableDescriptor hTableDescriptor :hTableDescriptors){
? ? ? ? ? ? System.out.println(hTableDescriptor.getNameAsString());
? ? ? ? }
? ? ? ? close();
? ? }
? ? /**
? ? * 向某一行的某一列插入數(shù)據(jù)
? ? * @param tableName 表名
? ? * @param rowKey 行鍵
? ? * @param colFamily 列族名
? ? * @param col 列名(如果其列族下沒有子列肉康,此參數(shù)可為空)
? ? * @param val 值
? ? * @throws IOException
? ? */
? ? public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException {
? ? ? ? init();
? ? ? ? Table table = connection.getTable(TableName.valueOf(tableName));
? ? ? ? Put put = new Put(rowKey.getBytes());
? ? ? ? put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes());
? ? ? ? table.put(put);
? ? ? ? table.close();
? ? ? ? close();
? ? }
? ? /**
? ? * 刪除數(shù)據(jù)
? ? * @param tableName 表名
? ? * @param rowKey 行鍵
? ? * @param colFamily 列族名
? ? * @param col 列名
? ? * @throws IOException
? ? */
? ? public static void deleteRow(String tableName,String rowKey,String colFamily,String col) throws IOException {
? ? ? ? init();
? ? ? ? Table table = connection.getTable(TableName.valueOf(tableName));
? ? ? ? Delete delete = new Delete(rowKey.getBytes());
? ? ? ? //刪除指定列族的所有數(shù)據(jù)
? ? ? ? //delete.addFamily(colFamily.getBytes());
? ? ? ? //刪除指定列的數(shù)據(jù)
? ? ? ? //delete.addColumn(colFamily.getBytes(), col.getBytes());
? ? ? ? table.delete(delete);
? ? ? ? table.close();
? ? ? ? close();
? ? }
? ? /**
? ? * 根據(jù)行鍵rowkey查找數(shù)據(jù)
? ? * @param tableName 表名
? ? * @param rowKey 行鍵
? ? * @param colFamily 列族名
? ? * @param col 列名
? ? * @throws IOException
? ? */
? ? public static void getData(String tableName,String rowKey,String colFamily,String col)throws? IOException{
? ? ? ? init();
? ? ? ? Table table = connection.getTable(TableName.valueOf(tableName));
? ? ? ? Get get = new Get(rowKey.getBytes());
? ? ? ? get.addColumn(colFamily.getBytes(),col.getBytes());
? ? ? ? Result result = table.get(get);
? ? ? ? showCell(result);
? ? ? ? table.close();
? ? ? ? close();
? ? }
? ? /**
? ? * 格式化輸出
? ? * @param result
? ? */
? ? public static void showCell(Result result){
? ? ? ? Cell[] cells = result.rawCells();
? ? ? ? for(Cell cell:cells){
? ? ? ? ? ? System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" ");
? ? ? ? ? ? System.out.println("Timetamp:"+cell.getTimestamp()+" ");
? ? ? ? ? ? System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" ");
? ? ? ? ? ? System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" ");
? ? ? ? ? ? System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" ");
? ? ? ? }
? ? }
}
```
使用Sqoop將數(shù)據(jù)從MySQL導入HBase
(1)在hbase中創(chuàng)建表
(2)運行shell
```
./bin/sqoop? import? --connect? jdbc:mysql://localhost:3306/dblab
--username? root
--password? hadoop
--table user_action
--hbase-table user_action #HBase中表名稱
--column-family f1 #列簇名稱
--hbase-row-key id #HBase 行鍵
--hbase-create-table #是否在不存在情況下創(chuàng)建表
```
-m 1 #啟動 Map 數(shù)量
查看:只查詢前10條
scan 'user_action',{LIMIT=>10}? #只查詢前面10行
一種MySQL到HBase的遷移策略的研究與實現(xiàn)
三類遷移方法的比較:
(1)現(xiàn)有的遷移工具如Hadoop的官方工具Sqoop只支持單表的增量加載,無法完成數(shù)據(jù)庫系統(tǒng)中眾多表模式的遷移;
(2)HBase的Importtsv 工具只支持TSV等指定文件的遷移;
(3)Put方法雖然簡單直接但也只是完成數(shù)據(jù)的遷移且遷移效率不佳灼舍。
? ? ? 關(guān)系形數(shù)據(jù)庫是一種建立在關(guān)系模型基礎(chǔ)上的數(shù)據(jù)庫吼和。用一張二維表代表現(xiàn)實世界中的實體,用表中的字段代表實體的屬性骑素,用外鍵等聯(lián)合操作代表實體之間的關(guān)系炫乓。關(guān)系型數(shù)據(jù)庫MySQL中默認安裝INFORMATION_SCHEMA數(shù)據(jù)庫,這些存儲在INFORMATION_SCHEMA中的數(shù)據(jù)就叫做數(shù)據(jù)庫系統(tǒng)的元數(shù)據(jù)献丑。因此末捣,在數(shù)據(jù)遷移的過程中,可以利用對關(guān)系型數(shù)據(jù)庫中元數(shù)據(jù)表的查詢快速獲取關(guān)系型數(shù)據(jù)庫中各個表的模式和各表之間的關(guān)系创橄,然后進行遷移箩做。
? ? ? HBase的表是一個稀疏矩陣。HBase與傳統(tǒng)關(guān)系型數(shù)據(jù)庫表所不同的是:它可以存儲半結(jié)構(gòu)化數(shù)據(jù)妥畏,即HBase中的表在設(shè)計上沒有嚴格的限制[8]邦邦,數(shù)據(jù)記錄可能包含不一致的列、不確定大小等醉蚁。此外燃辖,與關(guān)系型數(shù)據(jù)庫不同,HBase在存儲上基于列而非行网棍,因此對同列中的數(shù)據(jù)具有較好的查詢性能黔龟。
? ? ? HBase的數(shù)據(jù)存儲在HDFS中,能夠很好地利用HDFS的分布式處理模式,并從Hadoop的MapReduce程序模型中獲益氏身。 HBase邏輯上的表在行的方向上分割成多個HRegion,HRegion按大小分割巍棱,每張表開始只有一個Region,隨著記錄數(shù)的不斷增加,Region不斷增大观谦,當增大到一定程度時拉盾,HRegion會被等分成兩個新的HRegion。HRegion是HBase中分布式存儲和負載均衡的最小單元豁状,但卻不是存儲的最小單元捉偏。HRegion由一個或者多個Store組成,每個Store保存了表中的一個列族泻红。每個Store又由一個 Memstore和0至多個StoreFile(HFile)組成,StoreFile用來存儲數(shù)據(jù)并以HFile的形式保存在HDFS上夭禽。
提煉
為統(tǒng)一實現(xiàn)java的封裝,采用 bulk load工具來導入數(shù)據(jù)
(1)首先將數(shù)據(jù)庫的文件導出為CSV文件谊路,也可以在保存的時候保存為CSV文件讹躯,產(chǎn)生CSV文件
(2)準備工作:從數(shù)據(jù)源中提取數(shù)據(jù),開啟MapReduce守護進程缠劝,客戶端服務(wù)器上添加hac用戶用于運行job潮梯,在HDFS中為hac用戶建立主文件夾:
```
hadoop$ $HADOOP_HOME/bin/start-mapred.sh
root@client1# usermod -a -G hadoop hac
root@client1# chmod -R 775 /usr/local/hadoop/var
hadoop@client1$ $HADOOP_HOME/bin/hadoop fs -mkdir /user/hac
hadoop@client1$ $HADOOP_HOME/bin/hadoop fs -chown hac /user/hac
hadoop@client1$ $HADOOP_HOME/bin/hadoop fs -chmod -R 775 /usr/local/hadoop/var/mapred
```
(3)將在HDFS中建立文件夾,并且將TSV文件從本地文件系統(tǒng)拷貝至HDFS中
hac@client1$ $HADOOP_HOME/bin/hadoop fs -mkdir /user/hac/input/2-1
hac@client1$ $HADOOP_HOME/bin/hadoop fs -copyFromLocal hly-temp-10pctl.tsv /user/hac/input/2-1
(4)在HBase中添加目標表惨恭。連接到HBase秉馏,添加hly_temp表
hac@client1$ $HBASE_HOME/bin/hbase shell
hbase> create 'hly_temp', {NAME => 't', VERSIONS => 1}
? (5)將hbase-site.xml文件放置在Hadoop的配置目錄中就能夠加入Hadoop的環(huán)境變量了
hac@client1$ ln -s $HBASE_HOME/conf/hbase-site.xml $HADOOP_HOME/conf/hbase-site.xml
編輯客戶端服務(wù)器的$HADOOP_HOME/conf 下的hadoop-env.sh文件,添加HBase的依賴庫到Hadoop的環(huán)境變量中
hadoop@client1$ vi $HADOOP_HOME/conf/hadoop-env.sh
export HADOOP_CLASSPATH=/usr/local/zookeeper/current/zookeeper-3.4.3.jar:/usr/local/hbase/current/lib/guava-r09.jar
? (6)使用hac用戶運行importtsv工具脱羡,執(zhí)行如下腳本
hac@client1$ $HADOOP_HOME/bin/hadoop jar $HBASE_HOME/hbase-
0.92.1.jar importtsv \ -Dimporttsv.columns=HBASE_ROW_KEY,t:v01,t:v02,t:v03,t:v04,t:v05,t:v06,t:v07,t:v08,t:v09,t:v10,t:v11,t:v12,t:v13,t:v14,t:v15,t:v1
6,t:v17,t:v18,t:v19,t:v20,t:v21,t:v22,t:v23,t:v24 \
hly_temp \
/user/hac/input/2-1
? (7)檢查
HBase 寫優(yōu)化之 BulkLoad 實現(xiàn)數(shù)據(jù)快速入庫
bulk load 的入庫方式萝究,它是利用hbase的數(shù)據(jù)信息按照特定格式存儲在hdfs內(nèi)這一原理,直接在HDFS中生成持久化的HFile數(shù)據(jù)格式文件锉罐,然后上傳至合適位置帆竹,即完成巨量數(shù)據(jù)快速入庫的辦法。配合mapreduce完成脓规,高效便捷栽连,而且不占用region資源,增添負載侨舆,在大數(shù)據(jù)量寫入時能極大的提高寫入效率升酣,并降低對HBase節(jié)點的寫入壓力。
通過使用先生成HFile态罪,然后再BulkLoad到Hbase的方式來替代之前直接調(diào)用HTableOutputFormat的方法有如下的好處:
(1)消除了對HBase集群的插入壓力
(2)提高了Job的運行速度,降低了Job的執(zhí)行時間
目前此種方式僅僅適用于只有一個列族的情況下面,在新版 HBase 中复颈,單列族的限制會消除。
三步走:
(1)第一個Job還是運行原來業(yè)務(wù)處理邏輯,處理的結(jié)果不直接調(diào)用HTableOutputFormat寫入到HBase耗啦,而是先寫入到HDFS上的一個中間目錄下(如 middata)?
(2)第二個Job以第一個Job的輸出(middata)做為輸入凿菩,然后將其格式化HBase的底層存儲文件HFile?
(3)調(diào)用BulkLoad將第二個Job生成的HFile導入到對應(yīng)的HBase表中
代碼的實現(xiàn):
(1)繼承configured類和實現(xiàn)tool接口,
tool接口需要實現(xiàn)run方法帜讲,用于執(zhí)行帶有指定參數(shù)的命令衅谷。例如:hadoop jar myMR.jar MyTool -input inputDir -output outputDir
繼承configured,可直接使用setConf()和getConf()方法
(2)創(chuàng)建配值參數(shù)并連接似将,使用HBaseConfigured類來獲得Configured對象获黔。
通過toolrun運行配值,并取得連接后的狀態(tài)碼
(3)實現(xiàn)Maper類的編寫實現(xiàn)Maper類
將rowKey保存到外面在验,這樣會創(chuàng)建一個RowKey保證查詢不用玷氏,換文件夾,查詢快腋舌。
重寫maper方法盏触,首先獲得數(shù)據(jù),value.toString()通過表的格式進行分割块饺,
封裝put對象赞辩,傳入列對象,設(shè)置rowkey
? (4)在run方法中創(chuàng)建job,配值job類授艰,同時設(shè)置輸入\輸出,設(shè)置maper類
(5)設(shè)置自帶的reducer程序
(6)提交job
? (7)將HFile類導入到Hbase中