HBase CRUD 操作指南 (三)

Java API操作HBase通用CRUD教程 本文还有配套的精品资源,点击获取 简介:Java环境下,本指南介绍如何通过Java API执行HBase数据库的通用CRUD操作。文章首先介绍了设置HBase依赖的步骤,然后详细讲解了创建表、插入数据、读取数据、更新数据、删除数据以及扫描查询的操作方法,并提供了相应的Java代码示例。 1. HBase数据库介绍与应用领域 HBase是一个开源的非关系型分布... 阅读详情

继  HBase CRUD 操作指南 (二)

 

4 批处理操作 (Batch Operations)


之前介绍的 API 都是应用到单一行上的操作。本节介绍另外一些 API 调用,这些调用可以批量处理跨多行的不同操作。


    NOTE:
    ---------
    事实上,许多基于列表的操作,如 delete(List<Delete> deletes) 或 get(List<Get> gets), 都是基于 batch() 方法实现的。它们都是一些为了方便
    用户使用而存在的方法。如果是新手,推荐使用 batch() 方法进行操作。

下面的客户端 API  方法提供了批量处理操作。其中引入了一个新的类 Row, 它是 Get 和所有 Mutation 类型的基类, Put 和 Delete 类的父类。

    void batch(final List<? extends Row> actions, final Object[] results) throws IOException, InterruptedException
    void batchCallback(final List<? extends Row> actions, final Object[] results, final Batch.Callback<R> callback)
        throws IOException, InterruptedException

使用相同的父类允许在列表中实现多态,

示例:
    //Example application using batch operations
    //Create a list to hold all values
    List<Row> batch = new ArrayList<Row>();
    
    //Add a Put instance
    Put put = new Put(ROW2);
    put.addColumn(COLFAM2, QUAL1, 4, Bytes.toBytes("val5"));
    batch.add(put);
    
    //Add a Get instance for a different row.
    Get get1 = new Get(ROW1);
    get1.addColumn(COLFAM1, QUAL1);
    batch.add(get1);
    
    //Add a Delete instance.
    Delete delete = new Delete(ROW1);
    delete.addColumns(COLFAM1, QUAL2);
    batch.add(delete);
    
    //Add a Get instance that will fail
    Get get2 = new Get(ROW2);
    get2.addFamily(Bytes.toBytes("BOGUS"));
    batch.add(get2);
    
    //Create result array.
    Object[] results = new Object[batch.size()];
    
    try {
        table.batch(batch, results);
    } catch (Exception e) {
        //Print error that was caught
        System.err.println("Error: " + e);
    }
    for (int i = 0; i < results.length; i++) {
        //Print all results and class types
        System.out.println("Result[" + i + "]: type = " +
        results[i].getClass().getSimpleName() + "; " + results[i]);
    }

输出:
    Before batch call...
    Cell: row1/colfam1:qual1/1/Put/vlen=4/seqid=0, Value: val1
    Cell: row1/colfam1:qual2/2/Put/vlen=4/seqid=0, Value: val2
    Cell: row1/colfam1:qual3/3/Put/vlen=4/seqid=0, Value: val3
    Error: org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException:
    \
    Failed 1 action: \
    org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException:
    \
    Column family BOGUS does not exist in ...
    ...
    : 1 time,
    Result[0]: type = Result; keyvalues=NONE
    Result[1]: type = Result; keyvalues={row1/colfam1:qual1/1/Put/
    vlen=4/seqid=0}
    Result[2]: type = Result; keyvalues=NONE
    Result[3]: type = NoSuchColumnFamilyException; \
    org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException:
    \
    org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException:
    \
    Column family BOGUS does not exist in ...
    ...
    After batch call...
    Cell: row1/colfam1:qual1/1/Put/vlen=4/seqid=0, Value: val1
    Cell: row1/colfam1:qual3/3/Put/vlen=4/seqid=0, Value: val3
    Cell: row2/colfam2:qual1/4/Put/vlen=4/seqid=0, Value: val5

    batch() 调用返回可能的 result 值
    +---------------+-----------------------------------------------------------------------------------------------------------+
    | 结果            | 描述                                                                                                        |
    +---------------+-----------------------------------------------------------------------------------------------------------+
    | null            | The operation has failed to communicate with the remote server.                                            |
    +---------------+-----------------------------------------------------------------------------------------------------------+
    | Empty Result    | Returned for successful Put and Delete operations.                                                        |
    +---------------+-----------------------------------------------------------------------------------------------------------+
    | Result        | Returned for successful Get operations, but may also be empty when there was no matching row or column.    |
    +---------------+-----------------------------------------------------------------------------------------------------------+
    | Throwable        | In case the servers return an exception for the operation it is returned to the client as-is. You can        |
    |                | use it to check what went wrong and maybe handle the problem automatically in your code.                    |
    +---------------+-----------------------------------------------------------------------------------------------------------+

更进一步观察控制台上输出的返回结果数组,会发现空的 Result 实例打印出来的是:keyvalues=NONE (Result[0]). Get 请求成功找到相匹配的结果,
返回对应的 Cell 实例(Result[1]). Delete 操作也成功执行,返回空的 Result 实例 (Result[2]). 最后,BOGUS 列族操作产生异常 (Result[3])。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    用户使用 batch() 功能时, Put 实例不会被客户端写入缓冲区缓存。 batch() 请求是同步的,会把操作直接发送到服务器端,这个过程没有什么延迟
    或其它中间操作。这与 put() 调用明显不同,所以谨慎挑选需要的方法。

有两种不同的批处理调用看起来类似。上面的示例使用了第一种方式。第二种方式是允许提供一个回调实例,当在服务器上执行异步或并行调用时,由客户端
类库接收响应时调用。需要实现 Batch.Callback 接口,提供了 update() 方法。

以下示例是在上一示例基础上修改的,只是添加了回调实例:

    //Example application using batch operations with callbacks
    // Create a list to hold all values
    List<Row> batch = new ArrayList<Row>();
    
    Put put = new Put(ROW2);
    put.addColumn(COLFAM2, QUAL1, 4, Bytes.toBytes("val5"));
    batch.add(put);
    
    Get get1 = new Get(ROW1);
    get1.addColumn(COLFAM1, QUAL1);
    batch.add(get1);
    
    Delete delete = new Delete(ROW1);
    delete.addColumns(COLFAM1, QUAL2);
    batch.add(delete);
    
    Get get2 = new Get(ROW2);
    get2.addFamily(Bytes.toBytes("BOGUS"));
    batch.add(get2);
    
    try {
        table.batchCallback(batch, results, new Batch.Callback<Result>()
        {
            @Override
            public void update(byte[] region, byte[] row, Result result) {
                System.out.println("Received callback for row[" +
                Bytes.toString(row) + "] -> " + result);
            }
        });
    } catch (Exception e) {
        System.err.println("Error: " + e);
    }
    for (int i = 0; i < results.length; i++) {
        System.out.println("Result[" + i + "]: type = " +
        results[i].getClass().getSimpleName() + "; " + results[i]);
    }

