大数据技术 数据库之HBase1.2.6
沉沙 2018-10-10 来源 : 阅读 2291 评论 0

摘要:本篇教程探讨了大数据技术 数据库之HBase1.2.6,希望阅读本篇文章以后大家有所收获,帮助大家对大数据技术的理解更加深入。

本篇教程探讨了大数据技术 数据库之HBase1.2.6,希望阅读本篇文章以后大家有所收获,帮助大家对大数据技术的理解更加深入。

<

一 HBaes 介绍
1.1 HBase 的起源
HBase 的原型是 Google 的 BigTable 论文,受到了该论文思想的启发,目前作为 Hadoop 的子项目来开发维护,用于支持结构化的数据存储。
Apache HBase™是Hadoop数据库,这是一个分布式,可扩展的大数据存储。
当您需要随机,实时读取/写入您的大数据时使用Apache HBase™。该项目的目标是托管非常大的表 - 数十亿行×数百万列 - 在商品硬件集群上。Apache HBase是一个开源的,分布式的,版本化的非关系数据库,其模型是由Chang等人在Google的Bigtable:一种用于结构化数据的分布式存储系统之后建模的。就像Bigtable利用Google文件系统提供的分布式数据存储一样,Apache HBase在Hadoop和HDFS之上提供了类似Bigtable的功能。
官方旧版本下载地址://archive.apache.org/dist/hbase/       官方网站://hbase.apache.org

-- 2006 年 Google 发表 BigTable 白皮书
-- 2006 年开始开发 HBase
-- 2008 年北京成功开奥运会,程序员默默地将 HBase 弄成了 Hadoop 的子项目
-- 2010 年 HBase 成为 Apache 顶级项目
-- 现在很多公司二次开发出了很多发行版本,你也开始使用了。
1.2 HBase 的角色
1.2.1 HMaster
功能:
1) 监控 RegionServer
2) 处理 RegionServer 故障转移
3) 处理元数据的变更
4) 处理 region 的分配或移除
5) 在空闲时间进行数据的负载均衡
6) 通过 Zookeeper 发布自己的位置给客户端
1.2.2 RegionServer
功能:
1) 负责存储 HBase 的实际数据
2) 处理分配给它的 Region
3) 刷新缓存到 HDFS
4) 维护 HLog
5) 执行压缩


6) 负责处理 Region 分片
组件:
1) Write-Ahead logs
HBase 的修改记录,当对 HBase 读写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,数据会先写在一个叫做 Write-Ahead logfile 的文件中, 然后再写入内存中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
2) HFile
这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。
3) Store
HFile 存储在 Store 中,一个 Store 对应 HBase 表中的一个列族。
4) MemStore
顾名思义,就是内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在 WAL
中之后,RegsionServer 会在内存中存储键值对。
5) Region
Hbase 表的分片,HBase 表会根据 RowKey 值被切分成不同的 region 存储在 RegionServer 中,在一个 RegionServer 中可以有多个不同的 region。
1.3 HBase 的架构
HBase 一种是作为存储的分布式文件系统,另一种是作为数据处理模型的 MR 框架。因为日常开发人员比较熟练的是结构化的数据进行处理,但是在 HDFS 直接存储的文件往往不具有结构化,所以催生出了 HBase 在 HDFS 上的操作。如果需要查询数据,只需要通过键值便可以成功访问。
架构图如下图所示:

 

HBase  内置有 Zookeeper ,但一般我们会有其他的 Zookeeper  集群来监管 master  和
regionserver,Zookeeper  通过选举,保证任何时候,集群中只有一个活跃的 HMaster,HMaster
与 HRegionServer  启动时会向 ZooKeeper 注册,存储所有 HRegion 的寻址入口,实时监控
HRegionserver 的上线和下线信息。并实时通知给 HMaster,存储 HBase 的 schema 和 table 元数据,默认情况下,HBase 管理 ZooKeeper 实例,Zookeeper 的引入使得 HMaster 不再是单点故障。一般情况下会启动两个 HMaster,非 Active 的 HMaster 会定期的和 Active HMaster通信以获取其最新状态,从而保证它是实时更新的,因而如果启动了多个 HMaster 反而增加了 Active HMaster 的负担。
一个 RegionServer 可以包含多个 HRegion,每个 RegionServer 维护一个 HLog,和多个 HFiles以及其对应的 MemStore。RegionServer 运行于 DataNode 上,数量可以与 DatNode 数量一致, 请参考如下架构图:

 

二 HBase 部署与使用
2.1 完全分布式部署



 
Master
BackupMaster
RegionServer
Zookeeper


node21

 




node22
 





node23
 
 





2.1.1 Zookeeper 正常部署
首先保证 Zookeeper 集群的正常部署,并启动之:

$ ~/module/zookeeper-3.4.12/bin/zkServer.sh start

2.1.2 Hadoop 正常部署
Hadoop 集群的正常部署并启动:

$ ~/module/hadoop-2.7.6/sbin/start-dfs.sh
$ ~/module/hadoop-2.7.6/sbin/start-yarn.sh

2.1.3 HBase 的解压
解压 HBase 到指定目录:

[admin@node21 hbase-1.2.6]$ tar zxvf hbase-1.2.6-bin.tar.gz -C /opt/module/

2.1.4 HBase 的配置文件
需要修改 HBase 对应的配置文件。
hbase-env.sh 修改内容:

export JAVA_HOME=/opt/module/jdk1.8
export HBASE_MANAGES_ZK=false



hbase-site.xml 修改内容:



hbase.rootdir
hdfs://mycluster/hbase


hbase.cluster.distributed
true



hbase.zookeeper.quorum
node21,node22,node23


hbase.zookeeper.property.dataDir
/opt/module/zookeeper-3.4.12/Data



regionservers:

node21node22node23

创建一个文件 backup-masters,添加备机名

node22

2.1.5 HBase 需要依赖的 Jar 包
由于 HBase 需要依赖 Hadoop,所以替换 HBase 的 lib 目录下的 jar 包,以解决兼容问题:


1) 删除原有的 jar:

  rm -rf /opt/module/hbase-1.2.6/lib/hadoop-*
