hbase没有提供重命名表的API,无意中发现0.90.4版本有类似的jruby脚本,无聊之下搞了个java重命名表的类:
package com.cuirong.hbase.rtc;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.Permission;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.FSUtils;
import org.apache.hadoop.hbase.util.Writables;
public class RenameHBaseTable {
/**
* author:cuirong
*/
static Configuration c ;
static FileSystem fs;
static {
c = HBaseConfiguration.create();
c.set("hbase.zookeeper.quorum", "vmdev40");
c.set("hbase.rootdir","/hbase/");
c.set("fs.default.name", "hdfs://vmdev40:54310");
try {
fs = FileSystem.get(c);
System.out.println(fs);
} catch (IOException e) {
e.printStackTrace();
}
}
public void renames(String oldTableName,String newTableName) throws Exception{
Path rootdir = FSUtils.getRootDir(c);
//Path rootdir = new Path("/hbase/");
System.out.println(rootdir);
Path oldTableDir = fs.makeQualified(new Path(rootdir, new Path(oldTableName)));
System.out.println(oldTableDir);
isDirExists(fs, oldTableDir);
Path newTableDir = fs.makeQualified(new Path(rootdir, newTableName));
if (!fs.exists(newTableDir))
fs.mkdirs(newTableDir);
HTable metaTable = new HTable(c, HConstants.META_TABLE_NAME);
Scan scan = new Scan();
ResultScanner scanner = metaTable.getScanner(scan);
//scanner.next();
for( Result result : scanner){
String rowid = Bytes.toString(result.getRow());
HRegionInfo oldHRI = Writables.getHRegionInfo(result.getValue(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER));
//System.out.println(oldHRI.getTableDesc() +"===" +oldTableName);
//if(oldHRI.getTableDesc() == null){continue;}
boolean b = isTableRegion(oldTableName.getBytes(), oldHRI);
//System.out.println(b);
if(!b){
continue;
}
System.out.println(oldHRI.toString());
Path oldRDir = new Path(oldTableDir, new Path(oldHRI.getEncodedName()));
//make a new HRegionInfo to add to .META. for the new region.
HRegionInfo newHRI = createHRI(newTableName, oldHRI,oldTableName);
System.out.println(newHRI);
Path newRDir = new Path(newTableDir, new Path(newHRI.getEncodedName()));
//Move the region in filesystem
System.out.println("Renaming " + oldRDir.toString() + " as " + newRDir.toString());
fs.rename(oldRDir, newRDir);
//Removing old region from meta
System.out.println("Removing " + rowid + " from .META.");
Delete d = new Delete(result.getRow());
metaTable.delete(d);
// Create new region
HRegion newR = new HRegion(newTableDir, null, fs, c, newHRI, null,null);
// Add new row
System.out.println("Adding to meta: " + newR.toString());
byte [] bytes = Writables.getBytes(newR.getRegionInfo());
Put p = new Put(newR.getRegionName());
p.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, bytes);
metaTable.put(p);
// Finally update the .regioninfo under new region location so it has new name.
Path regioninfofile = new Path(newR.getRegionDir(), HRegion.REGIONINFO_FILE);
fs.delete(regioninfofile, true);
DataOutputStream out = fs.create(regioninfofile);
newR.getRegionInfo().write(out);
out.close();
}
scanner.close();
fs.delete(oldTableDir);
System.out.println("success");
}
private HRegionInfo createHRI(String tableName, HRegionInfo oldHRI,String table) {
HTableDescriptor htd = new HTableDescriptor(table);
System.out.println(htd);
HTableDescriptor newHtd = new HTableDescriptor(tableName);
for (HColumnDescriptor family : htd.getFamilies())
newHtd.addFamily(family);
return new HRegionInfo(tableName.getBytes(), oldHRI.getStartKey(), oldHRI.getEndKey(),oldHRI.isSplit());
}
private boolean isTableRegion(byte[] tableName, HRegionInfo oldHRI) {
return Bytes.equals(oldHRI.getTableName(), tableName);
}
private void isDirExists(FileSystem fs2, Path oldTableDir) throws IOException {
if(!fs2.exists(oldTableDir) || !fs2.isDirectory(oldTableDir)){
System.out.println("要重命名的表不存在!");
return;
}
}
public static void main(String[] args) throws Exception {
String oldTableName = "cuirong5";
String newTableName = "cuirong6";
new RenameHBaseTable().renames(oldTableName, newTableName);
}
}
还是有点问题,不过思路大概如此。