会看到与上个示例相同的输出结果,但还有些额外的信息是回调实现发出的,类似如下:
    Before delete call...
    Cell: row1/colfam1:qual1/1/Put/vlen=4/seqid=0, Value: val1
    Cell: row1/colfam1:qual2/2/Put/vlen=4/seqid=0, Value: val2
    Cell: row1/colfam1:qual3/3/Put/vlen=4/seqid=0, Value: val3
    Received callback for row[row2] ->
    keyvalues=NONE
    Received callback for row[row1] ->
    keyvalues={row1/colfam1:qual1/1/Put/vlen=4/seqid=0}
    Received callback for row[row1] ->
    keyvalues=NONE
    Error: org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException:
    Failed 1 action:
    ...
    : 1 time,
    Result[0]: type = Result; keyvalues=NONE
    Result[1]: type = Result; keyvalues={row1/colfam1:qual1/1/Put/
    vlen=4/seqid=0}
    Result[2]: type = Result; keyvalues=NONE
    Result[3]: type = NoSuchColumnFamilyException;
    org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException:
    ...
    After batch call...
    Cell: row1/colfam1:qual1/1/Put/vlen=4/seqid=0, Value: val1
    Cell: row1/colfam1:qual3/3/Put/vlen=4/seqid=0, Value: val3
    Cell: row2/colfam2:qual1/4/Put/vlen=4/seqid=0, Value: val5



5 扫描 (Scans)
-----------------------------------------------------------------------------------------------------------------------------------------
在讨论过基本的 CRUD 类型的操作之后,现在来看一下扫描技术(scan), 这种技术类似于数据库系统中的游标(cursor), 并利用到了 HBase 提供的底层顺序
存储的数据结构。


5.1 介绍 (Introduction)
-----------------------------------------------------------------------------------------------------------------------------------------
扫描操作的使用跟 get() 方法非常类似。类似于其它功能,也有一个与之相关的支持类,Scan. 但由于扫描类似于迭代,因此没有响应的 scan() 调用,而
是通过一个 getScanner() 方法返回实际的扫描器实例用于迭代,可用的方法如下:

    ResultScanner getScanner(Scan scan) throws IOException
    ResultScanner getScanner(byte[] family) throws IOException
    ResultScanner getScanner(byte[] family, byte[] qualifier) throws IOException

后面两个方法是便利方法,隐式地帮用户创建 Scan 实例,随后会调用 getScanner(Scan scan) 方法。

Scan 类有如下构造器:
    Scan()
    Scan(byte[] startRow, Filter filter)
    Scan(byte[] startRow)
    Scan(byte[] startRow, byte[] stopRow)
    Scan(Scan scan) throws IOException
    Scan(Get get)

这与 Get 类的不同之处是很明显的:不是指定单个行的行键,可选地提供一个 startRow 参数 —— 定义从 HBase table 上扫描开始的行键。可选的 stopRow
参数用于限定扫描结束的行键。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    起始行总是包含的,而结束行是不包含的,表示为 [startRow, stopRow) 区间标记。
    
扫描操作的一个特性是,不必精确匹配起始和结束行。而是,扫描匹配的第一行等于或大于给定的起始行(startRow). 如果没有给定起始行,扫描从表的开始
扫描。在当前的行键等于或大于可选的停止行时,扫描结束工作。如果没有指定停止行,扫描会运行到表的结尾。

还有另外一个可选参数 filter, 一个 Filter 实例的引用。通常,Scan 实例简单使用空参数构造器创建,所有的可选参数都有相应的 getter 和 setter
方法可以使用。

类似于其它数据相关的类型,有一个从现有 Scan 实例拷贝所有参数的构造器。也有一个从现有的 Get 实例中拷贝参数的构造器。get 和 scan 在服务器端
的功能实际上是相同的。唯一不同的是,Get 的扫描必须在扫描中包含停止行,起始行和停止行是同一个值。

另外,当使用基于 Get 实例的构造器时,Scan 的下面方法返回 true:

    boolean isGetScan()

一旦创建了 Scan 实例,就可以向其添加详细的限制信息。但也允许使用空的 scan, 这样会读取整个 table, 包括所有的列族以及它们的列。可以使用各种方法
限定读取数据:

    Scan addFamily(byte [] family)
    Scan addColumn(byte[] family, byte[] qualifier)

有很多类似于 Get 类的方法可用:可以通过 addFamily() 设定列族以限定扫描返回的数据,或者,通过 addColumn() 更严格地限定仅包含特定的列。


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    如果用户只需要数据的子集,那么限制扫描的范围能发挥 HBase 的优势。因为 HBase 中的数据是按列存储的,如果扫描不读取某个列族,那么整个列族
    文件就不会读取,这就是列式存储架构的优势。

Scan 还有其它用于选择性的方法,第一组是围绕返回的 cell 版本的方法:

    Scan setTimeStamp(long timestamp) throws IOException
    Scan setTimeRange(long minStamp, long maxStamp) throws IOException
    TimeRange getTimeRange()
    Scan setMaxVersions()
    Scan setMaxVersions(int maxVersions)
    int getMaxVersions()

setTimeStamp() 方法时设置时间区间的快捷方法:setTimeRange(time, time + 1), 这两个方法会选择匹配设定区间的 cell. 很明显,前者更特定,选择
确切匹配的一个时间戳。getTimeRange() 返回上两个方法设置的值。每个列多少个 cell —— 换句话说,扫描返回多少个版本由 setMaxVersions() 方法控制,
一个设定给定的数量,另一个设置所有版本。

下一组方法与包含到扫描中的行相关:

    Scan setStartRow(byte[] startRow)
    byte[] getStartRow()
    Scan setStopRow(byte[] stopRow)
    byte[] getStopRow()
    Scan setRowPrefixFilter(byte[] rowPrefix)

使用 setStartRow() 和 setStopRow() 可以定义与构造器相同的参数,所有的方法都是为了更进一步限定返回的数据。对应的 getter 返回当前的设置(可能
为 null, 因为这两个参数都是可选的). setRowPrefixFilter() 是设置起始行为 rowPrefix 的值,停止行为大于当前 key 的下一个 key,增大二进制 key
的计算逻辑是这样,例如,假设行键为 { 0x12, 0x23, 0xFF, 0xFF }, 增加它的结果为 { 0x12, 0x24 }, 因为最后两个字节已经到达了它们的最大值。