$ rm -rf /opt/module/hbase-1.2.6/lib/zookeeper-3.4.6.jar

2) 拷贝新 jar,涉及的 jar 有:

hadoop-annotations-2.7.6.jar  hadoop-mapreduce-client-app-2.7.6.jar     hadoop-mapreduce-client-hs-plugins-2.7.6.jar 
hadoop-auth-2.7.6.jar         hadoop-mapreduce-client-common-2.7.6.jar  hadoop-mapreduce-client-jobclient-2.7.6.jar  
hadoop-common-2.7.6.jar       hadoop-mapreduce-client-core-2.7.6.jar    hadoop-mapreduce-client-shuffle-2.7.6.jar     
hadoop-hdfs-2.7.6.jar         hadoop-mapreduce-client-hs-2.7.6.jar      hadoop-yarn-api-2.7.6.jar
hadoop-yarn-client-2.7.6.jar  hadoop-yarn-common-2.7.6.jar              hadoop-yarn-server-common-2.7.6.jarzookeeper-3.4.12.jar



尖叫提示:这些 jar 包的对应版本应替换成你目前使用的 hadoop 版本,具体情况具体分析。

$ find /opt/module/hadoop-2.7.6/ -name hadoop-annotations*

然后将找到的 jar 包复制到 HBase 的 lib 目录下即可。
2.1.6 HBase 软连接 Hadoop 配置

[admin@node21 lib]$ ln -s /opt/module/hadoop-2.7.6/etc/hadoop/hdfs-site.xml /opt/module/hbase-1.2.6/conf/

2.1.7 HBase 远程 scp 到其他集群

$ scp -r /opt/module/hbase-1.2.6/ node22:/opt/module/
$ scp -r /opt/module/hbase-1.2.6/ node23:/opt/module/

2.1.8 HBase 服务的启动

$ bin/hbase-daemon.sh start master
$ bin/hbase-daemon.sh start regionserver

尖叫提示: 如果集群之间的节点时间不同步, 会导致 regionserver 无法启动,抛出
ClockOutOfSyncException 异常。修复提示:
a、同步时间服务
请参看帮助文档:《大数据帮助文档 1.0》


hbase.master.maxclockskew
180000
Time difference of regionserver from master




启动方式 2:

$ bin/start-hbase.sh

对应的停止服务:

$ bin/stop-hbase.sh

尖叫提 示: 如果使用的是 JDK8 以 上 版 本 , 则 应 在 hbase-evn.sh 中 移除 
“HBASE_MASTER_OPTS”和“HBASE_REGIONSERVER_OPTS”配置。
2.1.9 查看 Hbse 页面
node21:16010
2.2 简单使用
2.2.1 基本操作
1) 进入 HBase 客户端命令行

$ bin/hbase shell

2) 查看帮助命令

hbase(main)> help

3) 查看当前数据库中有哪些表

hbase(main)> list

2.2.2 表的操作


1) 创建表

hbase(main)> create ‘student‘,‘info‘

2) 插入数据到表

hbase(main) > put ‘student‘,‘1001‘,‘info:name‘,‘Thomas‘ hbase(main) > put ‘student‘,‘1001‘,‘info:sex‘,‘male‘hbase(main) > put ‘student‘,‘1001‘,‘info:age‘,‘18‘ hbase(main) > put ‘student‘,‘1002‘,‘info:name‘,‘Janna‘ hbase(main) > put ‘student‘,‘1002‘,‘info:sex‘,‘female‘
hbase(main) > put ‘student‘,‘1002‘,‘info:age‘,‘20‘

3) 扫描查看表数据

hbase(main) > scan ‘student‘
hbase(main) > scan ‘student‘,{STARTROW => ‘1001‘, STOPROW    => ‘1001‘}hbase(main) > scan ‘student‘,{STARTROW => ‘1001‘}

4) 查看表结构

hbase(main):012:0> describe ‘student’

5) 更新指定字段的数据

hbase(main) > put ‘student‘,‘1001‘,‘info:name‘,‘Nick‘
hbase(main) > put ‘student‘,‘1001‘,‘info:age‘,‘100‘

6) 查看“指定行”或“指定列族:列”的数据

hbase(main) > get ‘student‘,‘1001‘
hbase(main) > get ‘student‘,‘1001‘,‘info:name‘

7) 删除数据


删除某 rowkey 的全部数据:

hbase(main) > deleteall ‘student‘,‘1001‘

删除某 rowkey 的某一列数据:

hbase(main) > delete ‘student‘,‘1002‘,‘info:sex‘

8) 清空表数据

hbase(main) > truncate ‘student‘

尖叫提示:清空表的操作顺序为先 disable,然后再 truncating。
9) 删除表
首先需要先让该表为 disable 状态:

hbase(main) > disable ‘student‘

然后才能 drop 这个表:

hbase(main) > drop ‘student‘

尖叫提示:如果直接 drop 表,会报错:Drop the named table. Table must first be disabled
ERROR: Table student is enabled. Disable it first.
10) 统计表数据行数

hbase(main) > count ‘student‘

11) 变更表信息
将 info 列族中的数据存放 3 个版本:

hbase(main) > alter ‘student‘,{NAME=>‘info‘,VERSIONS=>3}

2.3 读写流程
2.3.1 HBase 读数据流程
1) HRegionServer 保存着 meta 表以及表数据,要访问表数据,首先 Client 先去访问
zookeeper,从 zookeeper 里面获取 meta 表所在的位置信息,即找到这个 meta 表在哪个
HRegionServer 上保存着。
2) 接着 Client 通过刚才获取到的 HRegionServer 的 IP 来访问 Meta 表所在的


