火花插入HBase缓慢

时间:2015-05-30 13:35:13

标签: hadoop apache-spark hbase rdd

我使用Spark插入HBase,但速度很慢。对于60,000条记录,需要2-3分钟。我有大约1000万条记录要保存。

package com.ggl.testing;

import java.awt.Color;
import java.awt.Shape;

public class MyShape {

    private int brushSize;

    private Color interiorColor;

    private Shape shape;

    public MyShape() {
        this.brushSize = 1;
        this.interiorColor = Color.blue;
    }

    public MyShape(int brushSize, Color interiorColor, Shape shape) {
        this.brushSize = brushSize;
        this.interiorColor = interiorColor;
        this.shape = shape;
    }

    public int getBrushSize() {
        return brushSize;
    }

    public void setBrushSize(int brushSize) {
        this.brushSize = brushSize;
    }

    public Color getInteriorColor() {
        return interiorColor;
    }

    public void setInteriorColor(Color interiorColor) {
        this.interiorColor = interiorColor;
    }

    public Shape getShape() {
        return shape;
    }

    public void setShape(Shape shape) {
        this.shape = shape;
    }

}

我在spark-submit中使用它:

object WriteToHbase extends Serializable {
    def main(args: Array[String]) {
        val csvRows: RDD[Array[String] = ...
        val dateFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
        val usersRDD = csvRows.map(row => {
            new UserTable(row(0), row(1), row(2), row(9), row(10), row(11))
        })
        processUsers(sc: SparkContext, usersRDD, dateFormatter)
    })
}

def processUsers(sc: SparkContext, usersRDD: RDD[UserTable], dateFormatter: DateTimeFormatter): Unit = {

    usersRDD.foreachPartition(part => {
        val conf = HBaseConfiguration.create()
        val table = new HTable(conf, tablename)

        part.foreach(userRow => {
            val id = userRow.id
            val name = userRow.name
            val date1 = dateFormatter.parseDateTime(userRow.date1)
            val hRow = new Put(Bytes.toBytes(id))
            hRow.add(cf, q, Bytes.toBytes(date1))
            hRow.add(cf, q, Bytes.toBytes(name))
            ...
            table.put(hRow)
        })
        table.flushCommits()
        table.close()
    })
}

3 个答案:

答案 0 :(得分:3)

它很慢,因为实施并没有利用数据的接近程度;服务器中的Spark RDD可以传输到另一台服务器上运行的HBase RegionServer。

目前没有Spark的RRD操作以高效的方式使用HBase数据存储。

答案 1 :(得分:0)

在Htable中有一个批处理api,你可以尝试发送put请求为100-500 put包。我认为它可以加快你的速度。它返回每个操作的单个结果,因此您可以根据需要检查失败的放置。

public void batch(List<? extends Row> actions, Object[] results)

https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/HTable.html#batch%28java.util.List,%20java.lang.Object[]%29

答案 2 :(得分:0)

您必须查看可以分发您的传入数据到 Spark 作业的方法。在您当前的 foreachPartition 方法中,您必须查看map,mapToPair等转换。您需要评估整个 DAG生命周期以及可以节省更多时间的地方。

之后基于Parallelism实现,您可以调用 saveAsNewAPIHadoopDataset Spark的操作,以更快速和并行地写入HBase内部。像:

JavaPairRDD<ImmutableBytesWritable, Put> yourFinalRDD = yourRDD.<SparkTransformation>{()};    
yourFinalRDD.saveAsNewAPIHadoopDataset(yourHBaseConfiguration); 

注意: yourHBaseConfiguration 将是单例,并且将成为Executor节点上的单个对象,以便在任务之间共享

如果这个伪代码对您不起作用或者发现任何困难,请告诉我。