Hadoop 使用ImportTsv在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中插入数据:

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)作为分隔符,或者在从配置单元输出数据时将其他选项置于自定义分隔符中。