HBase表管理系统

1. 软件版本 & 部署:

maven:3.3.9,jdk:1.7 ,Struts2:2.3.24.1,Hibernate:4.3.6,Spring:4.2.5,MySQL:5.1.34,Junit:4,Myeclipse:2014;

Hadoop2.6.4,HBase1.1.2

源码下载:https://github.com/fansy1990/ssh_v3/releases

部署参考:http://blog.csdn.net/fansy1990/article/details/51356583

2. 系统功能及核心实现

2.1系统菜单

HBase表管理系统主要是对表以及表数据的相关操作;

2.2 表管理

直接打开Table管理界面,即可看到所有表的简要信息,包括数据库(namspace)、表名、简单表描述等;

这个查询的信息直接基于Admin的listTableNames方法,具体调用如下:

/**
	 * 获取所有表
	 *
	 * @return
	 * @throws IOException
	 */
	public List<HBaseTable> getTables() throws IOException {
		List<HBaseTable> list = new ArrayList<>();
		Admin admin = HadoopUtils.getHBaseConnection().getAdmin();
		TableName[] tables = admin.listTableNames();
		HBaseTable hTable = null;

		for (TableName t : tables) {
			hTable = new HBaseTable();
			hTable.setNameSpace(t.getNamespaceAsString());
			hTable.setTableName(t.getNameAsString());
			// HTableDescriptor htableDes = admin.getTableDescriptor(t);
			// System.out.println(htableDes.toString());
			// System.out.println(htableDes.toStringTableAttributes());
			// System.out.println(htableDes.getFamilies().toString());
			// System.out.println(htableDes.toStringCustomizedValues());
			hTable.setDescription(admin.getTableDescriptor(t)
					.toStringCustomizedValues());
			setRegions(hTable, admin.getTableRegions(t));
			list.add(hTable);
		}

		return list;
	}

2.2.1 表详细

表详细功能需要先选定一行记录,否则会提示:

选择一个记录后,点击表详细即可弹出表详细信息:

后台实现通过admin.getTableDescriptor即可获得表的详细信息,但是需要提供表名,表名可以从前天传入即可,如下:

/**
	 * 获取指定表详细信息
	 *
	 * @param tableName
	 * @return
	 * @throws IOException
	 */
	public String getTableDetails(String tableName) throws IOException {
		Admin admin = HadoopUtils.getHBaseConnection().getAdmin();
		HTableDescriptor tableDescriptors = admin
				.getTableDescriptor(getTableName(tableName));
		System.out.println(tableDescriptors.toStringCustomizedValues());
		System.out.println(tableDescriptors.toString());
		return admin.getTableDescriptor(getTableName(tableName)).toString();
	}

2.2.2 表新增

表新增功能只是提供一个简单的新增,即只提供表名、列簇名即可,如下:

同时提交后台后,如果表已经存在则会进行对应的提示,后台通过遍历所有表名实现此功能,效率不高,实现如下:

public boolean checkTableExists(String tableName) throws IOException {
		Admin admin = HadoopUtils.getHBaseConnection().getAdmin();
		TableName[] tables = admin.listTableNames();
		for (TableName t : tables) {
			if (t.getNameAsString().equals(tableName)) {
				return true;
			}
		}
		return false;
	}

新增表,通过admin的createTable实现:

public boolean saveTable(String tableName, String cfs) throws IOException {
		Admin admin = HadoopUtils.getHBaseConnection().getAdmin();
		HTableDescriptor hTableDescriptor = new HTableDescriptor(
				getTableName(tableName));
		String[] cfsArr = StringUtils.split(cfs, Utils.COMMA);
		for (String cf : cfsArr) {
			hTableDescriptor.addFamily(new HColumnDescriptor(cf));
		}
		admin.createTable(hTableDescriptor);
		return true;
	}

2.2.3 表删除

表删除,同样需要选择一条记录,如果没有选择记录,同样会提示选择表,选择表后,点击删除,会进行下面的提示:

如果点击OK,则删除,Cancel则取消;

删除实现,同样使用Admin的disableTable, deleteTable方法

public boolean deleteTable(String tableName) throws IOException {
		Admin admin = HadoopUtils.getHBaseConnection().getAdmin();
		admin.disableTable(getTableName(tableName));
		admin.deleteTable(getTableName(tableName));
		return true;
	}

备注: 这里应该先判断此表是否是enable状态,如果不是则直接删除;如果是disable状态,则执行上述代码会有问题;

2.3 表数据管理

在打开表数据管理页面后,会初始化表名的下拉框,下拉框中数据的获取采用AJax的方式访问后台获取,方法同样使用Admin的listTableNames方法;

在选择一个表后,会初始化列簇名下拉框数据和start rowkey ,如下:

在查询数据时,可以选择多个列簇名,同时可以修改Start rowkey ,选择记录数以及版本数;

根据表名获取列簇名后台代码实现如下(通过HTableDescriptor的getColumnFamilies方法获取):

