本文共 7179 字,大约阅读时间需要 23 分钟。
Apache Hbase是一个基于Hadoop的数据库,它可靠、数据多版本、分布式适合结构化大数据的存储,Apache Hbase是Google BigTable开源实现,基于列储存的菲关系型数据库。
列储存和行储存是指数据子存储介质中的额储存方式
**·**关系型数据库(行储存):Oracle、mysql等 **·**非关系型数据库(列储存):Hbase、Redis(1)大:一个表可以有上百亿行上百万列。
(2)面向列:面向列表(列簇)的存储和控制权限 (3)结构稀疏:对于为空(NULL)的列,并不占用储存空间,因此,表可以设计的非常稀疏。 (4)无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中的不同行可以有截然不同的列。 (5)数据多版本:每个单元格中的数据可以有多个版本,默认情况下,版本号自动分配,版本就是单元格插入时的时间戳。 (6)数据类型单一:Hbase中的数据在底层储存是都是byte【】,可以存放任意类型的数据。完全分布式结构:
zookeeper作为hbase集群的入口(后面java api中从连接hbase的方式就能看出来)hbase架构详解:
HBase中的每张表都通过rowKey按照一定的范围被分割成多个子表(HRegion),默认一个HRegion超过256M就要被分割成两个,这个过程由HRegionServer管理,而HRegion的分配由HMaster管理。HMaster的作用:
(1)为HRegionServer分配HRegion
(2)负责HRegionServer的负载均衡 (3)发现失效的HRegionServer并重新分配 (4)HDFS上的垃圾文件回收 (5)处理Schema更新请求HRegionServer的作用:
(1)维护HMaster分配给它的HRegion,处理对这些HRegion的IO请求
(2)负责切分正在运行过程中变得过大的HRegion可以看到,Client访问HBase上的数据并不需要HMaster参与,寻址访问ZooKeeper和HRegionServer,数据读写访问HRegionServer, HMaster仅仅维护Table和Region的元数据信息,Table的元数据信息保存在ZooKeeper上,负载很低。HRegionServer存取一个子表时,会创建一个HRegion对象,然后对表的每个列簇创建一个HStore对象,每个HStore都会有一个MemStore和0或多个StoreFile与之对应,每个StoreFile都会对应一个HFile,HFile就是实际的存储文件。因此,一个HRegion有多少列簇就有多少个Store。 一个HRegionServer会有多个HRegion和一个HLog。
HRegion
Table在行的方向上分割为多个HRegion,HRegion是HBase中分布式存储和负载均衡的最小单元,即不同的HRegion可以分别在不同的HRegionServer上,但同一个HRegion是不会拆分到多个HRegionServer上的。HRegion按大小分割,每个表一般只有一个HRegion,随着数据不断插入表,HRegion不断增大,
当HRegion的某个列簇达到一个阀值(默认256M)时就会分成两个新的HRegion。1、 <表名,startrowkey, 创建时间> 2、由目录表(-ROOT-和.META.)记录该Region的EndRowKeyHRegion定位:HRegion被分配给哪个HRegionServer是完全动态的,所以需要机制来定位HRegion具体在哪个HRegionServer,HBase使用三层结构来定位HRegion: 1、通过zk里的文件/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一个region。 2、通过-ROOT-表查找.META.表的第一个表中相应的HRegion位置。其实-ROOT-表是.META.表的第一个region; .META.表中的每一个Region在-ROOT-表中都是一行记录。 3、通过.META.表找到所要的用户表HRegion的位置。用户表的每个HRegion在.META.表中都是一行记录。 -ROOT-表永远不会被分隔为多个HRegion,保证了最多需要三次跳转,就能定位到任意的region。Client会将查询的位置信息保存缓存起来,缓存不会主动失效, 因此如果Client上的缓存全部失效,则需要进行6次网络来回,才能定位到正确的HRegion,其中三次用来发现缓存失效,另外三次用来获取位置信息。 表名,startrowkey,>
HStore
每一个HRegion由一个或多个HStore组成,至少是一个HStore,HBase会把一起访问的数据放在一个HStore里面,即为每个ColumnFamily建一个HStore,如果有几个ColumnFamily,也就有几个HStore。一个Store由一个MemStore和0或者多个StoreFile组成。 HBase以Store的大小来判断是否需要切分HRegion。MemStore
MemStore 是放在内存里的,保存修改的数据即keyValues。当MemStore的大小达到一个阀值(默认64MB)时,MemStore会被Flush到文件, 即生成一个快照。目前HBase会有一个线程来负责MemStore的Flush操作。StoreFile
MemStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存HLog
HLog(WAL log):WAL意为write ahead log,用来做灾难恢复使用,HLog记录数据的所有变更,一旦region server 宕机,就可以从log中进行恢复。简单描述一下Hbase故障恢复的过程:
Hmaster发现某些HregionServer不可用,开始故障恢复,获取故障的HregionServer的Hlog,分离每一个HRegion写指令,重新分配Hregion,在配到HregionServer中恢复HRegion数据,执行分离的HRegion写指令恢复MemStore,持久化完成的数据可以直接从HDFS中获取。org.apache.hbase hbase-client 1.2.4 org.apache.hbase hbase-common 1.2.4 org.apache.hbase hbase-protocol 1.2.4 org.apache.hbase hbase-server 1.2.4 junit junit 4.12 org.apache.hbase hbase-client 1.2.4 org.apache.hbase hbase-common 1.2.4 org.apache.hbase hbase-protocol 1.2.4 org.apache.hbase hbase-server 1.2.4 junit junit 4.12
package com.learn;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.hbase.*;import org.apache.hadoop.hbase.client.*;import org.apache.hadoop.hbase.util.Bytes;import org.junit.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.util.ArrayList;import java.util.Iterator;public class HbaseAPI { private Admin admin; private Connection connection; @Before public void doBefore() throws IOException { Configuration configuration = HBaseConfiguration.create(); configuration.set(HConstants.ZOOKEEPER_QUORUM,"192.168.139.156:2181"); connection = ConnectionFactory.createConnection(configuration); admin = connection.getAdmin(); } @Test public void testCreateNameSpace() throws IOException { NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create("gaoj").addConfiguration("author", "gaojian").build(); admin.createNamespace(namespaceDescriptor); } @Test public void testCreateTable() throws IOException { HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("gaoj:t_order")); HColumnDescriptor cf1 = new HColumnDescriptor("cf1"); cf1.setMaxVersions(3); HColumnDescriptor cf2 = new HColumnDescriptor("cf2"); cf2.setTimeToLive(1800); hTableDescriptor.addFamily(cf1); hTableDescriptor.addFamily(cf2); admin.createTable(hTableDescriptor); } @Test public void testInsert() throws IOException { Table table = connection.getTable(TableName.valueOf("gaoj:t_order")); Put put = new Put(Bytes.toBytes("order101")); put.addColumn(Bytes.toBytes("cf1"),Bytes.toBytes("count"),Bytes.toBytes(123)); table.put(put); } @Test public void testSelect() throws IOException { Table table = connection.getTable(TableName.valueOf("gaoj:t_order")); Get get = new Get(Bytes.toBytes("order101")); Result result = table.get(get); String name = Bytes.toString(result.getValue(Bytes.toBytes("cf1"), Bytes.toBytes("name"))); System.out.println(name); } @Test public void testDelete() throws IOException { Table table = connection.getTable(TableName.valueOf("gaoj:t_order")); Delete delete = new Delete(Bytes.toBytes("order101")); ArrayListlist = new ArrayList (); list.add(delete); table.delete(list); } @Test public void testScan() throws IOException { Table table = connection.getTable(TableName.valueOf("gaoj:t_order")); Scan scan = new Scan(); ResultScanner scanner = table.getScanner(scan); Iterator iterator = scanner.iterator(); while (iterator.hasNext()){ Result next = iterator.next(); String row = Bytes.toString(next.getRow()); String name = Bytes.toString(next.getValue(Bytes.toBytes("cf1"), Bytes.toBytes("name"))); System.out.println(row + "*" + name); } } @After public void doAfter() throws IOException { if(admin != null){ admin.close(); } if(connection != null){ connection.close(); } }}
以上api实现了数据的增删改查,关于Hbase,更多的掌握的是API的使用,在学习的过程中,我们可以使用help指令帮助学习。
转载地址:http://simzi.baihongyu.com/