问题描述:在hbase数据库中保存了许多的图像帧数据,其中图像一行帧数据用在数据表中对应一个rowkey,需要用这许多的rowkey合成一个图像,发现很慢,和单机上合成图像有的一比;
影响:因为图像需要实时合成,合成数据的快慢直接影响了用户的体验;
之前的解决思路:在hbase中的rowkey对应的一行图像帧数据很多,需要先对其进行处理,比如去掉图像行帧数据中的格式、校验图像行等无关信息的去除。之前的解决思路是:通过spark连接hbase,扫描需要合成图像的行,将其全部读取出来转换成rdd,然后查询出来的数据parallelized操作分区,接着对rdd中数据进行map操作如数据过滤,处理完了后collect合并图像行,最后调用jar包将图像行合成图像,其中合成图像那里很快,在处理图像行帧数据时很慢,无解。
新的思路:http://www.tuicool.com/articles/6ZBnQz2,在这里似乎已经做好了。其中有一段是这样描述的:
SparkOnHBase Design : We experimented with many designs for how Spark and HBase integration should work and ended up focusing on a few goals:
Create RDDs through Scan actions or from an existing RDD which are used to generate Get commands.(通过scan和存在的rdd中生成新的rdd,用于生成get命名)为此他们看了下GraphX API in Spark的实现方式。
最终他们写了个类HBaseContext,将sparkcontext和hbase结合在一起,完美的解决了sparkrdd 与hbase相结合的问题。
看段代码:
//造点数据,这些数据就认为是数据表中的rowkey吧
val rdd = sc.parallelize(Array(
(Bytes.toBytes("1")),
…
(Bytes.toBytes("6")),
(Bytes.toBytes("7"))))
//创建HBaseContext
val conf = HBaseConfiguration.create()
//读取配置文件,如果将这2个xml放在该类的路径下如:resource,HBaseConfiguation默认读取,下面可以省略
conf.addResource(new Path("/etc/hbase/conf/core-site.xml"))
conf.addResource(new Path("/etc/hbase/conf/hbase-site.xml"))
val hbaseContext = new HBaseContext(sc, conf);//将sc和hbase结合在一起
//This is the method we are going to focus on
val getRdd = hbaseContext.bulkGet[Array[Byte], String](
tableName, //查询数据的表名
2, //设置批查询的大小,一般小于 1000
rdd, //RDD 用于生成记录的get
record => { //将查询记录转换成get的方法
new Get(record)
},
(result: Result) > { //这个方法用来将查询结果转换成序列的对象
val it = result.list().iterator()
val b = new StringBuilder
b.append(Bytes.toString(result.getRow()) + ":")
while (it.hasNext()) {
val kv = it.next()
val q = Bytes.toString(kv.getQualifier())
if (q.equals("counter")) {
b.append("(" + Bytes.toString(kv.getQualifier()) + "," + Bytes.toLong(kv.getValue()) + ")")
} else {
b.append("(" + Bytes.toString(kv.getQualifier()) + "," + Bytes.toString(kv.getValue()) + ")")
}
}
b.toString
}).collect
上面的getRdd就是处理好的行数据信息rdd集合了。
总结:
hbaseContext类结合了sparkrdd的特点,整合hbase表数据Region能最大性能的发挥出spark分布式多核运算的特点。回想之前思路失败的原因是,将数据从habse中查询出来后,之后对图像帧数据所做的所有操作都是在同一个分区下的map操作,或者说始终是基于父类的窄依赖suffle,导致了数据的处理并没有完全使用集群的资源。