HbaseAPI
本文总结一下HBase的API
本文章参考了http://blog.csdn.net/lifuxiangcaohui/article/details/39997205这篇文章写的比较早,一些功能都没有,但也可以看一看。
Configuration
对Hbase进行的配置
返回值 | 函数 | 描述 |
---|---|---|
void | addResource(Path file) | 通过给定的路径所指的文件来添加资源 |
void | clear() | 清空所有已设置的属性 |
string | get(String name) | 获取属性名对应的值 |
String | getBoolean(String name, boolean defaultValue) | 获取为boolean类型的属性值,如果其属性值类型部位boolean,则返回默认属性值 |
void | set(String name, String value) | 通过属性名来设置值 |
void | setBoolean(String name, boolean value) | 设置boolean类型的属性值 |
HBaseAdmin
提供了一个接口来管理HBase数据库的表信息。它提供的方法包括:创建表,删除表,列出表项,使表有效或无效,以及添加或删除表列族成员等。
返回值 | 函数 | 描述 |
---|---|---|
void | addColumn(String tableName, HColumnDescriptor column) | 向一个已经存在的表添加咧 |
checkHBaseAvailable(HBaseConfiguration conf) | 静态函数,查看HBase是否处于运行状态 | |
createTable(HTableDescriptor desc) | 创建一个表,同步操作 | |
deleteTable(byte[] tableName) | 删除一个已经存在的表 | |
enableTable(byte[] tableName) | 使表处于有效状态 | |
disableTable(byte[] tableName) | 使表处于无效状态 | |
HTableDescriptor[] | listTables() | 列出所有用户控件表项 |
void | modifyTable(byte[] tableName, HTableDescriptor htd) | 修改表的模式,是异步的操作,可能需要花费一定的时间 |
boolean | tableExists(String tableName) | 检查表是否存在 |
HTableDescriptor
包含了表的名字极其对应表的列族
返回值 | 函数 | 描述 |
---|---|---|
void | addFamily(HColumnDescriptor) | 添加一个列族 |
HColumnDescriptor | removeFamily(byte[] column) | 移除一个列族 |
byte[] | getName() | 获取表的名字 |
byte[] | getValue(byte[] key) | 获取属性的值 |
void | setValue(String key, String value) | 设置属性的值 |
HColumnDescriptor
维护着关于列族的信息,例如版本号,压缩设置等。它通常在创建表或者为表添加列族的时候使用。列族被创建后不能直接修改,只能通过删除然后重新创建的方式。列族被删除的时候,列族里面的数据也会同时被删除。
返回值 | 函数 | 描述 |
---|---|---|
byte[] | getName() | 获取列族的名字 |
byte[] | getValue(byte[] key) | 获取对应的属性的值 |
void | setValue(String key, String value) | 设置对应属性的值 |
HTable
可以用来和HBase表直接通信。此方法对于更新操作来说是非线程安全的。
返回值 | 函数 | 描述 |
---|---|---|
void | checkAdnPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put | 自动的检查row/family/qualifier是否与给定的值匹配 |
void | close() | 释放所有的资源或挂起内部缓冲区中的更新 |
Boolean | exists(Get get) | 检查Get实例所指定的值是否存在于HTable的列中 |
Result | get(Get get) | 获取指定行的某些单元格所对应的值 |
byte[][] | getEndKeys() | 获取当前一打开的表每个区域的结束键值 |
ResultScanner | getScanner(byte[] family) | 获取当前给定列族的scanner实例 |
HTableDescriptor | getTableDescriptor() | 获取当前表的HTableDescriptor实例 |
byte[] | getTableName() | 获取表名 |
static boolean | isTableEnabled(HBaseConfiguration conf, String tableName) | 检查表是否有效 |
void | put(Put put) | 向表中添加值 |
Put
用来对单个行执行添加操作
返回值 | 函数 | 描述 |
---|---|---|
Put | add(byte[] family, byte[] qualifier, byte[] value) | 将指定的列和对应的值添加到Put实例中 |
Put | add(byte[] family, byte[] qualifier, long ts, byte[] value) | 将指定的列和对应的值及时间戳添加到Put实例中 |
byte[] | getRow() | 获取Put实例的行 |
RowLock | getRowLock() | 获取Put实例的行锁 |
long | getTimeStamp() | 获取Put实例的时间戳 |
boolean | isEmpty() | 检查familyMap是否为空 |
Put | setTimeStamp(long timeStamp) | 设置Put实例的时间戳 |
Get
用来获取单个行的相关信息
返回值 | 函数 | 描述 |
---|---|---|
Get | addColumn(byte[] family, byte[] qualifier) | 获取指定列族和列修饰符对应的列 |
Get | addFamily(byte[] family) | 通过指定的列族获取其对应列的所有列 |
Get | setTimeRange(long minStamp,long maxStamp) | 获取指定取件的列的版本号 |
Get | setFilter(Filter filter) | 当执行Get操作时设置服务器端的过滤器 |
Result
存储Get或者Scan操作后获取表的单行值。使用此类提供的方法可以直接获取值或者各种Map结构(key-value对)
返回值 | 函数 | 描述 |
---|---|---|
boolean | containsColumn(byte[] family, byte[] qualifier) | 检查指定的列是否存在 |
NavigableMap |
ResultScanner
客户端获取值的接口
返回值 | 函数 | 描述 |
---|---|---|
void | close() | 关闭scanner并释放分配给它的资源 |
Result | next() | 获取下一行的值 |
下面是我自己写的示例
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
//定义HBase配置,设定ZooKeeper地址,端口号,HBase信息存储地址
configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum",hbase_zk_conn); configuration.set("hbase.zookeeper.property.clientPort",zk_port); configuration.set("zookeeper.znode.parent","/hbase");
//建立连接
connection = ConnectionFactory.createConnection(configuration);
//得到admin
admin = connection.getAdmin();
//创建命名空间,命名空间可以用来区分用户,在大数据平台设计中我在它的基础上实现了用户隔离
String namespace="test_un"; admin.createNamespace(NamespaceDescriptor.create(namespace).build());
//创建表
String tablefullname=namespace+":"+"t_N";
TableName tName = TableName.valueOf(tablefullname);
//如果表不存在
if!(admin.tableExists(tName)){
HTableDescriptor hTableDescriptor = new HTableDescriptor(tName);
//添加列族
for(String cf:colfamily){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cf);
hTableDescriptor.addFamily(hColumnDescriptor);
}
}
admin.createTable(hTableDescriptor);
//列出命名空间下的表名
tableName = admin.listTableNamesByNamespace(namespace);
tableList = new ArrayList<String>();
for(TableName t :tableName){
String tab=t.getNameAsString();
if(tab.contains(":"))
tab=tab.split(":")[1];
tableList.add(tab);
}
//删除表
TableName tn = TableName.valueOf(tablefullname);
if (admin.tableExists(tn)) {
//先disable再delete
admin.disableTable(tn);
admin.deleteTable(tn);
}
//表的列族
TableName t=TableName.valueOf(tablefullname);
HColumnDescriptor [] colfamilies= admin.getTableDescriptor(t).getColumnFamilies();
for (HColumnDescriptor cf:colfamilies){
String f=cf.getNameAsString();
}
//插入数据
Table table;
String tablefullname=namespace+":"+tableName;
table = connection.getTable(TableName.valueOf(tablefullname));
Put put = new Put(Bytes.toBytes(rowkey));
put.addColumn(Bytes.toBytes(colfamily), Bytes.toBytes(col), Bytes.toBytes(value));
table.put(put);
table.close();
//扫描表
Table table;
table = connection.getTable(TableName.valueOf(tablefullname));
Scan scan = new Scan();
//起始rowkey
scan.setStartRow(Bytes.toBytes(start_row));
//结束rowkey
scan.setStopRow(Bytes.toBytes(end_row));
scan.setCaching(1000);//一次rpc请求1000条
Filter filter = new PageFilter(1000);//最多返回一千条
scan.setFilter(filter);
ResultScanner resultScanner = table.getScanner(scan);
for(Result r : resultScanner){
Cell[] cells = r.rawCells();
for(Cell cell:cells){
data=new hb_result_data();
rowkey=new String(CellUtil.cloneRow(cell));
timestamp=String.valueOf(cell.getTimestamp());
colfamily=new String(CellUtil.cloneFamily(cell));
col=new String(CellUtil.cloneQualifier(cell));
value=new String(CellUtil.cloneValue(cell));
}
}
resultScanner.close();
table.close();
//获取数据
table = connection.getTable(TableName.valueOf(tablefullname));
Get get = new Get(Bytes.toBytes(rowkey));
if(col!=null)
get.addColumn(Bytes.toBytes(colfamily),Bytes.toBytes(col));
else
get.addFamily(Bytes.toBytes(colfamily));
Result r = table.get(get);
Cell[] cells = r.rawCells();
for(Cell cell:cells){
rowkey=new String(CellUtil.cloneRow(cell));
timestamp=String.valueOf(cell.getTimestamp());
colfamily=new String(CellUtil.cloneFamily(cell));
col=new String(CellUtil.cloneQualifier(cell));
value=new String(CellUtil.cloneValue(cell));
}
table.close();
//删除数据
Table table;
table = connection.getTable(t);
Delete delete=new Delete(Bytes.toBytes(rowkey));
if(col!=null){
delete.addColumn(Bytes.toBytes(colfamily), Bytes.toBytes(col));
}
else{
delete.addFamily(Bytes.toBytes(colfamily));
}
table.delete(delete);
table.close();
一些复杂的查询可以用filter过滤器,比如上面代码的scan操作就是用了PageFilter实现了一个limit的功能。
每 一个put的操作实际上是RPC的操作,它将客户端的数据传送到服务器然后返回,这只适合小数据量的操作,如果有个应用程序需要每秒存储上千行数据到 HBase表中,这样处理就不太合适了。HBase的API配备了一个客户端的写缓冲区,缓冲区负责收集put操作,然后调用RPC操作一次性将put送 往服务器。默认情况下,客户端缓冲区是禁止的。可以通过自动刷写设置为FALSE来激活缓冲。
table.setAutoFlush(false);
这个方法是强制 将数据写到服务器。
void flushCommits () throws IOException
用户还可以根据下面的方法来配置客户端写缓冲区的大小。
void setWritaeBufferSize(long writeBufferSize) throws IOException;
默认大小是 2MB,这个也是适中的,一般用户插入的数据不大,不过如果你插入的数据大的话,可能要考虑增大这个值。从而允许客户端更高效地一定数量的数据组成一组通 过一次RPC请求来执行。
在 HBase中,所有的存储文件都被划分成了若干个小存储块,这些小存储块在get或scan操作时会加载到内存中,他们类似于RDBMS中的存储单元页。 这个参数的默认大小是64K。
通过以上方式设置:
void setBlocksize(int s);
(HBase中Hfile的默认大小就是64K跟 HDFS的块是64M没关系)
HBase顺序地读取一个数据块到内存缓存中,其读取相邻的数据时就可以再内存中读取而不需要从磁盘中再次读取,有效地减少 了磁盘I/O的次数。
void setBlockCacheEnabled(boolean blockCacheEnable);
这个参数默认为TRUE,这意味着每次读取的块都会缓存到内存中。但是,如果用户顺序读取某个特定的列族,最好将这个属性设置为 FALSE,从而禁止使用缓存快。上面这样描述的原因:如果我们访问特定的列族,但是我们还是启用了这个功能,这个时候我们的机制会把我们其它不需要的列 族的数据也加载到了内存中,增加了我们的负担,我们使用的条件是,我们获取相邻数据。