下一组方法时围绕过滤器的:

    Filter getFilter()
    Scan setFilter(Filter filter)
    boolean hasFilter()

过滤器是联合时间区间,行选择器的。可以更进一步加入列族和列名的选择支持。setFilter() 可以分配一个或多个过滤器给扫描,getFilter() 返回当前的
过滤器。

Scan 还提供了一些更特殊的方法,用于处理特定场景。可以把它们当做为高级用户提供的方法,但它们实际上用起来很直接:

    Scan setReversed(boolean reversed)
    boolean isReversed()
    Scan setRaw(boolean raw)
    boolean isRaw()
    Scan setSmall(boolean small)
    boolean isSmall()

第一对方法使应用不使用 forward-only 迭代,而是使用相反的迭代。传统上 HBase 只提供向前的扫描,但最近的版本引入了反向迭代选项。由于数据是按
升序存储的,反向扫描涉及更复杂的处理。换句话说,反向扫描会比正向扫描慢一些。但会减轻在构建应用程序级别两个方向上的查找索引 (but alleviate
the previous necessity of building application-level lookup indexes for both directions)。

反向扫描的一个精妙之处在于反向是按每行的,而不是在一行之内。仍然会像正向扫描那样接收到每一行。

第二对方法 setRaw() method 切换扫描器为一个特使的模式,返回它找到的每一个 cell. 这包括被删除的 cell 但还没有从物理上移除,也包括那些带有
delete 标记的 cell.

最后一对方法用于处理 "小" 扫描。这类扫描只需要读取非常小的数据集,可以在一个 RPC 调用中返回。在一个 scan 实例上调用 setSmall(true) 指示客
户端 API 不要以通常的方式联合使用打开扫描器、获取数据、关闭扫描器的远程调用,而是在一个调用中完成所有操作。这种模式下,服务器端也有对读取
的优化,因此扫描尽可能地快。

Scan 类还提供了其它的方法调用,详细信息参考最新版本的 API javadoc.

 
5.2 ResultScanner 接口 (The ResultScanner Interface)
-----------------------------------------------------------------------------------------------------------------------------------------
扫描操作不会通过一次 RPC 请求返回所有匹配的行,而是以行为单位(per-row basis)返回。很明显,行的数量非常大,可能有上千条甚至更多,因此一次
调用会占用大量的系统资源并消耗很长的时间。

ResultScanner 把操作转换为类似 get 的操作,将每一行数据封装成一个 Result 实例,并将所有的 Result 实例放入一个迭代器中。ResultScanner 有如下
方法:

    Result next() throws IOException
    Result[] next(int nbRows) throws IOException
    void close()

两个 next() 调用供用户选择,调用 close() 方法释放所有扫描控制的资源。

    
    ● 扫描器租约 (Scanner Leases)
    -------------------------------------------------------------------------------------------------------------------------------------
    要确保尽早释放扫描器实例。一个打开的扫描器会占用不少服务器端资源,积累多了会占用大量的堆空间。当使用完 ResultScanner 之后应调用它的
    close() 方法,并考虑将它放到 try/finally 块中,或 try-with-resources 结构中,这样,即便在迭代过程中发生异常或者错误,也会保证 close()
    方法被调用。
    
    就像行锁一样,扫描器也使用同样的租约超时机制,保护其不被失效的客户端阻塞太久。设置如下配置属性来修改超时阈值(单位为毫秒):
    
        <property>
            <name>hbase.client.scanner.timeout.period</name>
            <value>120000</value>
        </property>

    要确保这个属性的值对锁和扫描器租约同样有效。
    
next() 调用返回一个单独的 Result 实例,这个实例代表了下一个可用的行。此外,可以使用 next(int nbRows) 一次获取多行数据,它返回一个数组,数组
中包含的 Result 实例最多可达 nbRows 个,每个实例代表唯一的一行。如果没有足够多的行,返回的数组也可能比较短,也可能数组为空。很明显,之前的
扫描已到达表尾部或停止行,没有足够的行来填充数据。

注意, 如果已到达表末尾 next() 调用会返回 null,但 next(int nbRows) 总会返回一个有效的数组,同样的原因,数组为空元素,但数组是有效的。

示例:

    // Example using a scanner to access data in a table

    // Create empty Scan instance.
    Scan scan1 = new Scan();
    // Get a scanner to iterate over the rows.
    ResultScanner scanner1 = table.getScanner(scan1);
    for (Result res : scanner1) {
        // Print row content
        System.out.println(res);
    }
    // Close scanner to free remote resources.
    scanner1.close();

    Scan scan2 = new Scan();
    //Add one column family only, this will suppress the retrieval of “colfam2”.
    scan2.addFamily(Bytes.toBytes("colfam1"));
    ResultScanner scanner2 = table.getScanner(scan2);
    for (Result res : scanner2) {
        System.out.println(res);
    }
    scanner2.close();

    Scan scan3 = new Scan();

    //Use fluent pattern to add specific details to the Scan.
    scan3.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5")).
        addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col-33")).
        setStartRow(Bytes.toBytes("row-10")).
        setStopRow(Bytes.toBytes("row-20"));
        
    ResultScanner scanner3 = table.getScanner(scan3);
    for (Result res : scanner3) {
        System.out.println(res);
    }
    scanner3.close();

    Scan scan4 = new Scan();
    // Only select one column.
    scan4.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("col-5")).
        setStartRow(Bytes.toBytes("row-10")).
        setStopRow(Bytes.toBytes("row-20"));
        
    ResultScanner scanner4 = table.getScanner(scan4);
    for (Result res : scanner4) {
        System.out.println(res);
    }
    scanner4.close();

    Scan scan5 = new Scan();
    // One column scan that runs in reverse
    scan5.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5")).
        setStartRow(Bytes.toBytes("row-20")).
        setStopRow(Bytes.toBytes("row-10")).
        setReversed(true);
    ResultScanner scanner5 = table.getScanner(scan5);
    for (Result res : scanner5) {
        System.out.println(res);
    }
    
    scanner5.close();

