电信实时数据同步踩坑记(五):Sqoop 导入 HBase,ZooKeeper 超时
实时同步搞定之后,还剩一步:把 Oracle 里的历史数据(16.7 万条)批量导入 HBase。Sqoop 是现成的工具,按理说一条命令就能搞定。结果这一跑,又卡了很久。
现象
在 hadoop1 上执行 Sqoop import 命令:
sqoop import --append \
--connect jdbc:oracle:thin:@92.16.16.61:1521:orcl \
--username send --password send \
--table TEST \
--hbase-table FK:S02 \
--hbase-row-key ID \
--column-family CF \
-m 1
命令提交后,MapReduce 作业开始运行,但一直卡在 map 0% 不动。几分钟后,控制台开始刷错误:
INFO zookeeper.ClientCnxn: Opening socket connection to server hadoop2/92.16.16.27:2181
WARN zookeeper.ClientCnxn: Session 0x0 for server null, unexpected error, closing socket connection
java.net.ConnectException: Connection refused
然后不断重试 hadoop2、hadoop3、hadoop1,循环往复。最终作业失败:
ERROR tool.ImportTool: Encountered IOException running import job:
org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=36,
exceptions: java.net.SocketTimeoutException: callTimeout=60000, callDuration=68386
排查思路
1. 确认 HBase 和 ZooKeeper 状态
用 jps 检查,HBase 进程都正常(HMaster、HRegionServer、HQuorumPeer 都在)。而且之前 GoldenGate 实时同步已经能写入数据,说明 HBase 本身是好的。
那为什么 Sqoop 连不上?仔细看日志,Sqoop 尝试连接 hadoop2:2181 和 hadoop3:2181,但只有 hadoop1 的 2181 端口是通的。之前为了简化,我把 hbase.zookeeper.quorum 改成了 hadoop1 单节点,但 Sqoop 似乎没有读取这个配置?它仍然从 HBase 的某个地方拿到了三节点的 quorum。
2. 检查 Sqoop 如何获取 ZooKeeper 地址
Sqoop 的 HBase 导入功能会从 hbase-site.xml 中读取 hbase.zookeeper.quorum。我确认 hadoop1 上的 /app/hadoop/hbase-1.2.1/conf/hbase-site.xml 中确实改成了 hadoop1。但 Sqoop 可能使用了其他路径下的配置文件(比如 /etc/hbase/conf)或者 classpath 中的旧配置。
于是我在 Sqoop 命令中显式指定 ZooKeeper 地址:
sqoop import ... --hbase-zookeeper-quorum hadoop1 --hbase-zookeeper-property-clientPort 2181
结果报错:Unrecognized argument: --hbase-zookeeper-quorum。查了一下,Sqoop 1.4.6 根本不支持这些参数(可能是更高版本才有)。这条路走不通。
3. 修改 HBase 配置并重启
既然 Sqoop 固执地要用三节点 quorum,那就让 hadoop2 和 hadoop3 上的 ZooKeeper 真正跑起来。
-
在 hadoop2 和 hadoop3 上手动启动 ZooKeeper(HBase 内置的):
ssh hadoop2 '/app/hadoop/hbase-1.2.1/bin/hbase-daemon.sh start zookeeper'
ssh hadoop3 '/app/hadoop/hbase-1.2.1/bin/hbase-daemon.sh start zookeeper'
-
检查端口:
netstat -tlnp | grep 2181,三个节点都应该有监听。 -
将
hbase-site.xml中的hbase.zookeeper.quorum改回三节点:hadoop1,hadoop2,hadoop3。 -
重启 HBase。
再次运行 Sqoop 导入,这次没有 ZooKeeper 连接错误了,但作业仍然超时——这次是 HBase 写入超时。
4. 调整超时参数
在 hbase-site.xml 中增加:
<property>
<name>hbase.client.operation.timeout</name>
<value>120000</value>
</property>
<property>
<name>hbase.rpc.timeout</name>
<value>120000</value>
</property>
并加上 --batch 参数(虽然 Sqoop 1.4.6 不支持 --batch,但可以用 -D sqoop.hbase.bulk.load.enabled=false 之类的?不过最简单的还是增加 -m 1 并使用更小的批次)。
实际上,最终解决问题的是 将导入拆分成多个小批次,而不是一次导 16 万行。例如按 ID 范围分四次导入:
sqoop import ... --where "ID <= 50000" -m 1
sqoop import ... --where "ID > 50000 AND ID <= 100000" -m 1
...
但这样太麻烦。我尝试了另一个方向:将 HBase 的 ZooKeeper session 超时调大,并增加客户端的重试次数。同时确保 MapReduce 任务的并行度不要太高(-m 1 已经是最低)。
经过多次调整,最终一次导入成功,日志显示:
INFO mapreduce.ImportJobBase: Retrieved 167783 records.
根本原因
-
Sqoop 1.4.6 对 HBase 的集成不够智能,无法自动适应单节点 ZooKeeper 配置,必须要有完整的 ZooKeeper 集群。
-
HBase 默认的 RPC 超时较短(60 秒),导入大量数据时容易超时。
-
网络或防火墙可能导致 ZooKeeper 节点间通信延迟。
方案总结
-
确保所有节点的 ZooKeeper 都正常启动,并开放 2181 端口。
-
调整 HBase 超时参数(
hbase.client.operation.timeout、hbase.rpc.timeout)。 -
使用
-m 1降低并行度,避免并发写入冲突。 -
如果仍然超时,可以拆分成多个小范围导入(按 ID 或分区键)。
历史数据导入成功后,HBase 表里终于有了 16.7 万行数据。加上实时同步的增量,Hive 查询时总数接近 16.8 万。
更多推荐


所有评论(0)