《HBase 不睡觉书》是一本让人看了不会睡着的 HBase 技术书籍,写的很是不错,为了加深记忆,决定把书中重要的部分整理成读书笔记,便于后期查阅,同时但愿为初学 HBase 的同窗带来一些帮助。数据库
建立 HBase 链接请注意如下几点:编程
hbase-site.xml
和 Hadoop 配置文件夹中的 core-site.xml
配置文件从服务器上拖下来放到项目 resources 文件夹内;try-with-resources
特性;不推荐将 Connection 实现为单例,这样当某个操做卡住时,其余后续操做也会处于阻塞状态,没法达到并发的效果。缓存
public static void main(String[] args) throws URISyntaxException, IOException {
//获取配置文件
Configuration config = HBaseConfiguration.create();
config.addResource(new Path(ClassLoader.getSystemResource("hbase-site.xml").toURI()));
config.addResource(new Path(ClassLoader.getSystemResource("core-site.xml").toURI()));
//建立链接
try (Connection connection = ConnectionFactory.createConnection(config); Admin admin = connection.getAdmin()) {
//定义表名
TableName tableName = TableName.valueOf("tb1");
//定义列族
ColumnFamilyDescriptor myCf = ColumnFamilyDescriptorBuilder.of("cf1");
//定义表
TableDescriptor table = TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(myCf).build();
//执行建立表动做
admin.createTable(table);
} catch (Exception ex) {
ex.printStackTrace();
}
}
复制代码
早期的教程会教你们使用 HTable 类,并且使用这个类的时候不须要去手动地获取 Connection,只须要把 Configuration 类做为构建参数传给 HTable 类,它会自动地去链接并完成操做。这个方法看起来操做很简单,实则隐含着不少性能和安全问题,因此这个类被废弃了。安全
官方建议你们先手动获取 Connection,而后再从 Connection 中获取 Table 接口(注意:不是 HTable 类,而是 Table 接口):bash
// 已废弃,不推荐使用
// HTable table = new HTable(config, "mytable");
// 官方推荐
try (Connection connection = ConnectionFactory.createConnection(config)) {
connection.getTable(TableName.valueOf("tb1"));
}
复制代码
在你读出数据以后和修改数据中间这段时间,若是有别人也修改了这个数据,就会发生数据不一致的问题,checkAndPut 方法就是为了解决这个问题而产生的。服务器
checkAndPut 方法只是把检查和写入这两个步骤合二为一了,checkAndPut 方法在写入前会先比较目前存在的数据是否与你传入的数据一致,若是一致则进行 put 操做,并返回 true;若是不一致,则返回 false,但不写入数据。网络
最新版本中 checkAndPut 已经弃用了,官方推荐使用 checkAndMutate。并发
checkAndPut 与 checkAndDelete 在最新的 API 中已经不推荐使用了,官方推荐使用 Table.checkAndMutate(byte[], byte[])
。checkAndMutate 会在执行 Put/Delete/RowMutations
操做前检查 row/family/qualifier
value 是否与预期的值匹配,若是不匹配则不执行操做。oop
table.checkAndMutate(row, family).qualifier(qualifier).ifNotExists().thenPut(put);
复制代码
保证原子性的状况下,把数据库中的某个列的数字加 N(N 能够是正数或者负数)。post
Table table = connection.getTable(TableName.valueOf("tb1"));
Increment inc = new Increment(Bytes.toBytes("row1"));
inc.addColumn(Bytes.toBytes("cf1"), Bytes.toBytes("age"), 1L);
table.increment(inc);
复制代码
当须要一次性操做(Put、Get、Delete)不少条数据的时候,为了操做方便而且提升性能,可使用 batch 方法;这里的操做列表 actions 里面的操做能够是 Put、Get、Delete 中的任意一种;第二个参数的 results 是操做的结果,results 中的结果顺序是跟传入的操做列表顺序一一对应的。
void batch(List<Row>actions, Object[] results)
复制代码
最好不要把针对同一个单元格的 Put 和 Delete 放到同一个 actions 列表里面,由于 HBase 不必定是顺序地执行这些操做的,你可能会获得意想不到的结果。
HBase 提供了专门针对批量 put 的操做方法:void put(List<Put> puts)
;其实内部也是用 batch 来实现的。须要注意的是,当一部分数据插入成功,可是另外一部分数据插入失败,好比某个 RegionServer 服务器出现了问题,这时会返回一个 IOException,操做会被放弃,不过插入成功的数据不会被回滚,仍是成功插入了。
对于插入失败的数据,服务器会尝试着再次去插入或者换一个 RegionServer,当尝试的次数大于定义的最大次数会抛出 RetriesExhaustedWithDetailsException 异常,该异常包含了不少错误信息,包括有多少操做失败了,失败的缘由以及服务器名和重试的次数。
若是定义了错误的列族,则只会尝试一次,由于若是连列族都错了,就不必再继续尝试下去了,HBase 会直接返回 NoSuchColumnFamilyException。
插入失败的数据会继续被放到本地的写缓冲区,并在下次插入的时候重试,你甚至能够操做它们,好比清除这些数据。
客户端写缓冲区就是一个在客户端 JVM 里面的缓存机制,能够把多个 Put 操做攒到一块儿经过单个 RPC 请求发送给客户端,目的是节省网络握手带来的 IO 消耗。这个缓冲区能够经过调用 HTable.setAutoFlush(false)
来开启。
最新版的 API 中 setAutoFlush 被废弃了,每一个表自带的 writeBuffer 也被废弃了,可是客户端写缓冲区仍是存在的,只是转而使用 BufferedMutator 对象。
BufferedMutator bm = connection.getBufferedMutator(TableName.valueOf("tb1"));
// 而后用BufferedMutator对象来提交Put操做
bm.mutate(put);
// 而后调用 flush 或者 close 方法均可以把请求批量地提交给服务端
bm.flush();
bm.close();
复制代码
大部分状况下咱们不须要直接调用到 BufferedMutator,也不推荐直接调用 BufferedMutator。
早期的 HBase 在扫描的时候默认是不开启缓存的,可是通过了广大使用者许屡次的实践后,如今的 HBase 在扫描的时候已经默认开启了缓存。
具体地说就是:每一次的 next() 操做都会产生一次完整的 RPC 请求,而此次 RPC 请求能够获取多少数据是经过 hbase-site.xml
中的 hbase.client.scanner.caching
参数配置的。好比你若是配置该项为 1,那么当你遍历了 10 个结果就会发送 10 次请求,显而易见这是比较消耗性能的,尤为是当单条的数据量较小的时候。
能够在表层面修改缓存条数,也能够在扫描层面去修改,在表的层面修改是经过把这段配置写到 hbase-site.xml
内去实现:
<property>
<name>hbase.client.scanner.caching</name>
<value>200</value>
</property>
复制代码
意思是每次 next 操做都获取 200 条数据,默认配置是100。
可使用 Scan.setCaching(int caching)
方法在扫描层面修改缓存,这个配置优先级比配置文件内的高,能够复写这个配置值。缓存当然好,可是带来的危害就是会占用大量内存,最糟糕的就是直接出现 OutOfMemoryException,因此也不要盲目的调大缓存。
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一块儿前行。