HRegionServer,从而读取到 Meta,进而获取到 Meta 表中存放的元数据。
3) Client 通过元数据中存储的信息,访问对应的 HRegionServer,然后扫描所在
HRegionServer 的 Memstore 和 Storefile 来查询数据。
4) 最后 HRegionServer 把查询到的数据响应给 Client。
2.3.2 HBase 写数据流程
1) Client 也是先访问 zookeeper,找到 Meta 表,并获取 Meta 表信息。
2) 确定当前将要写入的数据所对应的 RegionServer 服务器和 Region。
3) Client 向该 RegionServer 服务器发起写入数据请求,然后 RegionServer 收到请求并响应。
4) Client 先把数据写入到 HLog,以防止数据丢失。
5) 然后将数据写入到 Memstore。
6) 如果 Hlog 和 Memstore 均写入成功,则这条数据写入成功。在此过程中,如果 Memstore
达到阈值,会把 Memstore 中的数据 flush 到 StoreFile 中。
7) 当 Storefile 越来越多,会触发 Compact 合并操作,把过多的 Storefile 合并成一个大的
Storefile。当 Storefile 越来越大,Region 也会越来越大,达到阈值后,会触发 Split 操作, 将 Region 一分为二。
尖叫提示:因为内存空间是有限的,所以说溢写过程必定伴随着大量的小文件产生。
2.4 JavaAPI
2.4.1 安装 Maven 并配置环境变量

$ tar -zxf ~/softwares/installations/apache-maven-3.5.0-bin.tar.gz -C ~/modules/

在环境变量中添加:

MAVEN_HOME=/home/admin/modules/apache-maven-3.5.0
export PATH=$PATH:$MAVEN_HOME/bin

2.4.2 新建 Maven Project
新建项目后在 pom.xml 中添加依赖:


org.apache.hbase
hbase-server
1.3.1


org.apache.hbase
hbase-client
1.3.1


jdk.tools
jdk.tools
1.6
system
${JAVA_HOME}/lib/tools.jar




2.4.3 编写 HBaseAPI
注意,这部分的学习内容,我们先学习使用老版本的 API,接着再写出新版本的 API 调用方式。因为在企业中,有些时候我们需要一些过时的 API 来提供更好的兼容性。
1) 首先需要获取 Configuration 对象:


public static Configuration conf; static{
//使用 HBaseConfiguration 的单例方法实例化
conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "192.168.216.20");
conf.set("hbase.zookeeper.property.clientPort", "2181");
}


2) 判断表是否存在:

public static boolean isTableExist(String tableName) throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
//在 HBase 中管理、访问表需要先创建 HBaseAdmin 对象
//Connection connection = ConnectionFactory.createConnection(conf);
//HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); HBaseAdmin admin = new HBaseAdmin(conf);
return admin.tableExists(tableName);
}

3) 创建表

public static void createTable(String tableName, String... columnFamily) throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
HBaseAdmin admin = new HBaseAdmin(conf);
//判断表是否存在if(isTableExist(tableName)){
System.out.println("表" + tableName + "已存在");
//System.exit(0);
}else{
//创建表属性对象,表名需要转字节
HTableDescriptor descriptor = new HTableDescriptor(TableName.valueOf(tableName));
//创建多个列族
for(String cf : columnFamily){ descriptor.addFamily(new HColumnDescriptor(cf));
}
//根据对表的配置,创建表
admin.createTable(descriptor);
System.out.println("表" + tableName + "创建成功!");
  }
}



4) 删除表

public static void dropTable(String tableName) throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
HBaseAdmin admin = new HBaseAdmin(conf); if(isTableExist(tableName)){
admin.disableTable(tableName); admin.deleteTable(tableName);
System.out.println("表" + tableName + "删除成功!");
}else{
System.out.println("表" + tableName + "不存在!");
}
}

5) 向表中插入数据

public static void addRowData(String tableName, String rowKey, String columnFamily, String column, String value) throws IOException{
//创建 HTable 对象
HTable hTable = new HTable(conf, tableName);
//向表中插入数据
Put put = new Put(Bytes.toBytes(rowKey));
//向 Put 对象中组装数据
put.add(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(value));
hTable.put(put); hTable.close();
System.out.println("插入数据成功");
}



6) 删除多行数据

public static void deleteMultiRow(String tableName, String... rows) throws IOException{ HTable hTable = new HTable(conf, tableName);
List deleteList = new ArrayList(); for(String row : rows){
Delete delete = new Delete(Bytes.toBytes(row)); deleteList.add(delete);
}
hTable.delete(deleteList); hTable.close();
}

7) 得到所有数据


public static void getAllRows(String tableName) throws IOException{ HTable hTable = new HTable(conf, tableName);
//得到用于扫描 region 的对象
Scan scan = new Scan();
//使用 HTable 得到 resultcanner 实现类的对象
ResultScanner resultScanner = hTable.getScanner(scan); for(Result result : resultScanner){
Cell[] cells = result.rawCells(); for(Cell cell : cells){
//得到 rowkey
System.out.println("行键:" + Bytes.toString(CellUtil.cloneRow(cell)));
//得到列族
System.out.println("列族" + Bytes.toString(CellUtil.cloneFamily(cell)));
System.out.println("列:" + Bytes.toString(CellUtil.cloneQualifier(cell)));
System.out.println("值:" + Bytes.toString(CellUtil.cloneValue(cell)));
    }
  }
}


8) 得到某一行所有数据

public static void getRow(String tableName, String rowKey) throws IOException{ HTable table = new HTable(conf, tableName);
Get get = new Get(Bytes.toBytes(rowKey));
//get.setMaxVersions();显示所有版本
//get.setTimeStamp();显示指定时间戳的版本Result result = table.get(get);
for(Cell cell : result.rawCells()){
System.out.println("行键:" + Bytes.toString(result.getRow()));
System.out.println("列族" + Bytes.toString(CellUtil.cloneFamily(cell)));
System.out.println("列:" + Bytes.toString(CellUtil.cloneQualifier(cell)));
System.out.println("值:" + Bytes.toString(CellUtil.cloneValue(cell)));
System.out.println("时间戳:" + cell.getTimestamp());
}
}

9) 获取某一行指定“列族:列”的数据

