在不同版本hdfs集群之间转移数据
本文仅供记录一下程序心得:
很多人会有这样一个需求:将一个hdfs集群上的数据写入另一个hdfs集群所在的hbase数据库。通常情况下两个hdfs集群的版本差距并不大,这样的程序会很容易写。但有时会跨大版本。比如作者所在的厂子,数据都在基于hadoop0.19.2版本修改的hdfs集群上,要将这样的数据导入版本为0.20.2+的hdfs集群,就不能使用同一个hadoop jar包来完成了。如何实现呢?
最简单的办法就是把src集群的数据导到本地,然后起另一个进程将本地数据传到des集群上去。
不过这有几个问题:
效率降低 占用本地磁盘空间 不能应付实时导数据需求 两个进程需要协调,复杂度增加
更好的办法是在同一个进程内一边读src数据,一边写des集群。不过这相当于在同一个进程空间内加载两个版本的hadoop jar包,这就需要在程序中使用两个classloader来实现。
以下代码可以实现classloader加载自定义的jar包,并生成需要的Configuration对象:
HBaseProxy.javapublic HBaseProxy(String hbase_conf, String tableName, boolean autoflush) throws IOException{Configuration conf = new Configuration();conf.addResource(new Path(hbase_conf));config = new Configuration(conf);htable = new HTable(config, tableName);admin = new HBaseAdmin(config);htable.setAutoFlush(autoflush);}public void addPut(String field, String column, String encode) throws IOException { try {p.add(column.split(":")[0].getBytes(), column.split(":")[1].getBytes(),field.getBytes(encode));} catch (UnsupportedEncodingException e) {p.add(column.split(":")[0].getBytes(), column.split(":")[1].getBytes(),field.getBytes());}} public void generatePut(String rowkey){p = new Put(rowkey.getBytes());} public void putLine() throws IOException{htable.put(p);}总之,在同一个进程中加载多个classloader时一定要注意,classloader A所加载的对象是不能转换成classloader B的对象的,当然也不能使用。两个空间的相互调用只能用java的基本类型或是反射。 1 楼 fakechris 2011-10-27 hadoop distcp hftp://from hdfs://to 也可以 2 楼 lc_koven 2011-10-27 fakechris 写道hadoop distcp hftp://from hdfs://to 也可以
恩,很多情况下这也是一个选择,我忘写上去了:)。不过这个方法有三个弱点:1 对于自己修改的版本通常不能使用(比如cloudrea版本hdfs无法读入ugi密码等问题)。这是让我们放弃这个方法的主要原因 2 hftp安全性问题 3 不灵活,必须拷贝完成后再做一次数据导入