public List<TextValue> getTablesColumnFamily(String tableName)
			throws IOException {
		List<TextValue> list = new ArrayList<>();
		Admin admin = HadoopUtils.getHBaseConnection().getAdmin();
		HTableDescriptor tableDescriptor = admin
				.getTableDescriptor(getTableName(tableName));
		HColumnDescriptor[] columnDescriptors = tableDescriptor
				.getColumnFamilies();
		for (HColumnDescriptor t : columnDescriptors) {
			list.add(new TextValue(t.getNameAsString()));
		}
		return list;
	}

以及start rowKey的后台代码如下(即,只读取第一行数据,然后返回其rowkey):

public String getTableRowKey(String tableName) throws IOException {
		Table table = HadoopUtils.getHBaseConnection().getTable(
				getTableName(tableName));
		Scan scan = new Scan();
		ResultScanner scanner = table.getScanner(scan);
		Result firstRow = scanner.next();
		scanner.close();
		table.close();
		if (firstRow == null)
			return "-1";

		return new String(firstRow.getRow());
	}

根据表名、列簇名、start rowkey、版本数、记录数,获取数据的后台代码如下:

public List<HBaseTableData> getTableData(String tableName, String cfs,
			String startRowKey, int limit, int versions) throws IOException {
		List<HBaseTableData> datas = new ArrayList<>();
		Table table = HadoopUtils.getHBaseConnection().getTable(
				getTableName(tableName));
		Scan scan = new Scan();
		scan.setMaxVersions(versions);
		if (startRowKey != "-1") {
			scan.setStartRow(startRowKey.getBytes());
		}
		String[] cfsArr = cfs.split(Utils.COMMA, -1);
		for (String cf : cfsArr) {
			scan.addFamily(cf.getBytes());
		}

		ResultScanner scanner = table.getScanner(scan);

		Result[] rows = scanner.next(limit);

		for (Result row : rows) {
			// Cell[] cells = row.rawCells();

			datas.addAll(getFromCells(row.rawCells()));
		}

		scanner.close();
		table.close();
		return datas;
	}

通过设置Scan的maxVersions以及startRow 来限定版本数和开始遍历位置,通过设置scanner.next来限定获取的记录数;

3.1 新增

数据新增,通过指定表名、列簇名即可,如果列簇名指定多个,会提示错误:

数据新增使用window弹出框,为了把表名和列簇名传递到该window,使用了url加参数的方法(比较别扭的方式),具体如下:

var win_table_add_data_ = $(‘#win_table_add_data‘).window({
	    width:450,
	    height:350,
	    modal:true,
	    left:400,
	    top:150,
	    title:‘数据新增‘,
	    collapsible:false,
	    minimizable:false,
	    maximizable:false,
//	    content: ‘<div style="padding:30px 20px 10px 20px;">‘ + "a" +‘</div>‘
	    content: ‘<iframe id="tabIframe" src="hbaseCommand/data_add.jsp?tableName=‘+tableName_+‘&cf=‘+cf_+
	    	‘" frameborder="0" style="border:0;width:100%;height:100%;">‘,
//	    href:"hbaseCommand/data_add.jsp",
	    onOpen:function(){
	    	// 修改对应的值;
//	    	$(‘#data_add_ff_tableName‘).val(getFakeData(‘cc_data_retrieve_tableName‘));
//	    	$(‘#data_add_ff_family‘).val(cf_);
//	    	$(‘#data_add_ff_family‘).textbox(‘setValue‘,cf_);  

	    }

	});

在弹出框中,用户可以输入rowkey,column,vlaue :

表名、列簇名不可编辑,用户点击添加后,直接put数据到表中;

public boolean saveTableData(String tableName, String cfs, String rowkey,
			String column, String value) throws IOException {
		Table table = HadoopUtils.getHBaseConnection().getTable(
				getTableName(tableName));
		Put put = new Put(Bytes.toBytes(rowkey));
		put.addColumn(Bytes.toBytes(cfs), Bytes.toBytes(column),
				Bytes.toBytes(value));

		table.put(put);
		table.close();
		return true;
	}

3.3.2数据删除

直接根据提供的数据使用checkAndDelete进行删除,防止在删除的时候数据被修改:

public boolean deleteTableData(String tableName, String family,
			String qualifier, String rowkey, String value, long timestamp)
			throws IOException {
		Table table = HadoopUtils.getHBaseConnection().getTable(
				getTableName(tableName));
		Delete delete = new Delete(Bytes.toBytes(rowkey));
		delete.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier),
				timestamp);
		boolean flag = table.checkAndDelete(Bytes.toBytes(rowkey),
				Bytes.toBytes(family), Bytes.toBytes(qualifier),
				Bytes.toBytes(value), delete);

		table.close();

		return flag;
	}

3.3.3 数据更新

数据更新,同样需要选择一条记录,弹出框的方式类似数据新增(比较别扭的方式),不过可修改的内容只有值而已:

除了值之外,其他输入框都是只读的;后台实现,同样使用checkAndPut 方法:

