我正在使用存储在HBase中的大量数据。存储在我的列中的许多值实际上是数据的“向量” - 多个值。我打算处理存储多个值的方法是通过ByteBuffer
。由于我知道列族中每列中存储的数据类型,因此我编写了一系列类,扩展了包含ByteBuffer
的基类,并为我提供了一组简单的方法来读取单个值以及在末尾添加其他值。我已经独立于我的HBase项目测试了这个类,它按预期工作。
为了更新我的数据库(每次更新几乎每一行都更新),我使用TableMapper
mapreduce作业迭代数据库中的每一行。我的每个映射器(在我的集群中,有六个)将整个更新文件(很少超过50MB)加载到内存中,然后在迭代它时更新每个行ID。
我遇到的问题是每次从Result
对象中提取数据值时,它都会在其末尾附加4个字节。这使我的更新变得困难,因为我不确定是否期望这个“填充”每次都是额外的4个字节,或者它是否可以膨胀到更大/更小的东西。因为我将它加载到我的ByteBuffer
包装器中,所以没有填充是很重要的,因为当我向其添加额外的数据点时,这将导致我的数据中存在间隙,这将导致无法读出它们以后没有错误。
我写了一个测试,通过创建一个测试表和类来确认我的假设。该表每列只有一个数据点(一个双 - 我已经确认进入的字节长度是8)并且我编写了以下代码来检索和检查它。
HTable table = new HTable("test");
byte[] rowId = Bytes.toBytes("myid");
Get get = new Get(rowId);
byte[] columnFamily = Bytes.toBytes("data");
byte[] column = Bytes.toBytes("column");
get.addColumn(columnFamily, column);
Result = table.get(get);
byte[] value = result.value();
System.out.printlin("Value size: " + value.length);
double doubleVal = Bytes.toDouble(value);
System.out.println("Fetch yielded: " + doubleVal);
byte[] test = new byte[8];
for (int i = 0; i < value.length - 4; i++)
blah[i] = value[i];
double dval = Bytes.toDouble(test);
System.out.println("dval: " + dval);
table.close()
结果是:
Value size: 12
Fetch yielded: 0.3652
dval: 0.3652
这些值是可以预期的。
有关如何解决此问题的任何想法?我知道像Avro这样的序列化引擎的存在,但我试图暂时避免使用它们,我的数据非常简单,我觉得我不应该这样做。
编辑:我继续向前,以我数据类型大小的最大公倍数截断我的数据。根据我的经验,这些额外的字节专门附加到我的byte[]
数组的末尾。我已经制作了一些以相当干净的方式自动处理这个问题的课程,但我仍然很好奇为什么会发生这种情况。
答案 0 :(得分:2)
使用MapReduce将数据导入HBase时遇到了类似的问题。由于这段代码,我的rowkeys中附加了垃圾字节:
public class MyReducer extends TableReducer<Text, CustomWritable, Text> {
protected void reduce(Text key, Iterable<CustomWritable> values, Context context) throws IOException, InterruptedException {
// only get first value for the example
CustomWritable value = values.iterator().next();
Put put = new Put(key.getBytes());
put.add(columnFamily, columnName, value.getBytes());
context.write(outputKey, put);
}
}
问题是Text.getBytes()从后端返回实际的字节数组(参见Text),MapReduce框架重用Text对象。因此,字节数组将具有来自其保持的先前值的垃圾字符。这个改变为我解决了这个问题:
Put put = new Put(Arrays.copyOf(key.getBytes(), key.getLength()));
如果你在某个地方使用Text作为你的价值类型,它可能会做同样的事情。
答案 1 :(得分:0)
这是jdk7与jdk6问题吗?你有两种不同的jvm版本吗?
可能与Playorm用户遇到的事情有关 https://github.com/deanhiller/playorm/commit/5e6ede13477a60c2047daaf1f7a7ce55550b0289
迪安