在HBase架构中的数据层面:
- HMaster负责管理类的操作(例如表、命令空间的创建删除),
- HRegionServer负责表的读写(即CRUD)
对应地在客户端API中有两个类:
- Admin类对象职能类似于HMaster
- HTable的职能类似于HRegionServer------应该放置到HTablePool中,不用从connection中获取。提升效率
通常这两个类的对象在一个应用程序中只创建一次,并且它们是由Connection对象获取的,Connection对象需要通过配置文件加载。所以以上对象一般为静态的,并且获取创建的过程在静态块中执行。
Hbase的所有操作都是追加插入操作(故此hbase有历史版本的概念存在)。它可以往数据里面insert,也可以update一些数据,但update的实际上也是insert,只是插入一个新的时间戳的一行。Delete数据,也是insert,只是insert一行带有delete标记的一行。
spring-boot-starter-hbase使用springboot的封装工具来使用Hbase,觉得没啥说的。
org.apache.hbase:hbase-client使用原生的客户端连接Hbase。
HBaseConfiguration包名 : org.apache.hadoop.hbase.HBaseConfiguration 作用:对HBase进行配置。 使用方法演示样例:
HBaseConfiguration hconfig = new HBaseConfiguration();
hconfig.set("hbase.zookeeper.property.clientPort","2181");
HBaseAdmin
HBaseAdmin类是Admin的子类,通常通过Admin实例即可完成对Hbase管理类的操作
包名 : org.apache.hadoop.hbase.client.HBaseAdmin 作用:提供了一个接口来管理HBase数据库的表信息。
它提供的方法包括:创建表,删除表,列出表项。使表有效或无效,以及加入或删除表列族成员等。 使用方法演示样例:
HBaseAdmin admin = new HBaseAdmin(config);
admin.disableTable("tablename")
//获得所有命名空间
NamespaceDescriptor[] listNamespaceDescriptors()
//指定命名空间名获取ns
NamespaceDescriptor getNamespaceDescriptor(final String name)
//删除命名空间
deleteNamespace(final String name)
//列出指定命名空间下的所有表
TableName[] listTableNamesByNamespace(final String name)
//列出所有表
HTableDescriptor[] listTables() throws IOException
创建表的同时可是初始化Region这样子在大批量插入的时候就不会触发大面积的Region的split,以提升插入效率.同时也可以避免后期的分裂时间cuiyaonan2000@163.com
//只根据表描述符来创建表
void createTable(HTableDescriptor desc)
//numRegions是要初始化的Region数量 ,startKey 是开始的key,endkey是结束的key 然后hbase自动拆分
void createTable(HTableDescriptor desc, byte[] startKey,byte[] endKey, int numRegions)
//这个是手动录入每一个region的分区.
//比如{Bytes.toBytes("A") ,Bytes.toBytes("G"),Bytes.toBytes("Z"")} 会生成4个region.即keynum+1个region
//且区段是
// 空 到 A
// A 到 G
// G 到 Z
// Z 到 空
void createTable(HTableDescriptor desc, byte[][] splitKeys)
//这个是后台异步执行,跟completefuturetask一样哦
void createTableAsync(HTableDescriptor desc, byte[][] splitKeys)
Region有关方法
合并region
//合并两个Region
void mergeRegions(final byte[] nameOfRegionA, final byte[] nameOfRegionB,
final boolean forcible) throws IOException
最后一个参数指定是否强制合并,默认为false,默认会合并两个相邻的Region,若设置为True可合并两个不相邻的Region
关于Region名可以在web端查看(在table详情页中),最后两个句号之间的数据即为Region名
移动region
void move(final byte[] encodedRegionName, final byte[] destServerName)
throws IOException
第二个参数指定了目的地服务器名(这个在登录页就可以看到),servername可通过web端查看
切分Region---自动的
void splitRegion(final byte[] regionName) throws IOException
//设置切分点行键
void split(final TableName tableName, final byte[] splitPoint)
throws IOException
同样还可以切表---自动的
void split(final TableName tableName) throws IOException
void split(final TableName tableName, final byte[] splitPoint)
throws IOException
负载均衡--即自动切分所有的region
//传入true开启负载均衡
boolean balancer(boolean force) throws IOException
//进行负载均衡
boolean balancer() throws IOException
表和Region的合并(compact)
这里的合并指的是minor compact和major compact,是底层HFile层面的合并
void compact(final TableName tableName) throws IOException
void compact(final TableName tableName, final byte[] columnFamily)
void compactRegion(final byte[] regionName) throws IOException
void compactRegion(final byte[] regionName, final byte[] columnFamily) throws IOException
void majorCompact(TableName tableName) throws IOException
void majorCompactRegion(final byte[] regionName) throws IOException
//...
HTableDescriptor
包名: org.apache.hadoop.hbase.HTableDescriptor 作用:包括了表的名字及其相应表的列族。 使用方法演示样例:
HTableDescriptor htd = new HTableDescriptor(table);
htd.addFamily(new HcolumnDescriptor("family"));
HColumnDescriptor
包名: org.apache.hadoop.hbase.HColumnDescriptor 作用:维护着关于列族的信息,比如版本。压缩设置等。
它通常在创建表或者为表加入列族的时候使用。列族被创建后不能直接改动。仅仅能通过删除,然后又一次创建的方式。
列族被删除的时候,列族里面的数据也会同一时候被删除。 使用方法演示样例:
HTableDescriptor htd = new HTableDescriptor(tablename);
HColumnDescriptor col = new HColumnDescriptor("content:");
htd.addFamily(col);
HTable
包名: org.apache.hadoop.hbase.client.HTable 作用:能够用来和HBase表直接通信。此方法对于更新操作来说是非线程安全的。 使用方法演示样例:
HTable table = new HTable(conf, Bytes.toBytes(tablename));
ResultScanner scanner = table.getScanner(family);
HTablePool------------用于替换HTable,提升资源效率,相当于表的连接池cuiyaonan2000
包名: org.apache.hadoop.hbase.client.HTablePool 作用:能够解决HTable存在的线程不安全问题。同一时候通过维护固定数量的HTable对象,能够在程序执行期间复用这些HTable资源对象。说明: 1. HTablePool能够自己主动创建HTable对象,并且对客户端来说使用上是全然透明的。能够避免多线程间数据并发改动问题。 2. HTablePool中的HTable对象之间是公用Configuration连接的,能够能够降低网络开销。
HTablePool的使用非常easy:每次进行操作前。通过HTablePool的getTable方法取得一个HTable对象,然后进行put/get/scan/delete等操作,最后通过HTablePool的putTable方法将HTable对象放回到HTablePool中。
/**
* A simple pool of HTable instances.
*
* Each HTablePool acts as a pool for all tables. To use, instantiate an
* HTablePool and use {@link #getTable(String)} to get an HTable from the pool.
*
* This method is not needed anymore, clients should call HTableInterface.close()
* rather than returning the tables to the pool
*
* Once you are done with it, close your instance of {@link HTableInterface}
* by calling {@link HTableInterface#close()} rather than returning the tables
* to the pool with (deprecated) {@link #putTable(HTableInterface)}.
*
*
* A pool can be created with a maxSize which defines the most HTable
* references that will ever be retained for each table. Otherwise the default
* is {@link Integer#MAX_VALUE}.
*
*
* Pool will manage its own connections to the cluster. See
* {@link HConnectionManager}.
* @deprecated as of 0.98.1. See {@link HConnection#getTable(String)}.
*/
@InterfaceAudience.Private
@Deprecated
public class HTablePool implements Closeable {
}
Put
包名: org.apache.hadoop.hbase.client.Put 作用:用来对单个行执行加入操作。 使用方法演示样例:
//Put类的构造函数
Put(byte[] row)
Put(byte[], long ts)
//put类提供的方法
//每次add都会添加特定的列,若再添加时间戳即形成了一个单元格
//若在addColumn时不指定时间戳,则会使用来自构造函数的时间戳;若构造时也没有声明,则时间戳将由HRegionServer来设定
Put addColumn(byte [] family, byte [] qualifier, byte [] value)
Put addColumn(byte [] family, byte [] qualifier, long ts, byte [] value)
Put add(Cell kv)
//用例
HTable table = (HTable) conn.getTable(TableName.valueOf(tableName));
Put put = new Put(Bytes.toBytes(rowKey));
put.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier), value);
table.put(put);
table.close();
table一次提交多个put
table提供的方法如下:
void put(List puts) throws IOException
当Put列表中有部分失败,例如部分Put指定了不存在的列族,由于客户端并不知道HBase中表的结构,所以对列族的检查会在服务器端完成。正常Put的数据会添加成功,并且客户端不会抛出异常,失败的Put实例会被保存在本地写缓冲区内,下一次刷写时会重试。客户端会检查Put实例内容是否为空或是否制定了列,在这种情况下客户端会抛出异常。
当提交了Put列表时,用户无法控制服务器端执行Put实例的顺序。若要尽量保证写入的顺序,可以减少每一批Put的数量并显式地刷写。
table的原子性的put方法调用table的checkAndPut会对指定单元格数据与参数value对比,若相同则视为检查通过,并执行指定Put。
使用场景为:当读取数据的同时还需要处理数据,想把一个处理好的数据写回到HBase并确保没有其他客户端做了相同的事------------相当于先去数据库中查询下该数据是否做了修改,如果没有做修改则执行put。cuiyaonan2000@163.com
boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier,
byte[] value, Put put) throws IOException
客户端的写缓冲区(批量puts 失败的时候,失败的会到这里来)
每一次put操作实际上就是一次rpc操作,这样的工作原理只适合小数据量的操作。减少rpc调用的关键是限制往返时间(LAN中1次rpc大约花1ms)和控制消息大小。所以API配备了一个客户端的写缓冲区,缓冲区负责收集put操作,然后调用rpc操作一次性将put发送至服务器。-------------目前2.0的版本及以上都去掉了如下的方法cuiyaonan2000@163.com
//默认情况下客户端缓冲区是禁用的,可以通过将自动刷写设置为false来激活缓冲区
table.setAutoFlush(false)
//当需要强制将数据刷写到服务器上时调用
table.flushCommits()
//通常强制刷写是不必要的,一旦超出了缓冲区指定的大小限制,客户端会隐式地调用刷写方法,可以通过以下命令设置缓冲区大小
table.setWriteBufferSize(2097152)
Get
包名: org.apache.hadoop.hbase.client.Get 作用:用来获取单个行的相关信息。
使用方法演示样例:
//get的构造方法
Get(byte[] row)
//get对象提供的方法
//指定列
Get addColumn(byte [] family, byte [] qualifier)
//指定列族
Get addFamily(byte [] family)
//指定时间戳及更旧的
Get setTimeStamp(long timestamp)
//Get请求默认返回版本数为1,不带参数的setMaxVersions设置最大版本号位int最大值
Get Get setMaxVersions()
Get setMaxVersions(int maxVersions) throws IOException
//用例
Get get = new Get(Bytes.toBytes(rowKey));
HTable table = (HTable) conn.getTable(TableName.valueOf(tableName));
//这里的allversion表示是否不需要包历史版本也查询出来,否则只查询最新版本
Result result = table.get(allVersion ? get.readAllVersions() : get);
return result.listCells();
table一次提交多个Get
table提供的方法如下:
Result[] get(List gets) throws IOException
注意此时get()方法要么返回一个与发送Get列表大小一致的Result数组,要么抛出异常
有错误的Get时:与put列表不同,当有一个Get错误时会导致整个get()操作终止。关于批量操作中的局部错误,可以使用batch()方法更精细地处理
table检查get中的数据是否存在exist()方法会引发regionserver服务器端的查询数据操作,通过这种方式而不是get()后检查可以避免网络数据传输的开
boolean exist(Get get) throws IOException
table获取get指定的前一条记录,或者查找最后一条记录
此方法中的行键要么与指定的一致,要么是指定行键之前的一行。
通常可以使用此方法在不知道行数的情况下获取表中最后一行的数据,调用getRowOrBefore()时传入像row-999999999这样的row参数,来获取表中最后一行row-n
Result getRowOrBefore(byte[] row, byte[] family) throws IOException
Delete
顾名思义:用于删除hbase中的记录
另外针对delete对象的方法cuiyaonan2000@163.com:
- 不指定时间戳,服务器会强制检索服务器端最近的时间戳,这比指定时间戳的删除要慢;
- 若尝试删除未设置时间戳的单元格,什么都不会发生
//delete的构造函数
Delete(byte [] row)
Delete(byte [] row, long timestamp)
//delete对象的方法
//不指定时间戳会删除整个列族;指定会删除改时间戳及更旧版本
Delete addFamily(final byte [] family)
Delete addFamily(final byte [] family, final long timestamp)
//不指定时间戳会删除指定列的所有版本;指定会删除该时间戳及比这个时间戳更旧的版本
Delete addColumns(final byte [] family, final byte [] qualifier)
Delete addColumns(final byte [] family, final byte [] qualifier, final long timestamp)
//不指定时间戳只删除指定列的最新版本,保留旧版本;指定会只指定列的指定版本
Delete addColumn(final byte [] family, final byte [] qualifier)
Delete addColumn(byte [] family, byte [] qualifier, long timestamp)
Delete setTimestamp(long timestamp
//示例
HTable table = (HTable) conn.getTable(TableName.valueOf(tableName));
Delete delete = new Delete(Bytes.toBytes(rowKey));
table.delete(delete);
table一次提交多个delete
用户不能设置删除操作在服务器端的执行顺序。API会重新排列它们,并将同一regionserver的操作集中到一个rpc中以提升性能
有错误的Delete时:与put类似,不能终止整个delete(),列信息正确的则被成功删除,错误删除的处理跟put的操作类似
void delete(List deletes) throws IOException
table的原子性的delete方法
当指定单元格的值与参数value相同时,才会执行指定的Delete,------即乐观锁的螺旋操作cuiyaonan2000@163.com
boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier,
byte[] value, Delete delete) throws IOException
Result
包名: org.apache.hadoop.hbase.client.Result 作用:存储Get或者Scan操作后获取表的单行值。
使用此类提供的方法能够直接获取值或者各种Map结构( key-value对)。
//Result提供的方法如下所示
//获取指定单元格的值
byte[] getValue(byte [] family, byte [] qualifier)
//获取第一列数据的最新版本
byte [] value()
//获取行键
byte [] getRow()
//获取单元格数量
int size()
//获取单元格列表
List listCells()
//示例
//获取一行数据中的所有单元格并打印基本信息
public static void get_row_cells(String tName, String rk){
Get get = new Get(Bytes.toBytes(rk));
try {
TableName tbn = TableName.valueOf(tName);
table = conn.getTable(tbn);
Result res = table.get(get);
List cl = res.listCells();
for(Cell c : cl){
//调用Cell工具类的cloneXXX方法获取信息,注意Cell.getXXX()已过时
String row = Bytes.toString(CellUtil.cloneRow(c));
String cf = Bytes.toString(CellUtil.cloneFamily(c));
String qua = Bytes.toString(CellUtil.cloneQualifier(c));
String val = Bytes.toString(CellUtil.cloneValue(c));
System.out.println("row:"+row+",cf:"+cf+",qua:"+qua+",val:"+val);
}
} catch (IOException e) {
e.printStackTrace();
}
}
table的batch批量操作
//参数说明
//Row类是Put、Get、Delete的父类。参数actions的列表中可以存放3种同类型的子类,将不同的操作融为一个rpc调用
//hmaster关于效率的解决也是有着自己处理方式
batch(final List
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?