public boolean updateTableData(String tableName, String cfs, String rowkey,
			String column, String value, long timestamp, String oldValue)
			throws IOException {
		Table table = HadoopUtils.getHBaseConnection().getTable(
				getTableName(tableName));
		Put put = new Put(Bytes.toBytes(rowkey));
		put.addColumn(Bytes.toBytes(cfs), Bytes.toBytes(column), timestamp,
				Bytes.toBytes(value));

		table.checkAndPut(Bytes.toBytes(rowkey), Bytes.toBytes(cfs),
				Bytes.toBytes(column), Bytes.toBytes(oldValue), put);
		table.close();
		return true;
	}

4. 总结

1)HBase的相关API的使用不是很难,主要是如果是插入或者更新操作,需要保持记录前后一致,需要进行row lock,这时就需要用到checkAndXxx 操作了,具体可以参考:http://blog.csdn.net/fansy1990/article/details/51451583

2) 数据新增和数据更新弹出框的方式比较别扭,可以考虑使用新的方式(因为要进行参数的传递);

分享,成长,快乐

脚踏实地,专注

转载请注明blog地址:http://blog.csdn.net/fansy1990

时间: 2024-11-05 12:26:59

HBase表管理系统的相关文章

使用MapReduce查询Hbase表指定列簇的全部数据输入到HDFS(一)

package com.bank.service; import java.io.IOException; import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.conf.Configured;import org.apache.hadoop.fs.Path;import org.apache.hadoop.hbase.HBaseConfiguration;import org.apache.hadoop.hba

HBase表数据导出和导入

本文不是技术收集贴,就是记录一下,因此没有收集所有的HBase表导入导出方式,只是记录一下自己用过的一种. 数据表的导出: 1 $ bin/hbase org.apache.hadoop.hbase.mapreduce.Driver export <tablename> <outputdir> [<versions> [<starttime> [<endtime>]]] 需要注意的是,outputdir指的是HDFS上的路径,建议使用绝对路径(没

HBase表设计

1.Column Family 由于Hbase是一个面向列族的存储器,调优和存储都是在列族这个层次上进行的,最好使列族成员都有相同的"访问模式(access pattern)"和大小特征. 在一张表里不要定义太多的column family.目前Hbase并不能很好的处理超过2~3个column family的表.因为某个column family在flush的时候,它邻近的column family也会因关联效应被触发flush,最终导致系统产生更多的I/O. 2.Row Key 1

利用BulkLoad导入Hbase表

1.插入HBase表传统方法具有什么问题? 我们先看下 HBase 的写流程: 通常 MapReduce 在写HBase时使用的是TableOutputFormat方式,在map/reduce中直接生成put对象写入HBase,该方式在大量数据写入时效率低下,因为HBase会block写入,频繁进行flush.split.compact等大量IO操作,这样对HBase节点的稳定性也会造成一定的影响,例如GC时间过长,响应变慢,导致节点超时退出,并引起一系列连锁反应,而HBase支持BulkLoa

HBase表的备份

HBase表备份其实就是先将Table导出,再导入两个过程. 导出过程 //hbase org.apache.hadoop.hbase.mapreduce.Driver export 表名 数据文件位置//数据文件位置:可以是本地文件目录,也可以是hdfs路径//当其为前者时,必须加上前缀file:////当其为后者时,可以直接指定 "/root/test/users",也可以写路径 "hdfs://hadoop01:9000/root/test/users"//另

mapreduce 只使用Mapper往多个hbase表中写数据

只使用Mapper不使用reduce会大大减少mapreduce程序的运行时间. 有时候程序会往多张hbase表写数据. 所以有如题的需求. 下面给出的代码,不是可以运行的代码,只是展示driver中需要进行的必要项设置,mapper类需要实现的接口,map函数需要的参数以及函数内部的处理方式. 实现过程比较曲折,只贴代码: class Qos2HbaseDriver extends Configured implements Tool { private static Logger logge

hadoop执行hdfs文件到hbase表插入操作(xjl456852原创)

本例中需要将hdfs上的文本文件,解析后插入到hbase的表中. 本例用到的hadoop版本2.7.2 hbase版本1.2.2 hbase的表如下: create 'ns2:user', 'info' hdfs上的文本文件如下[data/hbase_input/hbase.txt] 1,xiejl,20 2,haha,30 3,liudehua,40 4,daoming,41 可以通过命令查看hadoop的classpath现在包含哪些jar包: [[email protected] ~]$

数据分页处理系列之二:HBase表数据分页处理

  HBase是Hadoop大数据生态技术圈中的一项关键技术,是一种用于分布式存储大数据的列式数据库,关于HBase更加详细的介绍和技术细节,朋友们可以在网络上进行搜寻,笔者本人在接下来的日子里也会写一个HBase方面的技术专题,有兴趣的朋友们可以稍微的期待一下.不过本章节的重点是介绍下HBase表数据的分页处理,其他的就不多说了. 首先说一下表数据分页中不可回避的一个指标:总记录数.在关系数据库中很容易统计出记录总数,但在HBase中,这却是一个大难题,至少在目前,朋友们根本不要奢望能够通过类

Hbase表的设计

1. 表的设计 1.1 Pre-Creating Regions 默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候,所有的HBase客户端都向这一个region写数据,直到这个region足够大了才进行切分.一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入HBase时,会按照region分区情况,在集群内做数据的负载均衡. 下面是一个例子: public static boolean createTable(HBaseAdmi