代码插入了 100 行数据,每行有两个列族,每个列族下包含 100 个列。第一个扫描操作扫描全表内容,第二个扫描操作只扫描一个列族,最后一个扫描操作
有严格的限制条件,其中包括对行范围的限制,同时还要求只扫描两个特定的列。输出如下:

    ...
    Scanning table #4...
    keyvalues={row-10/colfam1:col-5/1427010030763/Put/vlen=8/seqid=0}
    keyvalues={row-100/colfam1:col-5/1427010039565/Put/vlen=9/seqid=0}
    ...
    keyvalues={row-19/colfam1:col-5/1427010031928/Put/vlen=8/seqid=0}
    keyvalues={row-2/colfam1:col-5/1427010029560/Put/vlen=7/seqid=0}
    Scanning table #5...
    keyvalues={row-20/colfam1:col-5/1427010032053/Put/vlen=8/seqid=0}
    keyvalues={row-2/colfam1:col-5/1427010029560/Put/vlen=7/seqid=0}
    ...
    keyvalues={row-11/colfam1:col-5/1427010030906/Put/vlen=8/seqid=0}
    keyvalues={row-100/colfam1:col-5/1427010039565/Put/vlen=9/seqid=0}

再次强调,匹配的行键是按词典顺序排序的。可以简单地用 0 把行键补齐,这样扫描出来的结果更具可读性。另外要注意的是停止行在扫描结果中是排除的,
意思就是说如果想要 20 到 10 (反向扫描) 之间的所有行,要设定起始行为 row-20, 将 row-10 作为结束行。


5.3 Scanner 缓存 (Scanner Caching)
-----------------------------------------------------------------------------------------------------------------------------------------
如果没有正确配置,那么每次 next() 调用会为每一行产生一次 RPC 调用,即便使用 next(int nbRows) 进行调用也是如此,因为它只不过是在客户端循环
调用 next() 而已。很明显,这在处理小型 cell 时不会获得很好的性能。如果一次 RPC 调用能抓取更多的行会更有意义。这称为扫描缓存(scanner caching)
并且默认情况下是启用的。

有一个集群范围的配置属性 hbase.client.scanner.caching 控制着所有扫描的默认缓存。该属性默认为 100, 从而指示所有的扫描器在每一次 RPC 调用过程
中同时抓取 100 行。可以在 Scan 实例级别改写这个属性:

    void setCaching(int caching)
    int getCaching()

设定 scan.setCaching(200) 会提升每次远程调用的载荷为 200 行。两种 next() 方法都会受到这个设置的影响。getCaching() 方法返回当前该属性的值。


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    可以修改整体 HBase 安装的默认 100 的设置,将下面的配置属性添加到 hbase-site.xml 配置文件中:
    
        <property>
            <name>hbase.client.scanner.caching</name>
            <value>200</value>
        </property>

    这会设置所有的扫描器缓存为 200 行。

需要在少量的 RPC 调用和客户端及服务器的内存使用方面找到一个平衡点。设置较高的扫描器缓存多数时候会提升扫描性能,但设置太高也会产生相反的效果:
每次 next() 调用会占用更多的时间,因为需要抓取更多的数据,并传输给客户端,并且一旦超出了客户端进程可用的最大堆内存数量,会导致
OutOfMemoryException 而终止。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    当传输和处理数据的时间超过配置的扫描器租约超时时间时,客户端会收到 ScannerTimeoutException 异常的租约过期错误(lease expired error) 而
    结束。

示例:

    //Example timeout while using a scanner
    Scan scan = new Scan();

    ResultScanner scanner = table.getScanner(scan);

    //Get currently configured lease timeout
    int scannerTimeout = (int) conf.getLong(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, -1);
    try {
        //Sleep a little longer than the lease allows.
        Thread.sleep(scannerTimeout + 5000);
    } catch (InterruptedException e) {
    // ignore
    }
    while (true){
        try {
            Result result = scanner.next();
            if (result == null) break;
            
            //Print row content.
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
            break;
        }
    }
    scanner.close();

输出如下:
    
    Adding rows to table...
    Current (local) lease period: 60000ms
    Sleeping now for 65000ms...
    Attempting to iterate over scanner...
    org.apache.hadoop.hbase.client.ScannerTimeoutException: \
    65017ms passed since the last invocation, timeout is currently set to 60000
    at org.apache.hadoop.hbase.client.ClientScanner.next(ClientScanner.
    java)
    at client.ScanTimeoutExample.main(ScanTimeoutExample.java:53)
    ...
    Caused by: org.apache.hadoop.hbase.UnknownScannerException: \
    org.apache.hadoop.hbase.UnknownScannerException: Name: 3915, already
    closed?
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(...)
    ...
    Caused by: org.apache.hadoop.hbase.ipc.RemoteWithExtrasException( \
    org.apache.hadoop.hbase.UnknownScannerException): \
    org.apache.hadoop.hbase.UnknownScannerException: Name: 3915, already
    closed?
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(...)
    ...
    Mar 22, 2015 9:55:22 AM org.apache.hadoop.hbase.client.ScannerCallable
    close
    WARNING: Ignore, probably already closed
    org.apache.hadoop.hbase.UnknownScannerException: \
    org.apache.hadoop.hbase.UnknownScannerException: Name: 3915, already
    closed?
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(...)
    ...


5.3 Scanner 批处理操作 (Scanner Batching)
-----------------------------------------------------------------------------------------------------------------------------------------
到目前为止,已经介绍了如何使用客户端扫描器缓存来从远程 region 服务器向客户端整批传输数据。不过有件事需要注意:对于数据量非常大的行,这些行
有可能超出了客户端进程的内存容量。HBase 及其客户端 API 对此提供了解决办法:批处理(batching). 可以利用如下方法控制批处理:

    void setBatch(int batch)
    int getBatch()

与缓存机制相对,操作作用于行级别,批处理作用于 cell 级别。它控制 ResultScanner 实例每次调用 next() 方法获取的 cell 数量。例如,setBatch(5)
设置扫描会使每个 Result 实例返回 5 个 cell.


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    如果一行包括的列数超过了批量设置中设置的值,则会将该行分片返回,扫描器每次 next() 调用返回的 Result 为行的一片。
    
    如果行中所有的列数不被设置的批处理数量整除,最后一次返回的 Result 实例可能会包含比较少的列, 例如,如果一行有 17 列,用户把 batch 值设
    为 5,则一共会返回 4 个 Result 实例,这 4 个实例中包括的列数量应当分别为 5、5、5 和 2。
    
组合使用扫描器缓存和批量大小,可以方便地控制扫描一个范围内的行键时所需要的 RPC 调用次数。下面的示例使用这两个参数来调节每次 Result 实例的
大小。

