当kafka avro记录转换为Json时,Hbase插入非常慢

时间:2017-05-31 02:25:21

标签: scala hbase spark-streaming confluent

我正在使用Kafka 10并从DB2 CDC接收记录。 Kafka 10使用Confluent Schema Registry存储DB2表模式,并将记录作为Avro Array[Byte]发送。我想将这些记录存储到Hbase(比如Raw Hbase),然后使用Hive对这些新记录(如删除列,聚合等)进行一些转换,并将转换后的记录再次存储到Hbase中(假设符合Hbase) )。我尝试了两种方法,两者都给了我一些问题。记录的长度很大,约有500列(尽管只有10%的列是必需的),每条记录的大小约为10kb。

1)我尝试将记录反序列化为Array[Byte],然后使用streamBulkPut方法将其插入Hbase。

反序列化代码:

def toRecord(buffer: Array[Byte]): Array[Byte] = {
var schemaRegistry: SchemaRegistryClient = null
schemaRegistry= new CachedSchemaRegistryClient(url, 10)
val bb = ByteBuffer.wrap(buffer)
bb.get() // consume MAGIC_BYTE
val schemaId = bb.getInt // consume schemaId //println(schemaId.toString)
val schema = schemaRegistry.getByID(schemaId) // consult the Schema Registry //println(schema)
val reader = new GenericDatumReader[GenericRecord](schema)
val decoder = DecoderFactory.get().binaryDecoder(buffer, bb.position(), bb.remaining(), null)
val writer = new GenericDatumWriter[GenericRecord](schema)
val baos = new ByteArrayOutputStream
val jsonEncoder = EncoderFactory.get.jsonEncoder(schema, baos)
writer.write( reader.read(null, decoder), jsonEncoder) //reader.read(null, decoder): returns Generic record
jsonEncoder.flush
baos.toByteArray
}

HBase bulkPut代码:

val messages = KafkaUtils.createDirectStream[Object,Array[Byte],KafkaAvroDecoder,DefaultDecoder](ssc, kafkaParams, topicSet)
val hconf = HBaseConfiguration.create()
val hbaseContext = new HBaseContext(ssc.sparkContext, hconf)
val tableName = "your_table"
var rowKeyArray: Array[String] = null
hbaseContext.streamBulkPut(messages,TableName.valueOf(tableName),putFunction)
def putFunction(avroRecord:Tuple2[Object,Array[Byte]]):Put = {
  implicit val formats = DefaultFormats
  val recordKey = getKeyString(parse(avroRecord._1.toString.mkString).extract[Map[String,String]].values.mkString)
  var put = new Put(Bytes.toBytes(recordKey))
  put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("row"), AvroDeserializer.toRecord(avroRecord._2))
  put
}
def getKeyString(keystr:String):String = {
(Math.abs(keystr map (_.hashCode) reduceLeft( 31 * _ + _) ) % 10 + 48).toChar + "_"  + keystr.trim
}

现在这种方法有效,但插入速度很慢。我每分钟的吞吐量达到约5k。该计划曾经是Raw Hbase中的记录我将使用Hive来阅读和爆炸json来进行转换。

2)而不是在存储到Raw Hbase时重新序列化记录,我想在从Raw-> Conformed Hbase加载时这样做(我可以管理这里的慢,因为数据已经在我身边,即kafka之外)。因此我尝试将Avro记录存储到Hbase中并且运行速度非常快,我能够在2分钟内插入150万条记录。以下是代码:

 hbaseContext.streamBulkPut(messages,TableName.valueOf(tableName),putFunction)
def putFunction(avroRecord:Tuple2[Object,Array[Byte]]):Put = {
implicit val formats = DefaultFormats
val recordKey = parse(avroRecord._1.toString.mkString).extract[Map[String,String]]
var put = new Put(Bytes.toBytes(getKeyString(recordKey.values.mkString)))
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("row"), avroRecord._2)
put
}

这种方法的问题是Hive无法从Hbase读取Avro记录,我无法过滤记录/运行任何逻辑。

我很感激我可以遵循的任何帮助或资源来提高性能。如果相应的问题得到解决,任何方法都适用于我。感谢

0 个答案:

没有答案