Spork 是 Apache Pig 在 Apache Spark 上的實驗性運行時(Pig on Spark)。將 Pig 的物理執行計劃(Physical Plan)翻譯為 Spark RDD 操作,繞過 MapReduce 階段。本文基於 flare-spork 分支分析。
對應 MR 模式的 MapReduceLauncher,核心職責:
PhysicalOperator 子類實例)POConverter 轉換為 RDD 運算Store/Dump)提交 Spark Jobpublic interface POConverter{ RDD convert(List > predecessorRdds, T physicalOperator) throws IOException; }
predecessorRdds:上游算子產生的 RDD 列表(對應物理計劃的邊)nextRDD:下游算子的輸入| Pig 物理算子 | Spark RDD 操作 | 關鍵邏輯 |
|---|---|---|
| POLoad | sc.newAPIHadoopFile → map | 讀取輸入格式,Tuple2 → Tuple |
| POStore | mapToPair → saveAsNewAPIHadoopFile | Tuple → Tuple2 寫入 |
| POForEach | mapPartitions | Iterator 轉換,復用 POForEach 內部邏輯 |
| POFilter | filter | 包裝 FilterFunction,調用 setInput/attachInput/getNextTuple |
| POLimit | filter (同 Filter) | 限制輸出條數 |
| PODistinct | distinct(numPartitions) | 映射為 (Tuple, null) → reduceByKey → 取 Key |
| POUnion | new UnionRDD | 合併多個父 RDD,JavaConversions.asScalaBuffer |
| POSort | OrderedRDDFunctions.sortByKey | Tuple → Tuple2 → RangePartitioner → 取 Key |
| POSplit | 直接返回第一個父 RDD | 分流邏輯由下游消費者處理 |
| POLocalRearrange | mapPartitions | 本地重組,輸出 (index, key, value) |
| POGlobalRearrange | groupByKey / cogroup | 單分區 groupByKey,多分區 CoGroupRDD 合併 Iterator |
| POPackage | mapPartitions | 將 (key, Seq 打包為最終輸出格式 |
// 核心:實現 Iterator=> Iterator rdd.mapPartitions(iter -> { return new Iterator () { POForEach po = (POForEach) physicalOperator; Iterator inputIter = iter; public boolean hasNext() { if (!inputIter.hasNext()) return false; Tuple t = inputIter.next(); po.setInput(t); // 設置輸入 po.attachInput(t); // 附加輸入 return po.getNextTuple() != null; } public Tuple next() { return po.getNextTuple(); // 觸發 processTuple() } }; });
關鍵:Pig 物理算子通過 setInput/attachInput 接收數據,getNextTuple 觸發處理邏輯。Converter 在 Iterator 中模擬此協議。
rdd.groupByKey() → map 取 (key, Iterator)map 為 (key, value) → new CoGroupRDD → map 合併 Iteratormerge(類似歸並)// 1. Tuple -> Tuple2rdd.map(t -> new Tuple2<>(t, null)) // 2. OrderedRDDFunctions.sortByKey(ascending, numPartitions) // 內部使用 RangePartitioner,各分區內有序,分區間按 Key 範圍分布 // 3. mapPartitions 取回 Key sorted.mapPartitions(iter -> iter.map(t2 -> t2._1))
比較器復用 POSort.mComparator,保證排序語義一致。
pig -x spark script.pig # 或 java -cp ... org.apache.pig.Main -x spark script.pig
HashPartitioner/RangePartitioner,無自定義分區優化Spork 展示了「傳統 DAG 引擎(Pig)向新一代 DAG 引擎(Spark)遷移」的典型路徑:
setInput/getNextTuple 生命週期mapPartitions/groupByKey/sortByKey雖 Spork 未成生產級,但其架構設計為理解 Pig、Spark 內核、跨引擎遷移提供了極佳案例。