Hadoop 使用ImportTsv在hbase中插入数据时出现问题
我尝试使用以下命令在hbase中插入数据:Hadoop 使用ImportTsv在hbase中插入数据时出现问题,hadoop,hbase,hive,Hadoop,Hbase,Hive,我尝试使用以下命令在hbase中插入数据: hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns=HBASE_ROW_KEY,f:pageviews,f:visit -Dimporttsv.separator=\001 -Dimporttsv.bulk.output=output modelvar /000000.gz hbase org.apache.hadoop.hbase.mapreduce.Load
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns=HBASE_ROW_KEY,f:pageviews,f:visit -Dimporttsv.separator=\001 -Dimporttsv.bulk.output=output modelvar /000000.gz
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles modelvar output
其中,
modelvar
是假定存储数据的最终hbase表<代码>输出是存储Hfiles的HDFS路径。现在的问题是,我试图插入的数据是hive的输出。所以,默认的分隔符是\001
,我无法更改。因此,我将-dimportsv.separator=
值保留为\001
。但是,我们不能保留多个字符作为分隔符。那么,如何在hive
编写的hbase
中插入数据呢?在hadoop配置中不能使用byte
但是我们可以注意到org.apache.hadoop.hbase.mapreduce.importtsv.separator_CONF_键定义的属性“importtsv.separator”是org.apache.hadoop.hbase.mapreduce.importtsv:245中的Base64编码
public static Job createSubmittableJob(Configuration conf, String[] args)
throws IOException, ClassNotFoundException {
// Support non-XML supported characters
// by re-encoding the passed separator as a Base64 string.
String actualSeparator = conf.get(SEPARATOR_CONF_KEY);
if (actualSeparator != null) {
conf.set(SEPARATOR_CONF_KEY,
Base64.encodeBytes(actualSeparator.getBytes()));
}
...
}
在org.apache.hadoop.hbase.mapreduce.ImportTsv:92中解码
protected void doSetup(Context context) {
Configuration conf = context.getConfiguration();
// If a custom separator has been used,
// decode it back from Base64 encoding.
separator = conf.get(ImportTsv.SEPARATOR_CONF_KEY);
if (separator == null) {
separator = ImportTsv.DEFAULT_SEPARATOR;
} else {
separator = new String(Base64.decode(separator));
}
...
}
最后在org.apache.hadoop.hbase.mapreduce.ImportTsv:97中检查为单个字节
public TsvParser(String columnsSpecification, String separatorStr) {
// Configure separator
byte[] separator = Bytes.toBytes(separatorStr);
Preconditions.checkArgument(separator.length == 1,
"TsvParser only supports single-byte separators");
separatorByte = separator[0];
...
}
作为解决方案,我建议您重新声明一个main方法,该方法在执行之前修改配置的属性
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.mapreduce.ImportTsv;
public class ImportTsvByteSeparator extends ImportTsv
{
/**
* Main entry point.
*
* @param args The command line parameters.
* @throws Exception When running the job fails.
*/
public static void main(String[] args) throws Exception {
// We just have to modify the configuration
Configuration conf = HBaseConfiguration.create();
int byteSeparator = conf.getInt("importtsv.byte_separator", 001);
String separator = Character.toString((char) byteSeparator);
conf.set("importtsv.separator", separator);
// Now we call ImportTsv main's method
ImportTsv.main(args);
}
}
由于属性的可见性,我认为我们无法覆盖流程内部的某些方法(如createSubmittableJob())。最终找到了答案,将分隔符替换为
$(echo-e“\002”)
。这适用于所有shell命令。1。您是否尝试使用“^A”(ASCII等效于\001)作为分隔符,或者在从配置单元输出数据时将其他选项置于自定义分隔符中。