当前位置:首页 > 问答 > 正文

高效导出Hbase海量数据,操作简单一键搞定,省时又省力

说到从Hbase里导出海量数据,很多搞技术的小伙伴第一反应可能就是头疼,数据量动不动就是几个T甚至更多,用普通的查询方法简直就是龟速,还容易把集群搞挂,网上有很多技术文章,比如CSDN博客上一些有经验的工程师会分享他们的做法,但动不动就是一大堆配置和代码,看着就让人头晕,今天咱们就聊一种相对简单、高效,而且对Hbase集群比较友好的方法,目标就是让你能“一键搞定”,这个“一键”指的是流程清晰、操作固定,不是真的就一个按钮。

最直接但也最不推荐的方法,就是直接用Hbase的Scan API写个Java程序来扫表,这种方法为什么不行呢?根据很多人的实践经验,比如知乎上一些用户提到的,当数据量巨大时,这种单线程或者简单多线程的扫描,速度慢得像蜗牛不说,还会给Hbase的RegionServer带来巨大的压力,容易引发GC(垃圾回收)问题,可能你数据没扫多少,反而把线上服务给拖慢了,这可是要出事故的,对于海量数据导出,我们必须换一种思路。

有没有什么“神器”呢?其实Hbase生态里已经给我们准备好了工具,关键是要用对,这里就要提到MapReduce这个老牌分布式计算框架了,听到MapReduce你可能觉得有点专业,但别怕,我们不需要自己从头写复杂的Map和Reduce函数,Hbase很贴心地提供了一个现成的工具类,叫做TableSnapshotInputFormat,这个方法是目前公认的导出海量数据的最佳实践之一,在很多技术社区,如开源中国社区里的讨论中都被强烈推荐。

这个方法妙在哪里呢?它核心是利用了Hbase的快照(Snapshot)功能,快照你可以理解为给表的数据拍一张瞬间的照片,这个操作非常快,几乎是瞬间完成的,因为它不直接拷贝数据文件,而是记录下当前数据的一个元数据状态,拍了快照之后,我们再启动一个MapReduce作业,这个作业不是直接去读正在线上服务的Hbase表,而是去读我们刚刚拍好的那个快照,这样做有几个天大的好处:

高效导出Hbase海量数据,操作简单一键搞定,省时又省力

第一,对线上业务影响极小,因为导数据的过程和真实的Hbase服务分离开了,不会和正常的读写请求抢资源,不会引起RegionServer的抖动,这就像是给高速公路修了一条辅路,大货车(数据导出作业)走辅路,不影响主路上的小轿车(线上业务)飞驰。

第二,效率非常高,MapReduce是分布式运行的,它可以启动很多个任务(Map Task),每个任务并行地读取快照中不同Region的数据,你集群的节点越多,并行度就可以越高,导出速度自然就上去了,这比单线程扫描不知道快了多少个数量级。

高效导出Hbase海量数据,操作简单一键搞定,省时又省力

第三,操作相对固定和简单,我们不需要关心复杂的Hbase API调用细节,整个流程可以固化成一个脚本,大致步骤就是:

  1. 在Hbase shell里或者用API,给要导出的表创建一个快照(命令很简单:snapshot '你的表名', '快照名称')。
  2. 编写一个简单的MapReduce驱动类,其实Hbase自带的export工具经过配置也能支持快照模式,或者参考GitHub上一些现成的例子写一个简单的Job。
  3. 配置这个Job使用TableSnapshotInputFormat,并指定快照名称、输出路径等参数。
  4. 提交Job到Hadoop集群运行。

整个过程可以写成一个shell脚本,把表名、快照名、输出路径作为参数传进去,以后每次需要导出,基本上就是执行一下这个脚本,修改几个参数就行了,非常符合“操作简单一键搞定”的期望。

数据导出的格式也很灵活,你可以选择导出成HDFS上的序列化文件(SequenceFile),或者更通用的格式比如AVRO,方便后续被其他系统(比如Spark、Hive)使用,根据IBM Developerworks上的一些技术文档建议,使用AVRO格式在数据序列化和后续处理方面会有更好的兼容性和性能。

这种方法也需要一些前提条件,比如你的Hbase集群必须开启了快照功能,并且你有权限操作Hadoop和Hbase,相比于其他方法,通过“快照+MapReduce”的方式来导出Hbase海量数据,在效率、稳定性和操作简便性上取得了非常好的平衡,确实是省时又省力的不二之选。