示例:
    // Example using caching and batch parameters for scans

    private static void scan(int caching, int batch, boolean small)
        throws IOException {
        
        int count = 0;
        
        // Set caching and batch parameters.
        Scan scan = new Scan()
            .setCaching(caching)
            .setBatch(batch)
            .setSmall(small)
            .setScanMetricsEnabled(true);
            
        ResultScanner scanner = table.getScanner(scan);
        
        //Count the number of Results available.
        for (Result result : scanner) {
            count++;
        }
        
        scanner.close();
        ScanMetrics metrics = scan.getScanMetrics();
        
        System.out.println("Caching: " + caching + ", Batch: " + batch +
            ", Small: " + small + ", Results: " + count +
            ", RPCs: " + metrics.countOfRPCcalls);
    }

    public static void main(String[] args) throws IOException {
        ...
        // Test various combinations.
        scan(1, 1, false);
        scan(1, 0, false);
        scan(1, 0, true);
        scan(200, 1, false);
        scan(200, 0, false);
        scan(200, 0, true);
        scan(2000, 100, false);
        scan(2, 100, false);
        scan(2, 10, false);
        scan(5, 100, false);
        scan(5, 20, false);
        scan(10, 10, false);
        ...
    }

代码打印出 caching 和 batching 的值,服务器返回的 result 数量,以及需要多少个 RPC 调用获取它们。例如下面的输出:

    Caching: 1, Batch: 1, Small: false, Results: 200, RPCs: 203
    Caching: 1, Batch: 0, Small: false, Results: 10, RPCs: 13
    Caching: 1, Batch: 0, Small: true, Results: 10, RPCs: 0
    Caching: 200, Batch: 1, Small: false, Results: 200, RPCs: 4
    Caching: 200, Batch: 0, Small: false, Results: 10, RPCs: 3
    Caching: 200, Batch: 0, Small: true, Results: 10, RPCs: 0
    Caching: 2000, Batch: 100, Small: false, Results: 10, RPCs: 3
    Caching: 2, Batch: 100, Small: false, Results: 10, RPCs: 8
    Caching: 2, Batch: 10, Small: false, Results: 20, RPCs: 13
    Caching: 5, Batch: 100, Small: false, Results: 10, RPCs: 5
    Caching: 5, Batch: 20, Small: false, Results: 10, RPCs: 5
    Caching: 10, Batch: 10, Small: false, Results: 20, RPCs: 5

可以修改调整这两个参数来查看它们对输出结果的影响。


5.4 行分片 (Slicing Rows)
-----------------------------------------------------------------------------------------------------------------------------------------
使用如下方法将表数据分片(slicing of table data):

    int getMaxResultsPerColumnFamily()
    Scan setMaxResultsPerColumnFamily(int limit)
    int getRowOffsetPerColumnFamily()
    Scan setRowOffsetPerColumnFamily(int offset)

    long getMaxResultSize()
    Scan setMaxResultSize(long maxResultSize)

前面四个方法一起工作,允许应用将每个选出的行切片,使用 offset 从某个特定的列开始,限制每个列族最大的结果(a max results per column family),
一旦达到就停止返回数据。后面一对方法允许设置和获取扫描返回数据大小的限制上限。它保持一个扫描选取 cell 的计数器,一旦超出了这个限制,就停止
返回数据。

示例:
    // Example using offset and limit parameters for scans
    private static void scan(int num, int caching, int batch, int offset,
        int maxResults, int maxResultSize, boolean dump) throws IOException
    {
        int count = 0;
        Scan scan = new Scan()
            .setCaching(caching)
            .setBatch(batch)
            .setRowOffsetPerColumnFamily(offset)
            .setMaxResultsPerColumnFamily(maxResults)
            .setMaxResultSize(maxResultSize)
            .setScanMetricsEnabled(true);
        
        ResultScanner scanner = table.getScanner(scan);
        System.out.println("Scan #" + num + " running...");
        
        for (Result result : scanner) {
            count++;
            if (dump) System.out.println("Result [" + count + "]:" + result);
        }
        
        scanner.close();
        ScanMetrics metrics = scan.getScanMetrics();
        
        System.out.println("Caching: " + caching + ", Batch: " + batch +
            ", Offset: " + offset + ", maxResults: " + maxResults +
            ", maxSize: " + maxResultSize + ", Results: " + count +
            ", RPCs: " + metrics.countOfRPCcalls);
    }

    public static void main(String[] args) throws IOException {
        scan(1, 11, 0, 0, 2, -1, true);
        scan(2, 11, 0, 4, 2, -1, true);
        scan(3, 5, 0, 0, 2, -1, false);
        scan(4, 11, 2, 0, 5, -1, true);
        scan(5, 11, -1, -1, -1, 1, false);
        scan(6, 11, -1, -1, -1, 10000, false);
        ...
    }

示例代码没有给出创建表的过程,表由两个列族组成,10 行数据,每个列族有 10 个列。代码输出类似如下:

    Scan #1 running...
    Result [1]:keyvalues={row-01/colfam1:col-01/1/Put/vlen=9/seqid=0,
    row-01/colfam1:col-02/2/Put/vlen=9/seqid=0,
    row-01/colfam2:col-01/1/Put/vlen=9/seqid=0,
    row-01/colfam2:col-02/2/Put/vlen=9/seqid=0}
    ...
    Result [10]:keyvalues={row-10/colfam1:col-01/1/Put/vlen=9/seqid=0,
    row-10/colfam1:col-02/2/Put/vlen=9/seqid=0,
    row-10/colfam2:col-01/1/Put/vlen=9/seqid=0,
    row-10/colfam2:col-02/2/Put/vlen=9/seqid=0}
    Caching: 11, Batch: 0, Offset: 0, maxResults: 2, maxSize: -1,
    Results: 10, RPCs: 3
    
    Scan #2 running...
    Result [1]:keyvalues={row-01/colfam1:col-05/5/Put/vlen=9/seqid=0,
    row-01/colfam1:col-06/6/Put/vlen=9/seqid=0,
    row-01/colfam2:col-05/5/Put/vlen=9/seqid=0,
    row-01/colfam2:col-06/6/Put/vlen=9/seqid=0}
    ...
    Result [10]:keyvalues={row-10/colfam1:col-05/5/Put/vlen=9/seqid=0,
    row-10/colfam1:col-06/6/Put/vlen=9/seqid=0,
    row-10/colfam2:col-05/5/Put/vlen=9/seqid=0,
    row-10/colfam2:col-06/6/Put/vlen=9/seqid=0}
    Caching: 11, Batch: 0, Offset: 4, maxResults: 2, maxSize: -1,
    Results: 10, RPCs: 3
    
    Scan #3 running...
    Caching: 5, Batch: 0, Offset: 0, maxResults: 2, maxSize: -1,
    Results: 10, RPCs: 5
    
    Scan #4 running...
    Result [1]:keyvalues={row-01/colfam1:col-01/1/Put/vlen=9/seqid=0,
    row-01/colfam1:col-02/2/Put/vlen=9/seqid=0}
    Result [2]:keyvalues={row-01/colfam1:col-03/3/Put/vlen=9/seqid=0,
    row-01/colfam1:col-04/4/Put/vlen=9/seqid=0}
    ...
    Result [31]:keyvalues={row-10/colfam1:col-03/3/Put/vlen=9/seqid=0,
    row-10/colfam1:col-04/4/Put/vlen=9/seqid=0}
    Caching: 11, Batch: 2, Offset: 0, maxResults: 5, maxSize: -1,
    Results: 32, RPCs: 5
    Scan #5 running...
    Caching: 11, Batch: -1, Offset: -1, maxResults: -1, maxSize: 1,
    Results: 10, RPCs: 13
    Scan #6 running...
    Caching: 11, Batch: -1, Offset: -1, maxResults: -1, maxSize: 10000,
    Results: 10, RPCs: 5