public static void getRowQualifier(String tableName, String rowKey, String family, String qualifier) throws IOException{
HTable table = new HTable(conf, tableName);
Get get = new Get(Bytes.toBytes(rowKey));
get.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier)); Result result = table.get(get);
for(Cell cell : result.rawCells()){
System.out.println("行键:" + Bytes.toString(result.getRow()));
System.out.println("列族" + Bytes.toString(CellUtil.cloneFamily(cell))); System.out.println("列:" + Bytes.toString(CellUtil.cloneQualifier(cell)));
System.out.println("值:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}



2.5 MapReduce
通过 HBase 的相关 JavaAPI,我们可以实现伴随 HBase 操作的 MapReduce 过程,比如使用
MapReduce 将数据从本地文件系统导入到 HBase 的表中,比如我们从 HBase 中读取一些原始数据后使用 MapReduce 做数据分析。
2.5.1 官方 HBase-MapReduce
1) 查看 HBase 的 MapReduce 任务的执行

$ bin/hbase mapredcp

2) 执行环境变量的导入

$ export HBASE_HOME=/opt/module/hbase-1.2.6
$ export HADOOP_HOME=/opt/module/hadoop-2.7.6
$ export HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase mapredcp`

3) 运行官方的 MapReduce 任务
-- 案例一:统计 Student 表中有多少行数据

$ ~/module/hadoop-2.7.6/bin/yarn jar lib/hbase-server-1.2.6.jar rowcounter student



-- 案例二:使用 MapReduce 将本地数据导入到 HBase
(1) 在本地创建一个 tsv 格式的文件:fruit.tsv




1001


Apple


Red




1002


Pear


Yellow




1003


Pineapple


Yellow




尖叫提示:上面的这个数据不要从 word 中直接复制,有格式错误
(2) 创建 HBase 表

hbase(main):001:0> create ‘fruit‘,‘info‘

(3) 在 HDFS 中创建 input_fruit 文件夹并上传 fruit.tsv 文件

$ ~/module/hadoop-2.7.6/bin/hdfs dfs -mkdir /input_fruit/
$ ~/module/hadoop-2.7.6/bin/hdfs dfs -put fruit.tsv /input_fruit/

(4) 执行 MapReduce 到 HBase 的 fruit 表中

$ ~/module/hadoop-2.7.6/bin/yarn jar lib/hbase-server-1.2.6.jar importtsv -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:color fruit \ hdfs://node21:8020/input_fruit

(5) 使用 scan 命令查看导入后的结果

hbase(main):001:0> scan ‘fruit’

2.5.2 自定义 HBase-MapReduce1
目标:将 fruit 表中的一部分数据,通过 MR 迁入到 fruit_mr 表中。分步实现:
1) 构建 ReadFruitMapper 类,用于读取 fruit 表中的数据

 

package com.z.hbase_mr;

import java.io.IOException;
import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;

public class ReadFruitMapper extends TableMapper {
@Override
protected void map(ImmutableBytesWritable key, Result value, Context context)
throws IOException, InterruptedException {
//将 fruit 的 name 和 color 提取出来,相当于将每一行数据读取出来放入到 Put 对象中。
Put put = new Put(key.get());
//遍历添加 column 行
for(Cell cell: value.rawCells()){
//添加/克隆列族:info
if("info".equals(Bytes.toString(CellUtil.cloneFamily(cell)))){
//添加/克隆列:name
if("name".equals(Bytes.toString(CellUtil.cloneQualifier(cell)))){
//将该列 cell 加入到 put 对象中
put.add(cell);
//添加/克隆列:color
}else if("color".equals(Bytes.toString(CellUtil.cloneQualifier(cell)))){
//向该列 cell 加入到 put 对象中
put.add(cell);
}
}
}
//将从 fruit 读取到的每行数据写入到 context 中作为 map 的输出
context.write(key, put);
}
}


2) 构建 WriteFruitMRReducer 类,用于将读取到的 fruit 表中的数据写入到 fruit_mr 表中

package com.z.hbase_mr;
import java.io.IOException;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.mapreduce.TableReducer; import org.apache.hadoop.io.NullWritable;
public class WriteFruitMRReducer extends TableReducer {
@Override
protected void reduce(ImmutableBytesWritable key, Iterable values, Context context) throws IOException, InterruptedException {
//读出来的每一行数据写入到 fruit_mr 表中
for(Put put: values){ context.write(NullWritable.get(), put);
}
}
}

3) 构建 Fruit2FruitMRRunner extends Configured implements Tool 用于组装运行 Job 任务

//组装 Job
public int run(String[] args) throws Exception {
//得到 Configuration
Configuration conf = this.getConf();
//创建 Job 任务
Job job = Job.getInstance(conf, this.getClass().getSimpleName());
job.setJarByClass(Fruit2FruitMRRunner.class);
//配置 Job
Scan scan = new Scan();
scan.setCacheBlocks(false); scan.setCaching(500);
//设置 Mapper,注意导入的是 mapreduce 包下的,不是 mapred 包下的,后者是老版本
TableMapReduceUtil.initTableMapperJob(
"fruit", //数据源的表名
scan, //scan 扫描控制器
ReadFruitMapper.class,//设置 Mapper 类
ImmutableBytesWritable.class,//设置 Mapper 输出 key 类型
Put.class,//设置 Mapper 输出 value 值类型
job//设置给哪个 JOB
);
//设置 Reducer
TableMapReduceUtil.initTableReducerJob("fruit_mr", WriteFruitMRReducer.class,job);
//设置 Reduce 数量,最少 1 个
job.setNumReduceTasks(1);
boolean isSuccess = job.waitForCompletion(true);
if(!isSuccess){
throw new IOException("Job running with error");
}
return isSuccess ? 0 : 1;
}



4) 主函数中调用运行该 Job 任务

public static void main( String[] args ) throws Exception{ Configuration conf = HBaseConfiguration.create();
int status = ToolRunner.run(conf, new Fruit2FruitMRRunner(), args);System.exit(status);

5) 打包运行任务

$ ~/module/hadoop-2.7.6/bin/yarn jar ~/softwares/jars/hbase-0.0.1-SNAPSHOT.jar
com.z.hbase.mr1.Fruit2FruitMRRunner

尖叫提示:运行任务前,如果待数据导入的表不存在,则需要提前创建之。
尖叫提示:maven 打包命令:-P local clean package 或-P dev clean package install(将第三方jar 包一同打包,需要插件:maven-shade-plugin)
2.5.3 自定义 HBase-MapReduce2
目标:实现将 HDFS 中的数据写入到 HBase 表中。分步实现:
1) 构建 ReadFruitFromHDFSMapper 于读取 HDFS 中的文件数据


package com.z.hbase.mr2;

import java.io.IOException;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class ReadFruitFromHDFSMapper extends Mapper {@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//从 HDFS 中读取的数据
String lineValue = value.toString();
//读取出来的每行数据使用\t 进行分割,存于 String 数组
String[] values = lineValue.split("\t");
//根据数据中值的含义取值String rowKey = values[0];String name = values[1];
String color = values[2];
//初始化 rowKey
ImmutableBytesWritable rowKeyWritable = new
ImmutableBytesWritable(Bytes.toBytes(rowKey));
//初始化 put 对象
Put put = new Put(Bytes.toBytes(rowKey));
//参数分别:列族、列、值
put.add(Bytes.toBytes("info"), Bytes.toBytes("name"),Bytes.toBytes(name)); put.add(Bytes.toBytes("info"), Bytes.toBytes("color"),Bytes.toBytes(color));
context.write(rowKeyWritable, put);
}
}

2)构建 WriteFruitMRFromTxtReducer 类

package com.z.hbase.mr2;
import java.io.IOException;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;import org.apache.hadoop.hbase.mapreduce.TableReducer;import org.apache.hadoop.io.NullWritable;
public class WriteFruitMRFromTxtReducer extends TableReducer {
@Override
protected void reduce(ImmutableBytesWritable key, Iterable values, Context context) throws IOException, InterruptedException {
//读出来的每一行数据写入到 fruit_hdfs 表中
for(Put put: values){ context.write(NullWritable.get(), put);
}
}
}

3)创建 Txt2FruitRunner 组装 Job

public int run(String[] args) throws Exception {
//得到 Configuration
Configuration conf = this.getConf();
//创建 Job 任务
Job job = Job.getInstance(conf, this.getClass().getSimpleName());
job.setJarByClass(Txt2FruitRunner.class);
Path inPath = new Path("hdfs://linux01:8020/input_fruit/fruit.tsv");
FileInputFormat.addInputPath(job, inPath);
// 设 置 Mapper job.setMapperClass(ReadFruitFromHDFSMapper.class);
job.setMapOutputKeyClass(ImmutableBytesWritable.class); job.setMapOutputValueClass(Put.class);
//设置 Reducer
TableMapReduceUtil.initTableReducerJob("fruit_mr", WriteFruitMRFromTxtReducer.class, job);
//设置 Reduce 数量,最少 1 个
job.setNumReduceTasks(1);
boolean isSuccess = job.waitForCompletion(true);
if(!isSuccess){
throw new IOException("Job running with error");
}
return isSuccess ? 0 : 1;

}


4) 调用执行 Job

public static void main(String[] args) throws Exception { Configuration conf = HBaseConfiguration.create();
int status = ToolRunner.run(conf, new Txt2FruitRunner(), args); System.exit(status);

5) 打包运行

$ ~/module/hadoop-2.7.6/bin/yarn jar ~/softwares/jars/hbase-0.0.1-SNAPSHOT.jar
com.z.hbase.mr2.Txt2FruitRunner

尖叫提示:运行任务前,如果待数据导入的表不存在,则需要提前创建之。
尖叫提示:maven 打包命令:-P local clean package 或-P dev clean package install(将第三方
jar 包一同打包,需要插件:maven-shade-plugin)
2.6 与 Hive 的集成
2.6.1 HBase 与 Hive 的对比
1) Hive
(1) 数据仓库
Hive 的本质其实就相当于将 HDFS 中已经存储的文件在 Mysql 中做了一个双射关系,以方便使用 HQL 去管理查询。
(2) 用于数据分析、清洗
Hive 适用于离线的数据分析和清洗,延迟较高。
(3) 基于 HDFS、MapReduce
Hive 存储的数据依旧在 DataNode 上,编写的 HQL 语句终将是转换为 MapReduce 代码执行。
2) HBase
(1) 数据库
是一种面向列存储的非关系型数据库。
(2) 用于存储结构化和非结构话的数据
适用于单表非关系型数据的存储,不适合做关联查询,类似 JOIN 等操作。


(3) 基于 HDFS
数据持久化存储的体现形式是 Hfile,存放于 DataNode 中,被 ResionServer 以 region 的形式进行管理。
(4) 延迟较低,接入在线业务使用
面对大量的企业数据,HBase 可以直线单表大量数据的存储,同时提供了高效的数据访问速度。
2.6.2 HBase 与 Hive 集成使用
尖叫提示:HBase 与 Hive 的集成在最新的两个版本中无法兼容。所以,我们只能含着泪勇敢的重新编译:hive-hbase-handler-1.2.2.jar!!
环境准备
因为我们后续可能会在操作 Hive 的同时对 HBase 也会产生影响,所以 Hive 需要持有操作HBase 的 Jar,那么接下来拷贝 Hive 所依赖的 Jar 包(或者使用软连接的形式)。


$ export HBASE_HOME=/home/admin/modules/hbase-1.2.6
$ export HIVE_HOME=/home/admin/modules/hive-2.3.3
$ ln -s $HBASE_HOME/lib/hbase-common-1.2.6.jar     $HIVE_HOME/lib/hbase-common-1.2.6.jar
$ ln -s $HBASE_HOME/lib/hbase-server-1.2.6.jar     $HIVE_HOME/lib/hbase-server-1.2.6.jar
$ ln -s $HBASE_HOME/lib/hbase-client-1.2.6.jar     $HIVE_HOME/lib/hbase-client-1.2.6.jar
$ ln -s $HBASE_HOME/lib/hbase-protocol-1.2.6.jar   $HIVE_HOME/lib/hbase-protocol-1.2.6.jar
$ ln -s $HBASE_HOME/lib/hbase-it-1.2.6.jar   $HIVE_HOME/lib/hbase-it-1.2.6.jar
$ ln -s $HBASE_HOME/lib/htrace-core-3.1.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.1.0-incubating.jar
$ ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-1.2.6.jar   $HIVE_HOME/lib/hbase-hadoop2-compat-1.2.6.jar
$ ln -s $HBASE_HOME/lib/hbase-hadoop-compat-1.2.6.jar    $HIVE_HOME/lib/hbase-hadoop-compat-1.2.6.jar


同时在 hive-site.xml 中修改 zookeeper 的属性,如下:


hive.zookeeper.quorum
node21,node22,node23
The list of ZooKeeper servers to talk to. This is only needed for read/write locks.


hive.zookeeper.client.port
2181
The port of ZooKeeper servers to talk to. This is only needed for read/write locks.


1) 案例一
目标:建立 Hive 表,关联 HBase 表,插入数据到 Hive 表的同时能够影响 HBase 表。分步实现:
(1) 在 Hive 中创建表同时关联 HBase


CREATE TABLE hive_hbase_emp_table( empno int,
ename string, job string,mgr int,
hiredate string, sal double, comm double,
deptno int)
STORED BY ‘org.apache.hadoop.hive.hbase.HBaseStorageHandler‘ WITH SERDEPROPERTIES ("hbase.columns.mapping" =
":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");


尖叫提示:完成之后,可以分别进入 Hive 和 HBase 查看,都生成了对应的表
(2) 在 Hive 中创建临时中间表,用于 load 文件中的数据
尖叫提示:不能将数据直接 load 进 Hive 所关联 HBase 的那张表中

CREATE TABLE emp(
empno int,ename string, job string,mgr int,
hiredate string, sal double, comm double, deptno int)
row format delimited fields terminated by ‘\t‘;

(3) 向 Hive 中间表中 load 数据

hive> load data local inpath ‘/home/admin/softwares/data/emp.txt‘ into table emp;

(4) 通过 insert 命令将中间表中的数据导入到 Hive 关联 HBase 的那张表中

hive> insert into table hive_hbase_emp_table select * from emp;

(5) 查看 Hive 以及关联的 HBase 表中是否已经成功的同步插入了数据
Hive:

hive> select * from hive_hbase_emp_table;

HBase:

hbase> scan ‘hbase_emp_table’

2) 案例二


目标:在 HBase 中已经存储了某一张表 hbase_emp_table,然后在 Hive 中创建一个外部表来
关联 HBase 中的 hbase_emp_table 这张表,使之可以借助 Hive 来分析 HBase 这张表中的数据。
注:该案例 2 紧跟案例 1 的脚步,所以完成此案例前,请先完成案例 1。分步实现:
(1) 在 Hive 中创建外部表

CREATE EXTERNAL TABLE relevance_hbase_emp(empno int,
ename string,job string,mgr int,
hiredate string,sal double,comm double,deptno int) STORED BY
‘org.apache.hadoop.hive.hbase.HBaseStorageHandler‘ WITH SERDEPROPERTIES ("hbase.columns.mapping" =
":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");

(2) 关联后就可以使用 Hive 函数进行一些分析操作了

hive (default)> select * from relevance_hbase_emp;

2.7 与 Sqoop 的集成
Sqoop supports additional import targets beyond HDFS and Hive. Sqoop can also import records into a table in HBase.
之前我们已经学习过如何使用 Sqoop 在 Hadoop 集群和关系型数据库中进行数据的导入导出
工作,接下来我们学习一下利用 Sqoop 在 HBase 和 RDBMS 中进行数据的转储。


相关参数:




参数


描述




--column-family 


Sets the target column family for the import
设置导入的目标列族。




--hbase-create-table


If specified, create missing HBase tables
是否自动创建不存在的 HBase 表(这就意味着,不需要手动提前在 HBase 中先建立表)




--hbase-row-key 


Specifies which input column to use as the row key.In case, if input table contains composite key, then  must be in the form of a
comma-separated list of composite key attributes.
mysql 中哪一列的值作为 HBase 的 rowkey,
如果rowkey 是个组合键,则以逗号分隔。(注:
避免 rowkey 的重复)




--hbase-table 


Specifies an HBase table to use as the target instead of HDFS.
指定数据将要导入到 HBase 中的哪张表中。




--hbase-bulkload


Enables bulk loading.
是否允许 bulk 形式的导入。




 
1) 案例
目标:将 RDBMS 中的数据抽取到 HBase 中分步实现:
(1) 配置 sqoop-env.sh,添加如下内容:

export HBASE_HOME=/opt/module/hbase-1.2.6

(2) 在 Mysql 中新建一个数据库 db_library,一张表 book


CREATE DATABASE db_library; CREATE TABLE db_library.book(
id int(4) PRIMARY KEY NOT NULL AUTO_INCREMENT,name VARCHAR(255) NOT NULL,
price VARCHAR(255) NOT NULL);


(3) 向表中插入一些数据

INSERT INTO db_library.book (name, price) VALUES(‘Lie Sporting‘, ‘30‘); INSERT INTO db_library.book (name, price) VALUES(‘Pride & Prejudice‘, ‘70‘);
INSERT INTO db_library.book (name, price) VALUES(‘Fall of Giants‘, ‘50‘);

(4) 执行 Sqoop 导入数据的操作

$ bin/sqoop import --connect jdbc:mysql://node21:3306/db_library \
--username root --password 123456 --table book --columns "id,name,price" --column-family "info" --hbase-create-table --hbase-row-key "id" --hbase-table "hbase_book" --num-mappers 1 --split-by id

尖叫提示:sqoop1.4.7 只支持 HBase1.0.1 之前的版本的自动创建 HBase 表的功能
解决方案:手动创建 HBase 表

hbase> create ‘hbase_book‘,‘info‘

(5) 在 HBase 中 scan 这张表得到如下内容



hbase> scan ‘hbase_book’

思考:尝试使用复合键作为导入数据时的 rowkey。
2.8 常用的 Shell 操作
1) satus
例如:显示服务器状态

hbase> status ‘node21’

2) whoami
显示 HBase 当前用户,例如:

hbase> whoami

3) list
显示当前所有的表

hbase> list

4) count
统计指定表的记录数,例如:

hbase> count ‘hbase_book‘

5) describe
展示表结构信息

hbase> describe ‘hbase_book‘

6) exist
检查表是否存在,适用于表量特别多的情况

hbase> exist ‘hbase_book‘

7) is_enabled/is_disabled
检查表是否启用或禁用

hbase> is_enabled ‘hbase_book‘
hbase> is_disabled ‘hbase_book‘

8) alter
该命令可以改变表和列族的模式,例如:


为当前表增加列族:

hbase> alter ‘hbase_book‘, NAME => ‘CF2‘, VERSIONS => 2

为当前表删除列族:

hbase> alter ‘hbase_book‘, ‘delete‘ => ’CF2’

9) disable
禁用一张表

hbase> disable ‘hbase_book‘

10) drop
删除一张表,记得在删除表之前必须先禁用

hbase> drop ‘hbase_book‘

11) delete
删除一行中一个单元格的值,例如:

hbase> delete ‘hbase_book’, ‘rowKey’, ‘CF:C’

12) truncate
清空表数据,即禁用表-删除表-创建表

hbase> truncate ‘hbase_book‘

13) create
创建表,例如:

hbase> create ‘table’, ‘cf’

创建多个列族:

hbase> create ‘t1‘, {NAME => ‘f1‘}, {NAME => ‘f2‘}, {NAME => ‘f3‘}

2.9 数据的备份与恢复
2.9.1 备份
停止 HBase 服务后,使用 distcp 命令运行 MapReduce 任务进行备份,将数据备份到另一个地方,可以是同一个集群,也可以是专用的备份集群。
即,把数据转移到当前集群的其他目录下(也可以不在同一个集群中):


$ bin/hadoop distcp \ hdfs://node21:8020/hbase \
hdfs://node21:8020/HbaseBackup/backup20180602


尖叫提示:执行该操作,一定要开启 Yarn 服务
2.9.2 恢复
非常简单,与备份方法一样,将数据整个移动回来即可。

$ bin/hadoop distcp hdfs://node21:8020/HbaseBackup/backup20180602 \ hdfs://node21:8020/hbase

2.10 节点的管理
2.10.1 、服役(commissioning)
当启动 regionserver 时,regionserver 会向 HMaster 注册并开始接收本地数据,开始的时候, 新加入的节点不会有任何数据,平衡器开启的情况下,将会有新的 region 移动到开启的
RegionServer 上。如果启动和停止进程是使用 ssh 和 HBase 脚本,那么会将新添加的节点的主机名加入到 conf/regionservers 文件中。
2.10.2 、退役(decommissioning)
顾名思义,就是从当前 HBase 集群中删除某个 RegionServer,这个过程分为如下几个过程:
1) 停止负载平衡器

hbase> balance_switch false

2) 在退役节点上停止 RegionServer

hbase> hbase-daemon.sh stop regionserver

3) RegionServer 一旦停止,会关闭维护的所有 region
4) Zookeeper 上的该 RegionServer 节点消失
5) Master 节点检测到该 RegionServer 下线
6) RegionServer 的 region 服务得到重新分配
该关闭方法比较传统,需要花费一定的时间,而且会造成部分 region 短暂的不可用。


另一种方案:
1) RegionServer 先卸载所管理的 region

$ bin/graceful_stop.sh 

2) 自动平衡数据
3) 和之前的 2~6 步是一样的
2.11 版本的确界
1) 版本的下界
默认的版本下界是 0,即禁用。row 版本使用的最小数目是与生存时间(TTL Time To Live) 相结合的,并且我们根据实际需求可以有 0 或更多的版本,使用 0,即只有 1 个版本的值写入 cell。
2) 版本的上界
之前默认的版本上界是 3,也就是一个 row 保留 3 个副本(基于时间戳的插入)。该值不要设计的过大,一般的业务不会超过 100。如果 cell 中存储的数据版本号超过了 3 个,再次插入数据时,最新的值会将最老的值覆盖。(现版本已默认为 1)
三 HBase 的优化
3.1 高可用
在 HBase 中 Hmaster 负责监控 RegionServer 的生命周期,均衡 RegionServer 的负载,如果
Hmaster 挂掉了,那么整个 HBase 集群将陷入不健康的状态,并且此时的工作状态并不会维持太久。所以 HBase 支持对 Hmaster 的高可用配置。
1) 关闭 HBase 集群(如果没有开启则跳过此步)

$ bin/stop-hbase.sh

2) 在 conf 目录下创建 backup-masters 文件

$ touch conf/backup-masters

3) 在 backup-masters 文件中配置高可用 HMaster 节点

$ echo node22 > conf/backup-masters

4) 将整个 conf 目录 scp 到其他节点



$ scp -r conf/ node22:/opt/module/hbase-1.2.6/
$ scp -r conf/ node23:/opt/module/hbase-1.2.6/

5) 打开页面测试查看

0.98 版本之前://node21:60010
0.98 版本之后://node21:16010

3.2 Hadoop 的通用性优化
1) NameNode 元数据备份使用 SSD
2) 定时备份 NameNode 上的元数据
每小时或者每天备份,如果数据极其重要,可以 5~10 分钟备份一次。备份可以通过定时任务复制元数据目录即可。
3) 为 NameNode 指定多个元数据目录
使用 dfs.name.dir 或者 dfs.namenode.name.dir 指定。这样可以提供元数据的冗余和健壮性, 以免发生故障。
4) NameNode 的 dir 自恢复
设置 dfs.namenode.name.dir.restore 为 true,允许尝试恢复之前失败的 dfs.namenode.name.dir
目录,在创建 checkpoint 时做此尝试,如果设置了多个磁盘,建议允许。
5) HDFS 保证 RPC 调用会有较多的线程数

属性:dfs.namenode.handler.count
解释:该属性是 NameNode 服务默认线程数,的默认值是 10,根据机器的可用内存可以调整为 50~100
属性:dfs.datanode.handler.count
解释:该属性默认值为 10,是 DataNode 的处理线程数,如果 HDFS 客户端程序读写请求比较多,可以调高到 15~20,设置的值越大,内存消耗越多,不要调整的过高,一般业务中,
5~10 即可。

hdfs-site.xml


6) HDFS 副本数的调整

属性:dfs.replication
解释:如果数据量巨大,且不是非常之重要,可以调整为 2~3,如果数据非常之重要,可以调整为 3~5。

hdfs-site.xml
7) HDFS 文件块大小的调整

属性:dfs.blocksize
解释:块大小定义,该属性应该根据存储的大量的单个文件大小来设置,如果大量的单个文件都小于 100M,建议设置成 64M 块大小,对于大于 100M 或者达到 GB 的这种情况,建议设置成 256M,一般设置范围波动在 64M~256M 之间。

hdfs-site.xml
8) MapReduce Job 任务服务线程数调整

属性:mapreduce.jobtracker.handler.count
解释:该属性是 Job 任务线程数,默认值是 10,根据机器的可用内存可以调整为 50~100

mapred-site.xml
9) Http 服务器工作线程数
mapred-site.xml

属性:mapreduce.tasktracker.http.threads
解释:定义 HTTP 服务器工作线程数,默认值为 40,对于大集群可以调整到 80~100

10) 文件排序合并优化
mapred-site.xml



属性:mapreduce.task.io.sort.factor
解释:文件排序时同时合并的数据流的数量,这也定义了同时打开文件的个数,默认值为
10,如果调高该参数,可以明显减少磁盘 IO,即减少文件读取的次数。

11) 设置任务并发
mapred-site.xml

属性:mapreduce.map.speculative
解释:该属性可以设置任务是否可以并发执行,如果任务多而小,该属性设置为 true 可以明显加快任务执行效率,但是对于延迟非常高的任务,建议改为 false,这就类似于迅雷下载。

12) MR 输出数据的压缩
mapred-site.xml

属性:mapreduce.map.output.compress、mapreduce.output.fileoutputformat.compress
解释:对于大集群而言,建议设置 Map-Reduce 的输出为压缩的数据,而对于小集群,则不需要。

13) 优化 Mapper 和 Reducer 的个数
mapred-site.xml



属性:mapreduce.tasktracker.map.tasks.maximum mapreduce.tasktracker.reduce.tasks.maximum
解释:以上两个属性分别为一个单独的 Job 任务可以同时运行的 Map 和 Reduce 的数量。
设置上面两个参数时,需要考虑 CPU 核数、磁盘和内存容量。假设一个 8 核的 CPU,业务内容非常消耗 CPU,那么可以设置 map 数量为 4,如果该业务不是特别消耗 CPU 类型的,那么可以设置 map 数量为 40,reduce 数量为 20。这些参数的值修改完成之后,一定要观察是否有较长等待的任务,如果有的话,可以减少数量以加快任务执行,如果设置一个很大的值,会引起大量的上下文切换,以及内存与磁盘之间的数据交换,这里没有标准的配置数值,
需要根据业务和硬件配置以及经验来做出选择。
在同一时刻,不要同时运行太多的 MapReduce,这样会消耗过多的内存,任务会执行的非常缓慢,我们需要根据 CPU 核数,内存容量设置一个 MR 任务并发的最大值,使固定数据量的任务完全加载到内存中,避免频繁的内存和磁盘数据交换,从而降低磁盘 IO,提高性能。

大概估算公式:
map = 2 + ?cpu_core reduce = 2 + ?cpu_core
3.3 Linux 优化
1) 开启文件系统的预读缓存可以提高读取速度

$ sudo blockdev --setra 32768 /dev/sda

尖叫提示:ra 是 readahead 的缩写
2) 关闭进程睡眠池
即不允许后台进程进入睡眠状态,如果进程空闲,则直接 kill 掉释放资源

$ sudo sysctl -w vm.swappiness=0

3) 调整 ulimit 上限,默认值为比较小的数字

$ ulimit -n 查看允许最大进程数
$ ulimit -u 查看允许打开最大文件数

优化修改:
 




末尾添加:


 




*


soft


nofile


1024000




*


hard


nofile


1024000




Hive


-


nofile


1024000




hive


-


nproc


1024000





 

4) 开启集群的时间同步 NTP
集群中某台机器同步网络时间服务器的时间,集群中其他机器则同步这台机器的时间。
5) 更新系统补丁
更新补丁前,请先测试新版本补丁对集群节点的兼容性。
3.4 Zookeeper 优化
1) 优化 Zookeeper 会话超时时间
hbase-site.xml

参数:zookeeper.session.timeout
解 释 :In hbase-site.xml, set zookeeper.session.timeout to 30 seconds or less to bound failure detection (20-30 seconds is a good start).该值会直接关系到 master 发现服务器宕机的最大周期,默认值为 30 秒,如果该值过小,会在 HBase 在写入大量数据发生而 GC 时,导致RegionServer 短暂的不可用,从而没有向 ZK 发送心跳包,最终导致认为从节点 shutdown。一般 20 台左右的集群需要配置 5 台 zookeeper。

3.5 HBase 优化
3.5.1 预分区
每一个region 维护着startRow 与endRowKey,如果加入的数据符合某个region 维护的rowKey范围,则该数据交给这个 region 维护。那么依照这个原则,我们可以将数据索要投放的分区提前大致的规划好,以提高 HBase 性能。
1) 手动设定预分区


hbase> create ‘staff‘,‘info‘,‘partition1‘,SPLITS => [‘1000‘,‘2000‘,‘3000‘,‘4000‘]


2) 生成 16 进制序列预分区

create ‘staff2‘,‘info‘,‘partition2‘,{NUMREGIONS => 15, SPLITALGO => ‘HexStringSplit‘}

3) 按照文件中设置的规则预分区
创建 splits.txt 文件内容如下:

aaaa bbbb cccc
dddd

然后执行:

create ‘staff3‘,‘partition3‘,SPLITS_FILE => ‘splits.txt‘

4) 使用 JavaAPI 创建预分区

//自定义算法,产生一系列 Hash 散列值存储在二维数组中
byte[][] splitKeys = 某个散列值函数
//创建 HBaseAdmin 实例
HBaseAdmin hAdmin = new HBaseAdmin(HBaseConfiguration.create());
//创建 HTableDescriptor 实例
HTableDescriptor tableDesc = new HTableDescriptor(tableName);
//通过 HTableDes    

本文由职坐标整理发布,学习更多的大数据技术相关知识,请关注职坐标大技术云计算大技术技术频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved