HBase简介

来源:互联网 发布:用python写网络爬虫 书 编辑:程序博客网 时间:2024/06/03 13:19

简介


HBase – Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。



生态


  • 利用Hadoop HDFS作为其文件存储系统。
  • 利用Hadoop MapReduce来处理HBase中的海量数据。
  • 利用Zookeeper作为协同服务



数据模型

Table & Column Family

Row KeyTimestampColumn Familynameager1t3Shenfuqiang22t2Shenfugui21t1

r2t5FZB23t4THen 1

  • Row Key: 行键,Table的主键,Table中的记录按Row Key排序
  • Timestamp: 时间戳,每次数据操作对应的时间戳,可以看作是数据的version number
  • Column Family:列簇,Table在水平方向有一个或者多个Column Family组成,一个Column Family中可以由任意多个Column组成,所有Column均以二进制格式存储,用户需要自行进行类型转换。

row key为表的主键,是必然存在的一列,其次HBase表中的除row key外的列被划分为若干个列族(column family),列族下面是的一些列。

数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。

hbase表中的每个列,都归属与某个列族。必须在使用表之前定义。列名都以列族作为前缀。例如courses:history,courses:math 都属于courses 这个列族。

cell中的数据是没有类型的,全部是字节码形式存贮。

针对一行的读与写操作都是原子的。

通常column family的数量比较少(百数量级),而且一般相对固定,通常在表创建之后就很难甚至不可能修改了。与此相对的column key一般没有数量限制,也可以动态增删。