第一次扫描开始于 offset 0 并请求最多 2 cells, 返回的列为 one and two.

第二次扫描与第一次相同,但设置 offset to 4, 因此获取列 five to six. 注意,offset 实际上定义的是从列起始忽略的 cell 的数量,值为 4 造成
最开始的 4 个列被忽略。

第三次扫描,没有输出任何信息,因为只对 metrics 感兴趣。与 #1 扫描相同,但是用了 caching 值 5. RPC 的最小值应该为 3 (对于小型扫描,执行
打开,抓取,和关闭调用),但我们看到的是 5 RPCs, 因为不能在一次调用中抓取表中的 10 行结果,需要两次调用,每次调用抓取 5 个结果,再加上一
次额外的调用确定没有剩下更多的行要抓取,因此为 5 RPCs.

#4 扫描,使用 batching 值为 2 联合之前的扫描,因此每次调用 next() 返回 2 个 cell, 但同时限制了每个列族返回的 cell 数量为 5。另外,联合
使用 caching 值为 11,因此看到 5 个到服务器的 RPC 调用。

最后 #5 and #6 扫描使用 setMaxResultSize() 限制返回给调用者的数据数量。扫描器的 caching 是设置行的数量,而 max result size 设置的是字节数。




5.5 按需载入列族 (Load Column Families on Demand)
-----------------------------------------------------------------------------------------------------------------------------------------
扫描还有一个高级特性,loading column families on demand, 由如下方法控制:

    Scan setLoadColumnFamiliesOnDemand(boolean value)
    Boolean getLoadColumnFamiliesOnDemandValue()
    boolean doLoadColumnFamiliesOnDemand()

这个功能是读优化的,只对有一个以上列族的表有用,特别是列族中的数据之间有依赖关系的场景有利。例如,假设一个列族持有元数据,另一个列族持有很
大量的载荷数据。要扫描元数据列,如果某个列中含有一个标志,需要访问在另外列族中的载荷数据。如果把这两个列族都包含到扫描中代价是很大的。因为
这样的扫描每一行都要载入载荷数据。

通过 setLoadColumnFamiliesOnDemand(true) 启用这个特性,只需一半的准备工作:也需要一个过滤器实现下面方法,返回一个 boolean 标志:

    boolean isFamilyEssential(byte[] name) throws IOException

过滤器的思想是决定某个列族是否为 essential. 当服务器扫描数据时,它们首先为列族设置内部的扫描器。如果 load column families on demand 已启用,
并且设置了过滤器,它会调用过滤器并请求决定一个包含的列族是否扫描。在列族加入之前,过滤器的 isFamilyEssential() 通过列族名称调用,并且如果
加入进来必须返回 true, 如果返回 false, 那么该列族当前被忽略,并且在之后需要时载入。

另一方面,必须添加所有的列族到扫描中,不管它们是否是基本的(essential)。它们只有先加入到扫描器中,框架才会调用过滤器来决定某个列族。



5.6 Scanner 度量 (Scanner Metrics)
-----------------------------------------------------------------------------------------------------------------------------------------
Scan 类的另一特性是使客户端可以探究操作的执行效率,通过如下方法实现:

    Scan setScanMetricsEnabled(final boolean enabled)
    boolean isScanMetricsEnabled()
    ScanMetrics getScanMetrics()

可以通过调用 setScanMetricsEnabled(true) 来启用 scan metrics 集合。一旦扫描完成,可以通过 getScanMetrics() 方法获取 ScanMetrics。
isScanMetricsEnabled() 方法用于检查之前 metrics 集合是否启用。获取的 ScanMetrics 实例有一组字段可以读取以确定操作的开销:

    Metrics provided by the ScanMetrics class
    +-------------------------------+-------------------------------------------------------------------
    | Metric Field                    | Description
    +-------------------------------+--------------------------------------------------------------------
    | countOfRPCcalls                | The total amount of RPC calls incurred by the scan.
    +-------------------------------+--------------------------------------------------------------------
    | countOfRemoteRPCcalls            | The amount of RPC calls to a remote host
    +-------------------------------+--------------------------------------------------------------------
    | sumOfMillisSecBetweenNexts    | The sum of milliseconds between sequential next() calls.
    +-------------------------------+--------------------------------------------------------------------
    | countOfNSRE                    | Number of NotServingRegionException caught.
    +-------------------------------+--------------------------------------------------------------------
    | countOfBytesInResults            | Number of bytes in Result instances returned by the servers.
    +-------------------------------+--------------------------------------------------------------------
    | countOfBytesInRemoteResults    | Same as above, but for bytes transferred from remote servers.
    +-------------------------------+--------------------------------------------------------------------
    | countOfRegions                | Number of regions that were involved in the scan.
    +-------------------------------+--------------------------------------------------------------------
    | countOfRPCRetries                | Number of RPC retries incurred during the scan.
    +-------------------------------+--------------------------------------------------------------------
    | countOfRemoteRPCRetries        | Same again, but RPC retries for non-local servers.
    +-------------------------------+--------------------------------------------------------------------



6 其它特性 (Miscellaneous Features)
-----------------------------------------------------------------------------------------------------------------------------------------



6.1 Table 实用方法 (The Table Utility Methods)
-----------------------------------------------------------------------------------------------------------------------------------------
客户端 API 表现为 Table 类的实例,并且给出访问 HBase 表的方法。除了已经讨论过的主要特性之外,这个类还有一些值得注意的方法:

    
    ● void close()
    -------------------------------------------------------------------------------------------------------------------------------------
    这个方法之前提到过,完成一个表的工作之后,要调用一次 close() 方法。在其内部有一些清理工作需要运行,调用该方法会触发这个过程。把打开和
    关闭某个表的工作放到 try/catch, 或者最好放到一个 try-with-resources(on Java 7 or later) 块中运行。
    
    
    ● TableName getName()
    -------------------------------------------------------------------------------------------------------------------------------------
    这个是获取表名称的便捷方法。作为 TableName 类的实例返回,提供对名称空间和实际的表名的访问。


    ● Configuration getConfiguration()
    -------------------------------------------------------------------------------------------------------------------------------------
    这个方法允许用户访问 Table 实例使用的配置。因为得到的是 Configuration 实例的引用,所以用户修改的参数立刻生效。



    ● HTableDescriptor getTableDescriptor()
    -------------------------------------------------------------------------------------------------------------------------------------
    每个表的定义由 HTableDescriptor 类实例描述,可以通过 getTableDescriptor() 访问底层定义。




