我想实现一个class
有一个函数,可以通过spark读取hbase,如下所示:
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();
}
}}
这是一个父类,我有一些子类实现了从hbase读取的menthod query()
,但如果我设置Configuration
,Scan
和JavaSparkContext
不是静态的,我会收到一些错误:这些类没有序列化。
为什么这些类必须是静态的?我有其他方法可以解决这个问题吗? THKS。
答案 0 :(得分:0)
您可以尝试为这些字段设置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
,Configuration
和Scan
吗?使用静态,您的字段将在所有实例中共享。但是,如果应该使用static
,则取决于您的使用情况。
但是使用transient
方式,它优于static
,因为JavaSparkCOntext
的序列化没有意义,因为这是在驱动程序上创建的。
- 在评论讨论后编辑 :
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
- 用于设置数据集的配置。注意:这个会 被放入广播。因此,如果您打算重复使用此conf to create multiple RDDs
,则需要确保不会修改 CONF 即可。一种安全的方法是始终为新的创建新的conf RDD 强>
广播:
广播变量允许程序员在每台计算机上保留只读变量缓存 ,而不是随副本一起发送它的副本。
所以基本上我认为对于那种情况static
是可以的(你只创建一次hbaceConf),但是如果你想避免static
,你可以按照javadoc中的建议来总是为了一个新的conf而烦恼一个新的RDD。