"com.tx.lottery" : { // row key"issues" : { // first column family"ssq": {  // column key  1 : "2014150" // single timestamp},"dlt": "15015",// no timestamp"k3" : {  10 : "20150301013", // multiple timestamp  7  : "20150301010",  1  : "20150301006"}}"apps" : { // second column family"" : "hsf"// empty column key}"fangInfo" : { // third column faimily  "location":,  "price":} }


Table & Region

当Table随着记录数不断增加而变大后,会逐渐分裂成多份splits,成为regions,一个region由[startkey,endkey)表示,不同的region会被Master分配给相应的RegionServer进行管理:


-ROOT- && .META. Table(0.96以前的版本

HBase中有两张特殊的Table,-ROOT-和.META.

Ø  .META.:记录了用户表的Region信息,.META.可以有多个regoin

Ø  -ROOT-:记录了.META.表的Region信息,-ROOT-只有一个region

Ø  Zookeeper中记录了-ROOT-表的location

Client访问用户数据之前需要首先访问zookeeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据的位置去访问,中间需要多次网络操作,不过client端会做cache缓存。



HBase系统架构

Client

HBase Client使用HBase的RPC机制与HMaster和HRegionServer进行通信。对于管理类操作,Client与HMaster进行RPC;对于数据读写类操作,Client与HRegionServer进行RPC。


Zookeeper

Zookeeper Quorum中除了存储了-ROOT-表的地址和HMaster的地址,HRegionServer也会把自己以Ephemeral方式注册到Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的健康状态。此外,Zookeeper也避免了HMaster的单点问题。


HMaster

HMaster没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper的Master Election机制保证总有一个Master运行,HMaster在功能上主要负责Table和Region的管理工作:

  1. 管理用户对Table的增、删、改、查操作
  2. 管理HRegionServer的负载均衡,调整Region分布
  3. 在Region Split后,负责新Region的分配
  4. 在HRegionServer停机后,负责失效HRegionServer 上的Regions迁移


HRegionServer

Client直接通过HRegionServer读写数据(从HMaster中获取元数据,找到RowKey所在的HRegion/HRegionServer后)

HRegionServer主要负责响应用户I/O请求,向HDFS文件系统中读写数据,是HBase中最核心的模块。HRegionServer内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region,HRegion中由多个HStore组成。每个HStore对应了Table中的一个Column Family的存储。

HStore存储是HBase存储的核心了,其中由两部分组成,一部分是MemStore,一部分是StoreFiles。MemStore是Sorted Memory Buffer,用户写入的数据首先会放入MemStore,当MemStore满了以后会Flush成一个StoreFile(底层实现是HFile),当StoreFile文件数量增长到一定阈值,会触发Compact合并操作,将多个StoreFiles合并成一个StoreFile,合并过程中会进行版本合并和数据删除,因此可以看出HBase其实只有增加数据,所有的更新和删除操作都是在后续的compact过程中进行的,这使得用户的写操作只要进入内存中就可以立即返回,保证了HBase I/O的高性能。当StoreFiles Compact后,会逐步形成越来越大的StoreFile,当单个StoreFile大小超过一定阈值后,会触发Split操作,同时把当前Region Split成2个Region,父Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上。下图描述了Compaction和Split的过程:

在理解了上述HStore的基本原理后,还必须了解一下HLog的功能,因为上述的HStore在系统正常工作的前提下是没有问题的,但是在分布式系统环境中,无法避免系统出错或者宕机,因此一旦HRegionServer意外退出,MemStore中的内存数据将会丢失,这就需要引入HLog了。每个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中(HLog文件格式见后续),HLog文件定期会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。

screenshot.png
screenshot.png


HFile

首先HFile文件是不定长的,长度固定的只有其中的两块:Trailer和FileInfo。Trailer中有指针指向其他数据块的起始点。File Info中记录了文件的一些Meta信息,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等。Data Index和Meta Index块记录了每个Data块和Meta块的起始点。

Data Block是HBase I/O的基本单元,为了提高效率,HRegionServer中有基于LRU的Block Cache机制。每个Data块的大小可以在创建一个Table的时候通过参数指定,大号的Block有利于顺序Scan,小号Block利于随机查询。每个Data块除了开头的Magic以外就是一个个KeyValue对拼接而成, Magic内容就是一些随机数字,目的是防止数据损坏。后面会详细介绍每个KeyValue对的内部构造。

HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构:

开始是两个固定长度的数值,分别表示Key的长度和Value的长度。紧接着是Key,开始是固定长度的数值,表示RowKey的长度,紧接着是RowKey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier,然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据了。




HBase表特点:


a.大:一个表可以有上亿行,上百万列
b.面向列:面向列(族)的存储和权限控制,列(族)独立检索。
c.稀疏:对于为空(null)的列,并不占用存储空间,因此,表可以设计的非常稀疏。



常用API

        Configuration config = new Configuration();        config.set(HConstants.ZOOKEEPER_CLIENT_PORT, port);        config.set(HConstants.ZOOKEEPER_QUORUM, quorum);        config.set(HConstants.ZOOKEEPER_ZNODE_PARENT, cluster);        config = HBaseConfiguration.create(config);        HTable hTable = new HTable(config, "lottery_tb_order");            HBaseAdmin hBaseAdmin = new HBaseAdmin(config);            HTableDescriptor[] hTableDescriptors = hBaseAdmin.listTables();        //创建配置        Configuration configuration = HBaseConfiguration.create();        HBaseAdmin admin = new HBaseAdmin(configuration);        // 新建表的基本信息,包含表名,column family信息等        HTableDescriptor tableDescriptor = new TableDescriptor(TableName.valueOf("lottery_info"));        tableDescriptor.addFamily(new HColumnDescriptor("issues"));        tableDescriptor.addFamily(new HColumnDescriptor("apps"));        tableDescriptor.addFamily(new HColumnDescriptor("fangInfo"));        // 执行建表        admin.createTable(tableDescriptor);        HColumnDescriptor columnDescriptor = new HColumnDescriptor("matches");        admin.addColumn("lottery_info", columnDescriptor);        admin.deleteColumn("lottery_info","fangInfo");        Configuration configuration = HBaseConfiguration.create();        HBaseAdmin admin = new HBaseAdmin(configuration);                String tableName = "lottery_info";        if (admin.tableExists(tableName) && !admin.isTableDisabled(tableName)) {            admin.disableTable(tableName);            admin.deleteTable(tableName);        }        Configuration configuration = HBaseConfiguration.create();        HTable table = new HTable(configuration, "lottery_info");        String rowKey = "com.tx.lottery";        String columnFamily = "issues";        String columnKey = "ssq";        String data = "2014150";        // 插入或更新一行        Put put = new Put(Bytes.toBytes(rowKey));        put.add(Bytes.toBytes(columnFamily), Bytes.toBytes(columnKey), Bytes.toBytes(data));        table.put(put);        // 查询一行        Get get = new Get(Bytes.toBytes(rowKey));        Result result = table.get(get);        byte[] value = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(columnFamily));        Configuration configuration = HBaseConfiguration.create();        HTable table = new HTable(configuration, "lottery_info");        String rowKey = "com.tx.lottery";        String columnFamily = "issues";        String columnKey = "ssq";        // 删除一行        Delete delete = new Delete(rowKey.getBytes());        table.delete(delete);        // 删除column下的最新版本数据        Delete specifiedDelete = new Delete(rowKey.getBytes());        specifiedDelete.addColumn(columnFamily.getBytes(), columnKey.getBytes());        table.delete(specifiedDelete);





原创粉丝点击