HBase笔记:对HBase原理的简单理解

  早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了。现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbase原理。

  首先来点实在的东西,假如我们已经在服务器上部署好了Hbase应用,作为客户端或者说的具体点,本地开发环境如何编写程序和服务端的Hbase进行交互了?

  下面我将展示这些,首先看工程的结构图,如下图所示:

  接下来我们将hbase应用下lib文件夹里所有jar包都导入到工程lib目录下,还要把conf目录下的hbase-site.xml下载下来放置在conf目录里,这里我还将hbase项目里的log4j.properties文件放置到了项目的根目录下,这样在我们运行程序时候,控制台打印的日志也会更加的详细,下面是HBaseStudy.java的源代码:

package cn.com.hbasetest;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
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.util.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HBaseStudy {

	public final static Logger logger = LoggerFactory.getLogger(HBaseStudy.class);

	/* 构建Configuration,这里就是hbase-site.xml解析出来的对象,这里我还指定了本地读取文件的方式 */
	static Configuration hbaseConf = HBaseConfiguration.create();
	static {
		hbaseConf.addResource("conf/hbase-site.xml");
	}

	/**
	 * 插入数据
	 * @throws IOException
	 */
	public void putTableData() throws IOException {
		HTable tbl = new HTable(hbaseConf, "xsharptable001");
		Put put = new Put(Bytes.toBytes("xrow01"));
		put.add(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol01"), Bytes.toBytes("xvalue01"));
		put.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"), Bytes.toBytes("xvalue02"));
		put.addImmutable(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol03"), Bytes.toBytes("xvalue03"));

		tbl.put(put);
	}

	/**
	 * 插入多行数据
	 * @throws IOException
	 */
	public void putTableDataRow() throws IOException {
		HTable tbl = new HTable(hbaseConf, "xsharptable001");
		Put put = new Put(Bytes.toBytes("xrow02"));
		put.add(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol01"), Bytes.toBytes("xvalue012"));
		put.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"), Bytes.toBytes("xvalue022"));
		put.addImmutable(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"), Bytes.toBytes("xvalue032"));

		tbl.put(put);

		put = new Put(Bytes.toBytes("xrow03"));
		put.add(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol01"), Bytes.toBytes("xvalue0213"));
		put.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"), Bytes.toBytes("xvalue0123"));
		put.addImmutable(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol03"), Bytes.toBytes("xvalue0223"));

		tbl.put(put);

		put = new Put(Bytes.toBytes("xrow04"));
		put.add(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol01"), Bytes.toBytes("xvalue0334"));
		put.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"), Bytes.toBytes("xvalue0224"));
		put.addImmutable(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol03"), Bytes.toBytes("xvalue0334"));
		put.addImmutable(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol04"), Bytes.toBytes("xvalue0334"));
		tbl.put(put);
	}

	/**
	 * 查询hbase表里的数据
	 * @throws IOException
	 */
	public void getTableData() throws IOException {
		HTable table = new HTable(hbaseConf, "xsharptable001");
		Get get = new Get(Bytes.toBytes("xrow01"));
		get.addFamily(Bytes.toBytes("xcolfam01"));
		Result result = table.get(get);
		byte[] bs = result.getValue(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"));
		// ============查询结果:xvalue02
		logger.info("============查询结果:" + Bytes.toString(bs));

	}

	/**
	 * 创建hbase的表
	 *
	 * @throws MasterNotRunningException
	 * @throws ZooKeeperConnectionException
	 * @throws IOException
	 */
	public void createTable() throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
		HBaseAdmin admin = new HBaseAdmin(hbaseConf);
		if (admin.tableExists(Bytes.toBytes("xsharptable001"))) {
			logger.info("===============:表已经存在!failure!");
		} else {
			TableName tableName = TableName.valueOf(Bytes.toBytes("xsharptable001"));
			HTableDescriptor tableDesc = new HTableDescriptor(tableName);
			HColumnDescriptor hcol = new HColumnDescriptor(Bytes.toBytes("xcolfam01"));
			tableDesc.addFamily(hcol);
			admin.createTable(tableDesc);
			logger.info("==============:表创建成功了!Success!");
		}
	}

	/**
	 * 通过scan扫描数据,相当于关系数据的游标
	 *
	 * @throws IOException
	 */
	public void scanTableData() throws IOException {
		HTable tbl = new HTable(hbaseConf, "xsharptable001");
		Scan scanAll = new Scan();
		ResultScanner scannerAll = tbl.getScanner(scanAll);
		for (Result resAll : scannerAll) {
			/*
			 * 打印出来的结果: 2016-06-14 15:46:10,723 INFO [main]
			 * hbasetest.HBaseStudy: ======ScanAll
			 * :keyvalues={xrow01/xcolfam01:xcol01/1465885252556/Put
			 * /vlen=8/seqid=0,
			 * xrow01/xcolfam01:xcol02/1465885252556/Put/vlen=8/seqid=0,
			 * xrow01/xcolfam01:xcol03/1465885252556/Put/vlen=8/seqid=0}
			 * 2016-06-14 15:46:10,723 INFO [main] hbasetest.HBaseStudy:
			 * ======ScanAll
			 * :keyvalues={xrow02/xcolfam01:xcol01/1465887392414/Put
			 * /vlen=9/seqid=0,
			 * xrow02/xcolfam01:xcol02/1465887392414/Put/vlen=9/seqid=0}
			 * 2016-06-14 15:46:10,723 INFO [main] hbasetest.HBaseStudy:
			 * ======ScanAll
			 * :keyvalues={xrow03/xcolfam01:xcol01/1465887392428/Put
			 * /vlen=10/seqid=0,
			 * xrow03/xcolfam01:xcol02/1465887392428/Put/vlen=10/seqid=0,
			 * xrow03/xcolfam01:xcol03/1465887392428/Put/vlen=10/seqid=0}
			 * 2016-06-14 15:46:10,723 INFO [main] hbasetest.HBaseStudy:
			 * ======ScanAll
			 * :keyvalues={xrow04/xcolfam01:xcol01/1465887392432/Put
			 * /vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol02/1465887392432/Put/vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol03/1465887392432/Put/vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol04/1465887392432/Put/vlen=10/seqid=0}
			 */
			logger.info("======ScanAll:" + resAll);
		}
		scannerAll.close();

		Scan scanColFam = new Scan();
		scanColFam.addFamily(Bytes.toBytes("xcolfam01"));
		ResultScanner scannerColFam = tbl.getScanner(scanColFam);
		for (Result resColFam : scannerColFam) {
			/*
			 * 2016-06-14 15:50:54,690 INFO [main] hbasetest.HBaseStudy:
			 * ======scannerColFam
			 * :keyvalues={xrow01/xcolfam01:xcol01/1465885252556
			 * /Put/vlen=8/seqid=0,
			 * xrow01/xcolfam01:xcol02/1465885252556/Put/vlen=8/seqid=0,
			 * xrow01/xcolfam01:xcol03/1465885252556/Put/vlen=8/seqid=0}
			 * 2016-06-14 15:50:54,690 INFO [main] hbasetest.HBaseStudy:
			 * ======scannerColFam
			 * :keyvalues={xrow02/xcolfam01:xcol01/1465887392414
			 * /Put/vlen=9/seqid=0,
			 * xrow02/xcolfam01:xcol02/1465887392414/Put/vlen=9/seqid=0}
			 * 2016-06-14 15:50:54,690 INFO [main] hbasetest.HBaseStudy:
			 * ======scannerColFam
			 * :keyvalues={xrow03/xcolfam01:xcol01/1465887392428
			 * /Put/vlen=10/seqid=0,
			 * xrow03/xcolfam01:xcol02/1465887392428/Put/vlen=10/seqid=0,
			 * xrow03/xcolfam01:xcol03/1465887392428/Put/vlen=10/seqid=0}
			 * 2016-06-14 15:50:54,690 INFO [main] hbasetest.HBaseStudy:
			 * ======scannerColFam
			 * :keyvalues={xrow04/xcolfam01:xcol01/1465887392432
			 * /Put/vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol02/1465887392432/Put/vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol03/1465887392432/Put/vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol04/1465887392432/Put/vlen=10/seqid=0}
			 */
			logger.info("======scannerColFam:" + resColFam);
		}
		scannerColFam.close();

		Scan scanRow = new Scan();
		scanRow.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"))
				.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol04")).setStartRow(Bytes.toBytes("xrow03"))
				.setStopRow(Bytes.toBytes("xrow05"));
		ResultScanner scannerRow = tbl.getScanner(scanRow);
		for (Result resRow : scannerRow) {
			/*
			 * 2016-06-14 15:57:29,449 INFO [main] hbasetest.HBaseStudy:
			 * ======scannerRow
			 * :keyvalues={xrow03/xcolfam01:xcol02/1465887392428/
			 * Put/vlen=10/seqid=0} 2016-06-14 15:57:29,449 INFO [main]
			 * hbasetest.HBaseStudy:
			 * ======scannerRow:keyvalues={xrow04/xcolfam01
			 * :xcol02/1465887392432/Put/vlen=10/seqid=0,
			 * xrow04/xcolfam01:xcol04/1465887392432/Put/vlen=10/seqid=0}
			 */
			logger.info("======scannerRow:" + resRow);
		}
		scannerRow.close();
	}

	public static void main(String[] args) {
		HBaseStudy hb = new HBaseStudy();
		/*try {
			hb.createTable();
			hb.putTableData();
		} catch (Exception e) {
			e.printStackTrace();
		}*/

		try {
			// hb.getTableData();
			// hb.putTableDataRow();
			hb.scanTableData();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

  这段代码写得匆忙,示例并没有好好设计,不过代码我是测试过,完全可以正常运行,下面几站截图是我通过hbase shell查询测试结果,如下图所示:

  图一:

  这里我通过describe命令查看表的基本信息。

  图二:

  这里我使用scan命令进行全表扫描。

  图三:

  当我插入更多数据时候使用scan命令进行全表扫描。

  本篇文章不会着重讲解hbase的javaAPI,其实本实例里也只是使用了少量的API,不过在我选择的API里我想体现的是hbase里表(table),行(rowkey),列族(family)和列(column)之间的关系。

  创建表我们要先定义好表名,列族,插入数据我们首先是插入行,然后根据列族定义列接下来添加数据,这些都是按照hbase设计规范进行操作的,下面就是关键所在了:我们是如何查询数据的。

  对于查询的Get操作,我们构造Get对象时候就是使用rowkey进行,scan可以进行全表扫描,也可以根据列族查询,还可以使用rowkey的范围限定scan扫描数据的范围,不管从什么角度进行查询,我们可以总结出hbase做查询时候都会跟rowkey和列族相关,hbase的javaAPI并没有再去提供更多查询手段,因此我们可以得出在提升hbase查询效率的因素里rowkey和列族必然承担了很重要的作用。

  大数据时代的数据量是超大规模的,传统的关系数据库已经很难存储和管理这些数据了,为了存储海量数据,我们有了HDFS,它可以把成千上万台服务器上的硬盘聚集成一块超级大的硬盘,为了让这些数据产生价值,我们有了mapreduce,它可以计算这个超大硬盘的数据,面对这么大的数据量我们还有一个迫切的需求那就是如何快速检索出我们想要的数据,而这个功能就是由hbase来承担。

  那么如此海量数据快速检索技术原理又是怎样的呢?我觉得原理很简单就是索引技术。Hbase通过rowkey来区别不同类型数据,通过列族把经常需要一起被查询出来的数据放在一起,例如我们如果要做一个电商平台的交易记录业务表设计,对于电商平台下的商户他其实只需要查询出自己的交易信息,而不会去关心其他商户的交易信息,那么我们就可以把商户号作为rowkey,每一个商户的交易的信息我们就放在一个列族里,商户号这样的信息就像数据在硬盘上的门牌号,我们一传入这个值做查询,hbase就能快速找到数据存储的位置,这就是hbase能快速检索到数据的原理。

  上面讲到的原理只是业务抽象的角度来说,在hbase底层它就是根据上面说到的这些原理来设计的,hbase里面有region的概念,region是一个数据集合,那么什么样的数据会放置到某一个region里呢?hbase是根据rowkey来把同一类的数据放置在一个region里,rowkey下面就是列族,列族对应的底层存储就是hfile,hfile放置在rowkey对应的region下,所以当我们查询时候我们很容易通过业务规则找到我们设计好的rowkey,找到了rowkey就找到region,那么region下存储的hfile列族信息也就可以全部查询出来了。

  Rowkey其实就是hbase的索引,也可以说是hbase官方给出的唯一索引,因此很多资料里说hbase只有一级索引,这个一级索引就指的就是rowkey,因此如何设计rowkey就是一门大学问了,时常我们一行数据不能满足我们复杂的查询要求,我们需要跨行就像scan那么扫描多行数据,而region里的行都是按照一定顺序排列的,这个顺序就是字典顺序,这个我在以前一篇文章里提到过,所以碰到这种情况,我们一般会通过md5将key散列,这样相邻的数据行会排列在一起,底层存储数据时候也会存储在同一个地方(相同region)或者是相互靠近的地方(相邻region),这样也就可以提升查询的效率。

  Hbase内部有两张表一个是-ROOT-表和.META.表,客户端程序就是像我上面给出的示例程序首先访问zookeeper,通过zookeeper获取含有-ROOT-的region服务器名,通过-ROOT-的region服务器可以查询到.META.表里行键rowkey对应的region位置,而-ROOT-和.META.客户端访问后就会缓存起来。

  其实hbase的表设计本身非常简单,对外接口也没有关系数据库那么丰富,我最近学习hbase,觉得hbase基本都没有关系数据库里那些计算函数,可见hbase只是提供一种能快速检索海量数据的一种计算模型而已。

  本文就到此为止了,好记性不如烂笔头,写写文章是对自己学习的总结,也是留一个备忘和将来的遗忘做斗争了。

时间: 2024-10-13 12:34:04

HBase笔记:对HBase原理的简单理解的相关文章

[转帖]mDNS原理的简单理解

mDNS原理的简单理解 https://binkery.com/archives/318.html 发现还有avahi-daemon mdns 设置ip地址 等等事项 网络部分 自己学习的还是不够多 ,需要加强学习. Android,Java,DNS,局域网,mDNS,组播,Java mDNS,Multicast DNS,mDNS原理,mDNS组播 2016-03-21 08:53:39 mDNS , multicast DNS, 可以理解为局域网内部的 DNS 系统,它和 DNS 有很多相似的

mDNS原理的简单理解

http://www.binkery.com/archives/318.html mDNS : multicast DNS ,规范文档地址: http://www.ietf.org/rfc/rfc6762.txt.转载请注明来自:http://www.binkery.com/ 在局域网内,你要通过一台主机和其他主机进行通信,你需要知道对方的 ip 地址,但是有些时候,你并不知道对方的 ip 地址,因为一般使用 DHCP 动态分配 ip 地址的局域网内,各个主机的 IP 地址是由 DHCP 服务器

HBase笔记整理(一)

[TOC] HBase笔记整理(一) 行列式数据库 行式数据库: 可以简单的理解为类似传统的rdbmspaint这些数据,存放的数据都是结构化的数据. 行式数据库,是有利于全表数据的扫描,不利于只查询个别字段 列式数据库: 对行式数据库的一个改进,将部分列(或者说有关联的一些列)存放到单独的文件中,其他列存在其它多个文件中, 我们在进行查询的时候,只需要读取出这些常用列即可完成工作,这样,减少了文件IO的读写,提高读写的效率( 不用再想行式数据库进行全表扫描,然后过滤相关字段) 在行式数据库里面

HBase笔记整理(二)

[TOC] HBase笔记整理(二) 逻辑结构 RowKey第一位 ColumnFamily ColumnQuiauer value(TimeStamps) Cell 物理结构 HMaster ----->NameNode 管理节点,用于管理HBase中的Table和Region的结构操作,比如用户增.删.修改表的操作. 在HBase集群中,可以启动多个HMaster,但是只能有一个HMaster属于Active的状态,通过ZooKeeper和其它standby状态的HMaster进程完成,一个

Hbase框架原理及相关的知识点理解、Hbase访问MapReduce、Hbase访问Java API、Hbase shell及Hbase性能优化总结

转自:http://blog.csdn.net/zhongwen7710/article/details/39577431 本blog的内容包含: 第一部分:Hbase框架原理理解 第二部分:Hbase调用MapReduce函数使用理解 第三部分:Hbase调用Java API使用理解 第四部分:Hbase Shell操作 第五部分:Hbase建表.读写操作方式性能优化总结 第一部分:Hbase框架原理理解 概述 HBase是一个构建在HDFS上的分布式列存储系统:HBase是基于Google

Hbase学习笔记之一 | Hbase Shell命令篇

最近在XX项目的测试过程中,接触到一些HBase的东西,希望能站在测试的角度,把过程记录下来,期望对快速了解它有点帮助.作为一个初次接触它的人来说,需要迫切掌握其中基本的概念,这里就不赘述了. HBase Shell是HBase提供的便捷的访问方式,首先你需要搭建HBase的环境,可以参考 http://hbase.apache.org/book/quickstart.html 和http://hbase.apache.org/book/notsoquick.html. 1.进入Hbase Sh

笔记《Hbase 权威指南》

为什么要用Hbase- Hbase的诞生是因为现有的关系型数据库已经无法在硬件上满足疯狂增长的数据了,而且因为需要实时的数据提取Memcached也无法满足- Hbase适合于无结构或半结构化数据,适合于schema变动的情况- Hbase天生适合以时间轴做查询 Werner Vogels,可以关注一下他的博客(Amazon的CTO) 分布式计算系统的CAP定理:在理論計算機科學中, CAP定理(CAP theorem), 又被稱作 布魯爾定理(Brewer's theorem), 它指出對於一

3D数学--学习笔记(六):我对矩阵的一些简单理解总结

1.矩阵的行列式: 任意矩阵中都存在一个标量,称作矩阵的行列式,这里该值记为A. 2D中,A等于以基向量为两边的平行四边形的有符号面积.有符号面积是指如果平行四边形相对于原来的方位"翻转",那么面积为负. 3D中,A等于以变换后的基向量为三边的平行六面体的有符号体积.3D中,如果变换使得平行六面体"由里向外"翻转,则行列式变负. A的大小和矩阵变换导致的尺寸改变有关.IAI和面积(2D).体积(3D)的改变相关. A的符号则说明了变换矩阵是否包含镜像. A还能对矩阵

HBase表的架构原理

HBase整体架构图 Hbase Table的基本单位是Region,一个Table对应多个Region,Table层级关系如下: Table       (HBase table) Region       (Regions for the table) Store          (Store per ColumnFamily for each Region for the table) MemStore         (MemStore for each Store for each