HBase 相关API操练
HBase 的 Shell 操作
HBase 为用户提供了一个非常方便的使用方式, 我们称之为“HBase Shell”。
HBase Shell 提供了大多数的 HBase 命令, 通过 HBase Shell 用户可以方便地创建、删除及修改表, 还可以向表中添加数据、列出表中的相关信息等。
备注:写错 HBase Shell 命令时用键盘上的“Delete”进行删除,“Backspace”不起作用。
在启动 HBase 之后,用户可以通过下面的命令进入 HBase Shell 之中,命令如下所示:
输入 help 可以看到命令分组。
Group Name Commands
部分命令清单。
下边分组举例 Shell 的各种操作。
general操作
查询 HBase 服务器状态 status:
查询hbase版本 version:
ddl操作
1、 创建一个表
create 'table1', 'tab1_id', 'tab1_add', 'tab1_info'
2、 列出所有的表
3、 获得表的描述
describe "table1"
4、 删除一个列族 disable alter enable
disable 'table1'
alter 'table1', {NAME=>'tab1_add', METHOD=>'delete'}
enable 'table1'
5、 查看表是否存在
exists 'table2'
6、 判断表是否为‘enable’
is_enabled 'table1'
7、 删除一个表
disable 'table1'
drop 'table1'
dml操作
1、 插入几条记录
put 'member', 'scutshuxue', 'info:age', '24'
put 'member', 'scutshuxue', 'info:birthday', '1996-07-17'
put 'member', 'scutshuxue', 'info:company', 'alibaba'
put 'member', 'scutshuxue', 'address:contry', 'china'
put 'member', 'scutshuxue', 'address:province', 'zhejiang'
put 'member', 'scutshuxue', 'address:city', 'hangzhou'
put命令比较简单,只有这一种用法:
hbase> put ‘t1′, ‘r1′, ‘c1′, ‘value', ts1
t1指表名,r1指行键名,c1指列名,value指单元格值。ts1指时间戳,一般都省略掉了。
2、 全表扫描 scan
scan 'member'
3、 获得数据 get
1) 获得一行的所有数据
get 'member', 'scutshuxue'
2) 获得某行,某列族的所有数据
get 'member', 'scutshuxue', 'info'
3) 获得某行,某列族,某列的所有数据
get 'member', 'scutshuxue', 'info:company'
4、 更新一条记录 put(把scutshuxue年龄改为99)
put 'member', 'scutshuxue', 'info:age', 99
5、 删除 delete、 deleteall
1) 删除行'scutshuxue', 列族为‘info' 中age的值
delete 'member', 'scutshuxue', 'info:age'
2) 删除整行
deleteall 'member', 'scutshuxue'
6、 查询表中有多少行
count 'member'
7、 给‘xiaoming’这个id增加'info:age'字段,并使用counter实现递增
incr 'member', 'xiaoming', 'info:age'
8、 将整个表清空
truncate 'member'
可以看出,HBase 是通过先对表执行 disable,然后再执行 drop 操作后重建表来实现 truncate 的功能的。
HBase 客户端
与 HBase 集群进行交互,有很多种不同的方式可以选择,如 Java API、REST、Thrift 等。下面我们以Java API为例介绍它们的用法。
Java API 交互
HBase 与 Hadoop 一样,都是用 java 编写的,所以 HBase 对 java 支持是必需的,下面看看怎么使用java 语言对 HBase 进行操作。Java API 核心类介绍如下。
1、 HBaseConfiguration 类
HBaseConfiguration 是每一个 HBase Client 都会使用到的对象,它代表 HBase 配置信息。有两种构造方式。
public HBaseConfiguration()
public HBaseConfiguration(final Configuration c)
默认构造方式会尝试从 hbase-default.xml 和 HBase-site.xml 文件中读取配置。如果CLASSPATH 没有这两个文件,就需要自己配置。
Configuration HBASE_CONFIG = new Configuration();
HBASE_CONFIG.set("hbase.ZooKeeper.quorum","zkServer"); //hbase 服务地址
HBASE_CONFIG.set("hbase.ZooKeeper.property.clientPort","2181"); //端口号
HBaseConfiguration cfg = new HBaseConfiguration(HBASE_CONFIG); //读取配置文件
2、 创建表
创建表通过 HBaseAdmin 对象操作。HBaseAdmin 负责META 表信息的处理。HBaseAdmin 提供了 createTable 方法。
public void createTable(HTableDescriptor desc)
HTableDescriptor 表示表的 Schema,提供常用方法有以下两个:
1)setMaxFileSize:指定最大 Region 的大小。
2)setMemStoreFlushSize:指定 MemStore Flush 到 HDFS 上的文件大小。
3、 增加 Family
使用 addFamily 方法实现 Family 的添加。
public void addFamily(final HColumnDescriptor family)
HColumnDescriptor 代表 Column 的 Schema,提供的常用方法有以下几个:
1、setTimeToLive:指定最大的 TTL(单位是 ms),过期数据会被自动删除。
2、setInMemory:指定是否放在内存中,对小表有用,可用于提高效率。默认关闭。
3、setBloomFilter:指定是否使用 BloomFilter,可提高随机查询效率。默认关闭。
4、setCompressionType:设定数据压缩类型。默认无压缩。
5、setMaxVersions:指定数据最大保存的版本个数。默认为3。
举个简单的例子,创建 4 个 Family 表,命令如下:
HBaseAdmin hAdmin = new HBaseAdmin(hbaseConfig);
HTableDescriptor table = new HTableDescriptor(tableName);
table.addFamily(new HColumnDescriptor("f1"));
table.addFamily(new HColumnDescriptor("f2"));
table.addFamily(new HColumnDescriptor("f3"));
table.addFamily(new HColumnDescriptor("f4"));
hAdmin.createTable(table);
4、 删除表
删除表也是通过 HBaseAdmin 来操作,删除表之前首先要 disable 表。这是一个非常耗时的操作,所以不建议频繁删除表。
disableTable 和 deleteTable 分别用来执行 disable 和 delete 操作。使用方法如下:
HBaseAdmin hAdmin = new HBaseAdmin(hbaseConfig);
if(hAdmin.tableExists(tableName)){
hAdmin.disableTable(tableName);
hAdmin.deleteTable(tableName);
}
5、查询数据
查询分为单条随机查询和批量查询。单条查询通过 Row Key 在Table 中查询某一行的数据,HTable 提供了get 方法完成单条查询。批量查询通过制定一段 Row Key 的范围来查询,HTable 提供了 getScanner 方法完成批量查询。
public Result get(final Get get)
public ResultScanner getScanner(final Scan scan)
Get 对象包含一个 Get 查询需要的信息,它的构造方法有两种。
public Get(byte [] row)
public Get(byte [] row,RowLock rowLock)
Row Lock 为了保证读写的原子性,可以传递一个已经存在 Row Lock,否则 HBase 会自动生成一个新的 Row Lock。
Scan 对象提供了默认构造函数,一般使用默认构造函数。
1) Get 和 Scan 的常用方法有以下几个:
addFamily/addColumn:指定需要的 Family 或者 Column,如果没有调用任何 Family 或者 Column,会返回所有的 Column。
setMaxVersions:指定最大的版本个数。如果不带任何参数调用 setMaxVersions,表示取所有的版本。如果不调用 setMaxVersions,只会取到最新的版本。
setTimeRange:指定最大的时间戳和最小的时间戳,只有在此范围内的 Cell 才能被获取。
setTimeStamp:指定时间戳。
setFilter:指定 Filter 过滤不需要的信息。
2) Scan 特有的方法如下:
setStartRow:指定开始的行。如果不调用,从表头开始。
setStopRow:指定结束的行(不含此行)。
setBatch:指定最多返回的 Cell 数目。防止一行中有过多的数据,导致 OOM 错误。
3) Result 代表是一行的数据。常用方法有以下几个:
getRow:返回 Row Key。
raw:返回所有的 KeyValue 数组。
getValue:按照 Column 来获取 Cell 的值。
ResultScanner 是 Result 的一个容器,每次调用ResultScanner 的next 方法会返回Result。
public Result next() throws IOException;
public Result [] next(int nbRows) throws IOException;
示例代码如下:
6、 插入数据
HTable 通过 put 方法插入数据,可以传递单个 put 对象 或 List put 对象分别实现单条插入和批量插入。
public void put(final Put put) throws IOException
public void put(final List< Put> puts) throws IOException
Put 提供3 种构造方式:
public Put(byte [] row)
public Put(byte [] row)
public Put(byte [] row,RowLock rowLock)
public Put(Put putToCopy)
Put 常用的方法有以下几个:
1)add:增加一个 Cell。
2)setTimeStamp:指定所有 Cell 默认的 timestamp,如果一个 Cell 没有指定 timestamp,就会用到这个值。如果没有调用,HBase 会将当前时间作为未指定 timestamp 的Cell 的 timestamp。
3)setWriteToWAL:WAL 是 Write Ahead Log 的缩写,指的是 HBase 在插入操作前是否写 Log。默认是打开,关掉会提高性能,但是如果系统出现故障(负责插入的Region Server 挂掉),数据可能会丢失。
另外 HTable 也有两个方法会影响插入的性能。
1)setAutoFlash:AutoFlush 指的是在每次调用 HBase 的 Put 操作,是否提交到 HBase Server。默认是 true,每次会提交。如果此时是单条插入,就会有更多的I/O,从而降低其性能。
2)setWriteBufferSize:Write Buffer Size 在 AutoFlush 为false 的时候起作用,默认是 2MB,也就是插入数据超过 2MB,就会自动提交到 Server。
示例代码如下:
7、 删除数据
HTable 通过 delete 方法删除数据。
public void delete(final Delete delete)
Delete 构造方法如下:
public Delete(byte [] row)
public Delete(byte [] row, long timestamp, RowLock rowLock)
public Delete(final Delete d)
Delete 常用方法有 deleteFamily/deleteColumn,用来指定要删除的 Family 或者 Column 的数据。 如果不调用任何这样的方法,将会删除整行。
注意: 如果某个 Cell 的 timestamp 高于当前时间,这个 Cell 将不会被删除,仍然可以查出来。
示例代码如下:
HTable table = new HTable(hbaseConfig,"mytest");
Delete d = new Delete("row1".getBytes());
table.delete(d)
8、 切分表
HBaseAdmin 提供 split 方法将 table 进行切分。
public void split(final String tableNameOrRegionName)
如果提供的是 tableName,会将 table 所有 Region 进行切分;如果提供的是 RegionName,只会切分这个Region。Split 是一个异步操作,因此它并不能确切控制 Region 的个数。
示例代码如下:
MapReduce 操作 HBase
在 HBase 系统上运行批处理运算,最方便和实用的模型依然是 MapReduce,如下图所示:
HBase Table 和 Region 的关系类似 HDFS File 和 Block 的关系,HBase提供配套的 TableInputFormat 和 TableOutputFormat API,可以方便地将 HBase Table 作为 Hadoop MapReduce 的Source 和 Sink。对于 MapReduce Job 应用开发人员来说,基本不需要关注 HBase 系统本身的细节。
org.apache.hadoop.hbase.mapreduce 包中的类和工具用来将 HBase 作为 MapReduce 作业的输出
1、 HBaseConfiguration 类
org.apache.hadoop.hbase.HbaseConfiguration 继承了 org.apache.hadoop.conf.Configuration 类, 创建一个 HBaseConfiguration 对象实例,会返回读入 CLASSPATH 下 hbase-site.xml 文件和hbase-default.xml 文件中 HBase 配置信息的一个 Configuration,该Configuration 接下来会用于 创建 HBaseAdmin 和 HTable 实例。
HBaseAdmin 和 HTable 两个类在 org.apache.hadoop.hbase.client 包中,HBaseAdmin 用于管理 HBase 集群、添加和删除表,HTable 用于访问指定的表,Configuration 实例指向了执行这些代码的集群上的这些类。
2、 HtableDescriptor 类和 HColumnDescriptor 类
HBase 中表结构由 HTableDescriptor 描述(包括 HColumnDescriptor),对表的新增、修改、删除操作在接口 HMasterInterface 中定义,而该接口由 HMaster 实现。
HTabledescriptor包含:
1)表名、byte[] 和 String 格式。
2)表的元信息,以Key-Value形式存储。存储信息包括文件最大的大小(默认256MB)、是否只读、Flush 时内存占用大小(默认64MB)、是否 root 或 Meta Region、DEFERRED_LOG_FLUSH。
3)表的各 Family 描述 HColumnDescriptor。
HColumnDescriptor 描述 Column Family 的信息,包括:
1)压缩格式(不压缩或仅压缩 Value、压缩 Block 中的一系列记录)。
2)数据的版本数量。
3)Block 的大小。
4)是否在内存中。
5)是否 Cache Block。
6)是否使用 bloomfilter。
7)Cell 内容的存活时间。
8)是否复制。
当一个 Column Family 创建后,其参数不能修改,除非删除该 Column Family 后新建一个, 但删除 Column Family 也会删除该 Column Family 下的数据。另外,HTableDescriptor 中包含 ROOT_TABLEDESC 和 META_TABLEDESC 两个实例以描述-ROOT- 和 .META 表。
1)ROOT_TABLEDESC 包含一个 info 的 Column Family。
2)META_TABLEDESC 包含一个 info 和 historian,两个 Column Family。
3、 CreateTable 方法
如果指定 Split Key 为该 Table 按指定键初始创建多个 Region,否则仅创建一个 Region,过程如下:
1) 为 Table 创建 HRegionInfo
2) 判断是不是所有的 Meta Region 都 online(由 RegionManager 的 MetaScanner 扫描线程分配 Meta Region)。
3) 判断 ServerManager 是否有足够 Region Server 来创建 table。
从 RegionManager 的 online MetaRegion 查找该 HRegionInfo 应放入哪一个 MetaRegion 中,在 onlineMetaRegion 中查找仅比RegionName 小的 MetaRegion,而RegionName 由 tableName、起始 Key 和 regionId(root 为0,meta 为1,user 当前时间)组成,同时 Master 的 ServerConnection 获取 HRegionInterface 代理连接到该 MetaRegion,并查找对应该 Table 为 Key 的记录是否存在,若存在则报错该表已经存在,由 RegionManager 根据 HRegionInfo 创建新的 user。Region 在 rootDir 目录下 新建以 tableName 为名的目录,在 tableName 目录下新建一个 Region 的目录(经编码后的 RegionName),并新建一个 HRegion 对象。
disable、enable 和 delete 等操作封装在继承自 TableOperation 的类中,该类先获得要操作表的所有 MetaRegion,扫描这些 MetaRegion 中 所有该表的 user Region 信息并做相应处理,最后处理 MetaRegion。
4、 TableInputFormat 类
通过设置 conf.set(TableInputFormat.INPUT_TABLE,"tableName") 设定 HBase 的输入表,tableName 为表名。
设置 conf.set(TableInputFormat.SCAN,TableMRUtil.convertScanToString(scan)),设定对 HBase 输入表的 scan 方式。
setTable(new HTable(new Configuration(conf),tableName));
通过 TableInputFormat.setConf(Configuration conf) 方法初始化 scan 对象;scan 对象是从 Job 中设置的对象,以字符串的形式传给 TableInputFormat,在 TableInputFormat 内部将 scan 字符串转换为 scan 对象,操作如下:
scan = TableMapReduceUtil.convertStringtoScan(conf.get(SCAN))
TableInputFormat 继承 TableInputFormatBase 实现了 InputFormat 抽象类的两个抽象方法 getSplits() 和 createRecordReader()。
getSplits() 判定输入对象的切分原则,原则是对于 TableInputFormatBase,会遍历HBase 相应表的所有 HRegion,每一个 HRegion 都会被切分成一个 Split,所以切分的块数与表中 HRegion 的数目是相同的,代码如下:
InputSplit split = new TableSplit(table.getTableName(),splitStart,splitStop,regionLocation);
在 Split 中只会记载 HRegion 的起始 Row Key 和 结束Row Key,具体去读取这片区域的数据是 createRecordReader() 实现的。
对于一个 Map 任务,JobTracker 会考虑 TaskTracker 的网络位置,并选取一个距离其输入分片文件的最近的 TaskTracker。在理想情况下,任务是数据本地化的(data-local), 也就是任务运行在输入分片所在的节点上。同样,任务也可能是机器本地化的;任务和输入分片在同一个机架,但不在同一个节点上。
对于Reduce 任务,JobTracker 简单地从待运行的 Reduce 任务列表中选取下一个来运行,用不着考虑数据段本地化。
createRecordReader() 按照必然格式读取响应数据,接受 Split 块,返回读取记录的结果,操作代码如下:
tableRecorderReader.init() 返回的是这个分块的起始 Row Key 的记录;RecordReader 将一个 Split 解析成 < Key, Value> 的形式 提供给 map 函数,Key 就是Row Key,Value 就是对应的一行数据。
RecorderReader 用于在划分中读取 < Key,Value> 对。RecorderReader 有5 个虚方法,下面分别进行介绍:
1、initialize:初始化,输入参数包括该 Reader 工作的数据划分 InputSplit 和 Job 的上下文 context。
2、nextKey:得到输入的下一个 Key,如果数据划分已经没有新的记录,返回空。
3、nextValue:得到 Key 对应的 Value,必须在调用 nextKey 后调用。
4、 getProgress:得到现在的进度。
5、close:来自 java.io 的Closeable 接口,用于清理 RecorderReader。
在 MapReduce 驱动中调用 TableInputFormat 的类:
job.setInputFormatClass(TableInputFormat.class);
使用以下方法就不需要再单独定义。
tableMapReduceUtil.initTableReducerJob("daily_result", DailyReduce.class, job);
initTableReducerJob() 方法完成一系列操作。
1) job.setOutputFormatClass(TableOutputFormat.class);设置输出格式。
2)conf.set(TableOutputFormat.OUTPUT_TABLE,table);设置输出表。
3) 初始化 partition。
向 HBase 中写入数据
本节介绍利用 MapReduce 操作 HBase,首先介绍如何上传数据,借助最熟悉的 WordCount 案例,将 WordCount 的结果存储到 HBase 而不是 HDFS。
输入文件 test.txt 的内容为:
hello hadoop
hadoop is easy
1) 编写 Mapper 函数。
2) 编写 Reducer 类。
3) 编写驱动类。
数据插入hbase数据库后,查询结果如下所示:
读取 HBase 中的数据
下面介绍如何读取 HBase 中的数据。读取数据比较简单,编写 Mapper 函数,读取 < Key,Value> 值,通过 Reducer 函数直接输出得到的结果就行了。
1) 编写 Mapper 函数。
2) 实现 Reducer 类。
3) 编写驱动类。
从hbase读取数据,输出到hdfs的数据如下所示:
easy 1
hadoop 2
hello 1
is 1
至此!
- 点赞
- 收藏
- 关注作者
评论(0)