使用spark从hbase读取数据时,关于序列化的几个问题



我想实现一个class有一个函数从hbase通过spark读取,像这样:

public abstract class QueryNode implements Serializable{
  private static final long serialVersionUID = -2961214832101500548L;
  private int id;
  private int parent;
  protected static Configuration hbaseConf;
  protected static Scan scan;
  protected static JavaSparkContext sc;
  public abstract RDDResult query();
  public int getParent() {
      return parent;
  }
  public void setParent(int parent) {
      this.parent = parent;
  }
  public int getId() {
      return id;
  }
  public void setId(int id) {
      this.id = id;
  }
  public void setScanToConf() {
     try {
          ClientProtos.Scan proto = ProtobufUtil.toScan(scan);
          String scanToString = Base64.encodeBytes(proto.toByteArray());
          hbaseConf.set(TableInputFormat.SCAN, scanToString);
      } catch (IOException e) {
        e.printStackTrace();
      }
  }}

这是一个父类,我有一些子类实现方法query()从hbase读取,但如果我设置Configuration, ScanJavaSparkContext不是静态的,我会得到一些错误:这些类没有序列化

为什么这些类必须是静态的?我有其他的方法来解决这个问题吗?呢。

您可以尝试为这些字段设置transient以避免像

这样的序列化异常

由:java.io.NotSerializableException引起:org.apache.spark.streaming.api.java.JavaStreamingContext

你对Java说你不想序列化这些字段:

  protected transient Configuration hbaseConf;
  protected transient Scan scan;
  protected transient JavaSparkContext sc;

您是否在main或任何静态方法中初始化JavaSparkContext, ConfigurationScan ?对于静态,您的字段通过所有实例共享。但这取决于你的用例是否应该使用static

但是transient的方式比static好,因为JavaSparkCOntext序列化没有意义,因为这是在驱动程序上创建的。


——编辑讨论后在评论:

java doc for newAPIHadoopRDD

public <K,V,F extends org.apache.hadoop.mapreduce.InputFormat<K,V>> JavaPairRDD<K,V> newAPIHadoopRDD(org.apache.hadoop.conf.Configuration conf,
                                                                                            Class<F> fClass,
                                                                                            Class<K> kClass,
                                                                                            Class<V> vClass)

conf -设置数据集的配置。注意:这个将将被放入Broadcast。因此,如果您计划重用此conf to create multiple RDDs,则需要确保不会修改参看。一个安全的方法是总是为一个新的文件创建一个新的文件抽样 .

广播:

广播变量允许程序员在每台机器上缓存一个只读变量,而不是在任务中附带它的副本。

所以基本上我认为在这种情况下,static是可以的(你创建hbaceConf只有一次),但如果你想避免static,你可以按照javadoc的建议,总是为新的RDD创建一个新的配置。

最新更新