【问题标题】:HBase Put with timestamp does not work带有时间戳的 HBase Put 不起作用
【发布时间】:2012-08-07 16:29:38
【问题描述】:

我写了一个简单的测试程序来插入一行。与普通 HBase Put 示例程序的唯一不同点是 Put 实例及其 KeyValue 实例是使用时间戳创建的。

预期的行为是插入一行。但是,在我的 HBase 环境中,没有插入任何行。

下面是我的测试程序。

import java.io.*;
import java.util.*;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.*;

public class Test
{
    // Names of table, family, qualifier and row ID.
    private static final byte[] TABLE     = Bytes.toBytes("test-table");
    private static final byte[] FAMILY    = Bytes.toBytes("test-family");
    private static final byte[] QUALIFIER = Bytes.toBytes("test-qualifier");
    private static final byte[] ROWID     = Bytes.toBytes("test-rowid");

    /**
     * The entry point of this program.
     *
     * <p>
     * This program assumes that there already exists an HBase
     * table named "test-table" with a column family named
     * "test-family". To create an HBase table satisfying these
     * conditions, type the following at the hbase shell prompt.
     * </p>
     *
     * <pre>
     * hbase&gt; create 'test-table', 'test-family'
     * </pre>
     *
     * <p>
     * This program inserts a row whose row ID is "test-rowid"
     * with a column named "test-family:test-qualifier". The
     * value of the column is the string expression of
     * <code>new Date()</code>.
     * </p>
     */
    public static void main(String[] args) throws Exception
    {
        // Get the table.
        Configuration conf = HBaseConfiguration.create();
        HTable table = new HTable(conf, TABLE);

        // Prepare data to put.
        byte[] value = Bytes.toBytes(new Date().toString());
        Put put = new Put(ROWID);
        put.add(FAMILY, QUALIFIER, value);

        // Clone Put with a timestamp.
        put = clone(put, 10);

        // Put the data.
        table.put(put);

        // Read back the data.
        Get get = new Get(ROWID);
        Result result = table.get(get);

        // Dump the read data.
        System.out.println("DATA = " + result.toString());
    }

    /**
     * Clone the given Put instance with the given timestamp.
     */
    private static Put clone(Put a, long timestamp) throws IOException
    {
        // Create a Put instance with the specified timestamp.
        Put b = new Put(a.getRow(), timestamp);

        Map<byte[], List<KeyValue>> kvs = a.getFamilyMap();

        // Copy KeyValue's from the source Put (a) to
        // the cloned Put (b). Note the given timestamp
        // is used for each new KeyValue instance.
        for (List<KeyValue> kvl : kvs.values())
        {
            for (KeyValue kv : kvl)
            {
                b.add(new KeyValue(
                    kv.getRow(),
                    kv.getFamily(),
                    kv.getQualifier(),
                    timestamp,
                    kv.getValue()));
            }
        }

        return b;
    }
}

这个程序生成的控制台输出如下。

DATA = keyvalues=NONE

hbase shell 中的“扫描”显示“0 行”。

hbase(main):011:0> scan 'test-table'
ROW                                              COLUMN+CELL
0 row(s) in 0.0080 seconds

注释掉克隆 Put 实例的代码行,如下所示,

        // Clone Put with a timestamp.
        //put = clone(put, 10);

也就是说,使用不带时间戳参数创建的 Put 实例会改变程序的行为。在这种情况下,控制台输出显示插入的值,

DATA = keyvalues={test-rowid/test-family:test-qualifier/1344594210281/Put/vlen=28}

“扫描”显示插入的行。

hbase(main):012:0> scan 'test-table'
ROW                                              COLUMN+CELL
 test-rowid                                      column=test-family:test-qualifier, timestamp=1344594210281, value=Fri Aug 10 19:23:30 JST 2012
1 row(s) in 0.0110 seconds

在我的测试程序中使用时间戳克隆 Put 实例的逻辑摘自一个已知可以工作的开源项目。所以,我猜这个问题的根本原因存在于我的 HBase 环境中,但我不知道。我的调查可能不够充分,但我还没有在 HBase 日志中看到任何错误。

谁能告诉我这个问题?

【问题讨论】:

  • 您是否尝试过创建一个带有时间戳的新 put 而不是克隆现有的?您还可以在 Put 类的 add 方法中指定时间戳。只是看看问题是否仍然存在,如果是,则可能意味着问题出在您的环境中。

标签: hbase


【解决方案1】:

Timestamp 列族和列名构成一个组合键。这里的时间戳是 UNIX 时间戳。

【讨论】:

    【解决方案2】:

    KeyValueTestUtil.create 可以创建 KeyValue 对象,并将其设置为 Put

    【讨论】:

      【解决方案3】:

      我不确定这是否会有所帮助,但是 - 我以前去过那里,所以,只是想帮助你调试你的逻辑。

      我要确保的第一件事是您之前从未删除过该行。 H-Base Delete 的工作方式是在当前时间戳(除非您指定另一个)有问题的( Row/KeyValue )中的位置放置一个墓碑标记。太棒了 - 如果你在删除之后拍了一个 Put,并且没有发生重大压缩,你将永远看不到你的 Put ...这是一个线程:https://issues.apache.org/jira/browse/HBASE-5241 - 你可以尝试执行“major_compact”在执行另一个测试循环之前,从该表上的 H-Base shell 中提取。

      ..这是我的第一个猜测...它符合以下测试场景:在当前时间放置,执行扫描,断言放置操作有效(是的 - 是的!),然后,删除当前数据以重置托盘,使用较小的时间戳执行下一个 Put - 执行扫描 - 刮头...

      分手的想法 - Get 操作总是返回 KeyValue 的 最新 版本。所以......如果在您的测试中您执行一个时间戳为 T1 的 Put,然后您执行一个时间戳为 T2 且 T2

      希望里面的东西能帮助你的旅程.....

      【讨论】:

        猜你喜欢
        • 2017-07-28
        • 2020-02-28
        • 2021-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多