Python 批量加载时间戳敏感数据HBase

Python 批量加载时间戳敏感数据HBase,python,scala,apache-spark,hbase,Python,Scala,Apache Spark,Hbase,我们有很多历史数据需要迁移到HBase中。我们的HBase的设置是,(时间戳)版本控制是相关的,并且使用一些领域知识,我们知道不同列在什么时候可用。数据量很大,所以我想知道什么是进行批量加载的好方法。Scala或Python很好,最好是使用Spark。我已经发布了一篇文章,让您在大部分方面都能做到这一点。我将在这里复制最相关的方法: def write[TK, TF, TQ, TV]( tableName: String, ds: Dataset[(TK, Map[TF, Map[TQ,

我们有很多历史数据需要迁移到HBase中。我们的HBase的设置是,(时间戳)版本控制是相关的,并且使用一些领域知识,我们知道不同列在什么时候可用。数据量很大,所以我想知道什么是进行批量加载的好方法。Scala或Python很好,最好是使用Spark。

我已经发布了一篇文章,让您在大部分方面都能做到这一点。我将在这里复制最相关的方法:

def write[TK, TF, TQ, TV](
  tableName: String,
  ds: Dataset[(TK, Map[TF, Map[TQ, TV]])],
  batch: Int = 1000
)(implicit
  fk: TK => HBaseData,
  ff: TF => HBaseData,
  fq: TQ => HBaseData,
  fv: TV => HBaseData
): Unit = {
  ds.foreachPartition(p => {
    val hbase = HBase.getHBase
    val table = hbase.getTable(TableName.valueOf(tableName))
    val puts = ArrayBuffer[Put]()

    p.foreach(r => {
      val put = new Put(r._1)
      r._2.foreach( f => {
        f._2.foreach( q => {
          put.addColumn(f._1, q._1, q._2)
        })
      })

      puts += put
      if (puts.length >= batch) {
        table.put(puts.asJava)
        puts.clear()
      }
    })
    if (puts.nonEmpty) {
      table.put(puts.asJava)
      puts.clear()
    }
    table.close()
  })
}
需要注意的是,此方法在其默认行为中仅使用HBase时间戳,因此必须对其进行扩展,以包括提供您自己的时间戳。基本上,只需将
TV
类型设置为
Map[Long,TV]
,并添加适当的附加嵌套循环即可

hba
类型是一个
case类
,有几种隐式方法可将最常见的类型转换为
数组[字节]
,以实现高效的HBase存储

getHbase
方法确保每个分区只有一个到HBase的连接,以避免连接/断开每个记录


希望这一切都是合理的,因为我是泛型的初学者。

我在scala的spark中使用HBase做了很多工作。我有一些好的隐式和其他方法,可以让你达到90%。我将发布一个答案后,我概括了一点。感谢有用的代码。关于您的节点,“getHbase方法确保每个分区只与HBase连接一次,以避免每个记录都连接/断开连接。”--您是否有Java中实现这一点的等效方法?使用HBase Spark connector?如果仔细观察,
HBase
对象有一个私有的
选项[连接]
getHbase
方法检查是否已在
选项中创建并存储了
连接
对象,并返回该对象,否则将创建一个新对象并存储该对象。这只能在
foreachPartition
的上下文中完成,因为无法序列化实时连接以发送给执行者。在
foreachPartition
的上下文中,每个执行者都有自己的
HBase
对象副本,因此,它有自己的连接,在您迭代分区中的记录时共享。它的编写方式可以是每个执行者,而不仅仅是每个分区都有一个连接,但我对spark内部的研究还不够深入,不知道情况是否如此。我没有在Java中使用spark,也没有使用HBase spark连接器。我明白你的意思。在JavaHBase Spark连接器中,forEachPartition有它自己的连接对象从外部主程序传递给它,但是我怀疑这个连接是否真的得到了回收。也许这是一个更好的方法。我将尝试一下,看看哪种方法更可靠。谢谢