Apache Spark中的密钥使用不同的Reducers

时间:2016-08-25 02:11:24

标签: java apache-spark distributed

我遇到了一个大规模的数据处理问题,我试图用Java中的Apache Spark解决这个问题。我的输入是一组相对较小的自定义Java对象。

我的地图步骤会对每个对象执行一些小的更改。完成后,它会识别对象所属的一个或多个等价类。结合起来,可能有数十亿个等价类/对象对。

我的问题是我需要对每个等价类的元素执行不同的操作。这个项目需要支持插件架构,所以我不知道等价类是什么,或者每个类需要发生的不同操作。

我的直觉是使用以下内容:

//Get the input set.
JavaRDD<MyType> input = ... //Not important

//Transform the input into (Equivalence Class, MyType) pairs, 
//using strings to store the equivalence class.
JavaPairRDD<String, MyType> classedInput = input.flatMapToPair(

    new PairFlatMapFunction<MyType, String, MyType>() {

        Iterator<Tuple2<String, MyType>> call(MyType arg) {

            List<Tuple2<String, MyType>> out = new ArrayList<>();

            //Compute equivalence classes for arg.
            for(String eqClz: getEquivalenceClasses(arg)) {
                out.add(new Tuple2<String, MyType>(equClz, arg));
            }

            return out.iterator();
        }
});

//Collapse the results for each equivalence class.
JavaPairRDD<String, MyType> output = classedInput.reduceByKey(

    new Function2<MyType, MyType, MyType>() {

        MyType call(MyType a, MyType b) {
            String eqClz = ??? //<= Problem
            List<MyModule> modules = MyFramework.getModulesForEqClz(eqClz);
            for(MyModule m: modules) {
               a = m.merge(a, b);
            }
            return a;
        }
    }

);

我希望能够将等价类传递给reduceByKey的函数,以便使用它来确定需要调用哪些模块。问题是我找不到Spark的键控合成器函数,而是将密钥传递给它们的回调函数。

由于classedInput的大小,我想避免使用MyType对象保存密钥,或者在地图后添加太多额外的分布式操作。

是否有一种类似Spark的方式来实现我尝试的目标?

1 个答案:

答案 0 :(得分:0)

看来你的问题与"secondary sort"问题相反。我认为它可以通过逆解来解决(见下面的2)。

  1. 一种方法是使用reduce函数(或更完整的版本,aggregate),只需要一个关联操作即可汇总数据结果,无论密钥如何。但是,在同一等价类中表达对项目分组的详细信息可能会有点复杂。
  2. 保持对与项匹配的等价类的引用的简单方法是简单地重复值中的等价类:
  3. Tuple2<String, MyType> outValue = new Tuple2<String, MyType>(eqClz, arg); out.add(new Tuple2<String, Tuple2<String, MyType>>(equClz, outValue));

    如果您在评论中提到,当您传输数据时,您担心随机播放的大小,那么您想要限制的是用作键控结构的表示的大小。我的意思是,重复上面建议的值中的键会导致equClz变量的两个副本。但是如果是十几个字节,那么你要减小其大小的那个是关键位置的副本。为此,您可能希望选择正确长度的非加密哈希。

    你提到每个记录多十几个字节会导致数十亿字节的数据,这意味着你最多有几亿条记录,因此最多只有几亿“equClz”值。这很容易被32位非加密哈希覆盖(你很容易找到这些哈希的实现,Murmur3,XXHash)。由于32位是4个字节,因此它应该将传输开销减少至少一个数量级。