6.2 Bytes 类 (The Bytes Class)
-----------------------------------------------------------------------------------------------------------------------------------------
这个类用于将 Java 原生基本类型转换为 HBase 原生支持的原始字节数组格式,例如 String, long

大部分方法有 3 种形式,如:

    static long toLong(byte[] bytes)
    static long toLong(byte[] bytes, int offset)
    static long toLong(byte[] bytes, int offset, int length)

可以只输入一个字节数组,或者一个数组和一个偏移量,或者一个数组,偏移量,以及一个长度值。具体用法取决于最初这个字节数组是如何生成的。如果是
之前由 toBytes() 方法创建的,可以安全地使用第一种形式,简单地将数组输入方法中就可以了。整个数组内容都转换为值。

Bytes 类支持以下原生 Java 类型和字节数组之间的转换:String, boolean, short, int, long, double, float, ByteBuffer, and BigDecimal.

详细信息参考最新版本的 JavaDoc-based API

 

(本篇完)

 

系列目录:

HBase CRUD 操作指南 (一)

HBase CRUD 操作指南 (二)

HBase CRUD 操作指南 (三)

 

参考:

    《HBase - The Definitive Guide - 2nd Edition》Early release —— 2015.7 Lars George

大语言模型在建筑规范自动化合规审查中的微调策略与规模效应实践 大语言模型(LLM)通过在海量文本数据上预训练,具备了强大的语言理解和生成能力。其核心原理是基于Transformer架构,通过自注意力机制捕捉长距离依赖关系。在工程实践中,为了将这种通用能力适配到建筑、法律、金融等高度专业化的垂直领域,通常需要采用领域微调技术。微调通过使用特定领域的高质量指令数据对模型参数进行更新,使其掌握专业术语、逻辑规则和任务范式,从而解决通用模型在专业场景下知识匮乏和“幻觉”问题。结合检索增强生成(RAG)技术,将动态外部知识库作为模型的“参考手册”,能进一步提升事实准确性并降低幻 阅读详情

相关推荐

STM32单片机语音提示盲人拐杖整点报时夜间警示超声波测距

STM32单片机语音提示盲人拐杖整点报时夜间警示超声波测距 关键词:语音提示盲人拐杖 整点报时 超声波测距拐杖

LS840233684的博客 2047

JAVA中row与column,Java Scan.getRowOffsetPerColumnFamily方法代码示例

import org.apache.hadoop.hbase.client.Scan; //导入方法依赖的package包/类/*** Opens a scanner across memstore, snapshot, and all StoreFiles. Assumes we* are not in a compaction.** @param store who we scan* @p...

weixin_32867357的博客 247

移相变压器Simulink建模与HVDC系统仿真实践

移相变压器是电力电子领域实现精确相位调节的核心设备,其通过特殊绕组设计改变输出电压相位角,在解决环网潮流不均、阻尼功率振荡等场景具有关键作用。本文基于MATLAB/Simulink环境,详细解析移相变压器的建模原理与技术实现,包括磁路耦合特性模拟、参数计算方法和控制策略设计。针对HVDC高压直流输电和FACTS柔性交流输电系统等典型应用,提供仿真模型搭建技巧与问题排查指南,特别涵盖新能源并网场景下的相位调节优化方案。通过实测数据验证,所建模型在稳态精度和动态响应方面均满足工程要求,为电力系统稳定性分析提供有

weixin_28278377的博客 272

org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException: org.apache.hadoop.hbase.regionserv

报错: Exception in thread "main" org.apache.hadoop.hbase.NamespaceNotFoundException: org.apache.hadoop.hbase.NamespaceNotFoundException: school Caused by: org.apache.hadoop.hbase.ipc.RemoteWithExtrasException(org.apache.hadoop.hbase.NamespaceNotFoundExcepti

Y0730Y的博客 4010

MATLAB并行开不了的解决办法

在服务器上新安装了MATLAB 2013b,在开并行计算的时候出现了下列问题 经过在网上搜多这个问题,我感觉这个问题应该是安装的时候的验证问题或者激活不成功之类的。注意其中有一句validate the profile ‘local’ in the Cluster Profile Manager.在matlab官网上找到了设置Cluster Manager的教程,如下 parallel>

sinat_36713319的博客 5987

音视频从入门到精通——指数哥伦布码原理

在计算机中,一般数字的编码都为二进制,但是由于以相等长度来记录不同数字,因此会出现很多的。

mirana的专栏 1383

NoSuchColumnFamilyException: org.apache.hadoop.hbase.regionserv

参考链接:https://www.cnblogs.com/mkl34367803/p/10723554.html。

weixin_44589713的博客 1037

在国产麒麟系统上,用Postfix和Dovecot手搓一个内部邮件服务器(附Foxmail配置)

本文详细介绍了在国产麒麟系统上使用Postfix和Dovecot搭建内部邮件服务器的完整流程,包括系统准备、核心配置、安全加固及客户端适配。针对国产环境的特殊需求,提供了依赖包适配、配置差异和Foxmail客户端配置的实用解决方案,助力企业实现高效内部协作。

weixin_33722405的博客 371

hbase 查询设置超时_hbase scan超时问题

下面是异常信息:2018-11-08 16:55:52,361 INFO [main] org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl: recovered from org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=36, ...

weixin_39556590的博客 862

SCCM实战指南:从零搭建企业级Windows自动化部署平台

本文提供了一份详细的SCCM实战指南,手把手教你从零搭建企业级Windows自动化部署平台。内容涵盖环境规划、AD架构扩展、SQL Server配置、SCCM主站点安装,以及最终实现操作系统镜像的自动化部署,旨在帮助IT管理员彻底告别手动装机,实现高效、规范的Windows设备批量管理。

weixin_29251337的博客 638

【血汗泪心路历程】怎么彻底删掉Sangfor文件?怎么彻底删除easyconnect?删除sangfor后网络坏了、某些app无法正常启动怎么解决?

教程来源于网络的五湖四海+gpt解答。用到了好几个教程和方法,遂这篇总结一下。会标明出处!先上一下战绩:终于把sangfor扔进回收站里了!!!哈哈哈那一刻真的好爽。

weixin_71246590的博客 6万+

HBase Java API 开发:表的扫描与扫描的缓存和批量处理 第1关:批量处理

HBase Java API 开发:表的扫描与扫描的缓存和批量处理 第1关:批量处理

qq_61604164的博客 2570

2025华为OD机试真题最新题库 (B+C+D+E+2025A+2025B卷) + 在线OJ在线刷题使用(C++、Java、Python C语言 JS合集)(正在更新2025B卷,目前已收录710道)

2024年,华为目前已经启用D卷,目前D卷和C卷的题目一样一次订阅永久阅读,支持在线刷题,持续更新,有问题随时解答,本专栏题目数量已收录到484道。每篇文章的思路分析都非常详细,题目新增图解思路,问题解疑,多样例测试,超过百字的思路参考解析。

KJ.JK 11万+

大数据期末实战指南:ZooKeeper、HBase与Hive核心操作解析

本文为大数据技术学习者提供了一份详尽的期末实战指南,重点解析了ZooKeeper、HBase与Hive三大核心组件的操作与应用。文章深入浅出地讲解了ZooKeeper的协调机制与常用命令、HBase的数据模型与Shell操作,以及Hive的外部表创建与SQL查询,旨在帮助读者巩固知识体系,高效应对期末考试与实践挑战。

weixin_29083475的博客 117

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

基本操作:如何在HBase中进行基本的CRUD操作

1.背景介绍 在HBase中进行基本的CRUD操作是一项重要的技能。在本文中,我们将深入了解HBase的核心概念和算法原理,并通过具体的代码实例来展示如何进行基本的CRUD操作。 1. 背景介绍 HBase是一个分布式、可扩展、高性能的列式存储系统,基于Google的Bigtable设计。HBase可以存储大量数据,并提供快速的随机读写访问。HBase的核心特点是支持大规模数据的存储和查询,...

AI天才研究院 1179

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

使用Java API对HBase进行CRUD操作

package test;   import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry;   import org.apache.

bingjie1217的专栏 1667

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

第二十二章:HBase的CRUD操作

1.背景介绍 1. 背景介绍 HBase是一个分布式、可扩展、高性能的列式存储系统,基于Google的Bigtable设计。它是Hadoop生态系统的一部分,可以与HDFS、MapReduce、ZooKeeper等组件集成。HBase具有高可靠性、高性能和高可扩展性,适用于大规模数据存储和实时数据访问场景。 在HBase中,数据以行为单位存储,每行数据由一个行键(row key)和一组列族(...

AI天才研究院 1220

HBase基本操作与CRUD

1.背景介绍 HBase是一个分布式、可扩展、高性能的列式存储系统,基于Google的Bigtable设计。它是Hadoop生态系统的一部分,可以与HDFS、MapReduce、ZooKeeper等组件集成。HBase适用于大规模数据存储和实时数据访问场景,如日志记录、实时数据分析、实时数据处理等。 HBase的核心特点是提供了高性能的随机读写操作,支持数据的自动分区和负载均衡,同时具有高可用...

AI天才研究院 1194

JavaAPI如何操作HBase完成CRUD

精选30+云产品,助力企业轻松上云!>>> 1.只需...

3918

HBase CRUD 操作指南 (二)

继  HBase CRUD 操作指南 (一)   3. CRUD 操作 (CRUD Operations) 数据库的初始基本操作通常称为 CRUD (create, read, update, and delete), 指的是 增、查、改、删四种操作。HBase 中有与之对应的的一组操作,由 Table interface 接口提供。     public interface Table ...

devalone 的专栏 2694

HBase DDL操作代码汇总(namespace+table CRUD操作)

注:如果出现无法连接到zookeeper等的相关错误,可以将以下代码打jar包,在HMaster节点上执行。具体效果可以通过web端进行查看,端口为60010,ip替换即可。将代码打包部署于HMaster的节点上,运行jar文件即可。2.hbase-site.xml(请参考自己的配置文件)DDL操作主要是关于命名空间和表格的内容增删改查。

wusuoweiieq的博客 1465

HBase中的CRUD

addColumns(byte[ ] family , byte[ ] qualifiler , long timestamp) 删除指定列的等于或小于给定版本号的所有版本。addColumn(byte[ ] family , byte[ ] qualifiler , long timestamp) 删除指定列的特定版本。addColumn(byte[ ] family , byte[ ] qualifiler) 删除指定列的最新版本。Table接口提供的,保证在一个原子操作内对数据完成修改和删除操作。

kelouze06的博客 1328

Spark操作Hbase

Spark 下操作 HBase(1.0.0 新 API) HBase经过七年发展,终于在今年2月底,发布了 1.0.0 版本。这个版本提供了一些让人激动的功能,并且,在不牺牲稳定性的前提下,引入了新的API。虽然 1.0.0 兼容旧版本的 API,不过还是应该尽早地来熟悉下新版API。并且了解下如何与当下正红的 Spark 结合,进行数据的写入与读取。鉴于国内外有关 HBase 1.0.

拱头的专栏 1万+

安装并配置Hbase,使用Hbase的Java API实现简单的CRUD操作

实验内容:安装并配置Hbase,使用Hbase的Java API实现简单的CRUD操作 实验步骤: 一.HBase安装配置 下载压缩包 将压缩包从Windows传输到Linux当前目录下 安装 解压安装到指定目录下/opt/module 配置环境变量 在/etc/profile文件里添加HBase安装路径的配置信息,之后用source命令使配置生效。 二 .HBase配置(...

qq_44301910的博客 350

HBase学习之路(二):Java客户端的CRUD操作详讲

内容简介一、概述二、操作前的准备三、put操作四、get操作五、delete操作六、总结 一、概述 HBase作为一个数据库最常见的交互方式是使用JavaAPI与其交互,HBase提供给客户端非常丰富的JavaAPI对数据库进行增删改查等操作。事实上,HBase的主要客户端接口是由org.apache.hadoop.hbase.client包中的HTable提供,我们可以通过这个类向HBase读...

萧邦主的城邦 839

HBASE的CRUD操作

HBASE中最基本的操作是CRUD(Creat,Read,Update,Delete)操作,HBase提供了两种方式实现相关操作,即JAVA API和HBASE shell。 Put 类 Put类是Hbase存储数据的基本类,通过api可知,put的构造方法有多种,但无论哪种构造方法,都需要传入行键row,如: Put(byte[] row) Put(byte[] row,

萧萧落木的专栏 1595
上一篇: HBase CRUD 操作指南 (二)
下一篇: HBase 过滤器 (一)
devalone
博客等级 码龄17年 108粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值