Fork me on GitHub

hbase(二)

一、HBase简介

1.1简介

hbase是bigtable的开源山寨版本。是建立的hdfs之上,提供高可靠性、高性能、列存储、可伸缩、实时读写的数据库系统。
它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的range来检索数据,仅支持单行事务(可通过hive支持来实现多表join等复杂操作)。主要用来存储非结构化和半结构化的松散数据。与hadoop一样,Hbase目标主要依靠横向扩展,通过不断增加廉价的商用服务器,来增加计算和存储能力。

1.2 Hbase与传统数据库的对比

HBase以表的形式存储数据。表有行和列组成。列划分为若干个列族(row family)。

我们可以先来看一下传统的关系型数据库中的表:

 

然后与HBase的表进行对比,hbase的表结构,与传统的关系型数据库有较大的差别

我们就可以发现很多不同地方:

hbase不支持sql语句,它是一个nosql的一种,如果没有学过nosql或rubey,我们可以用help
1、定义表时不指定字段
2、定义表的时候只要指定列族名,列族数量不限
3、每一行都有一个固定的字段(行键),具有唯一性
4、对值的修改,原来的值是保留着的,每个值可以保留多个版本。默认查询的是最新版本的的值。(默认保留一个版本)

1.3 HBase中的重要概念

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

访问控制、磁盘和内存的使用统计都是在列族层面进行的。实际应用中,列族上的控制权限能帮助我们管理不同类型的应用:我们允许一些应用可以添加新的基本数据、一些应用可以读取基本数据并创建继承的列族、一些应用则只允许浏览数据(甚至可能因 为隐私的原因不能浏览所有数据)。

时间戳:HBase中通过row和columns确定的为一个存贮单元称为cell。每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个 cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。

为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,hbase提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(比如最近七天)。用户可以针对每个列族进行设置。

Cell:由{row key, column( =<family> + <label>),version} 唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存贮。

 

二、HBase体系结构

1、一个表会按照行划分为若干个region,每一个region分配给一台特定的regionserver管理
2、每一个region内部还要一句列族划分为若干个HStore
3、每个HStore中的数据会落地到若干个HFILE文件中
4、region体积会随着数据插入而不断增长,到一定阈值后分裂
5、随着region的分裂,一台regionserver上管理的region会越来越多
6、HMASTER会根据regionserver上管理的region数做负载均衡
7、region中的数据拥有一个内存缓存:memstore,数据的访问优先在memstore中进行
8、memstore中的数据因为空间有限,所以需要定期flush到文件storefile中,每次flush都是生成新的storefile
9、storefile的数量随着时间也会不断增加,regionserver会定期将大量storefile进行合并(merge)

行键的设计对数据查询效率的影响非常大。
HBase具有很好的可伸缩性:如果存储容量不够的时候,直接加datanode或者regionservers
hbase可以作为一个线上系统的底层系统的功能。

Hmaster可以做负载均衡,监控到各个节点之间的数据存储情况。
每一个store(列族)会有一个内存缓存,存放的是一些最热的数据(最近访问的),这样的话读取数据的速度会快很多。

文件都是有索引的,所以查起来会比较快的。

region会在storefile定期进行合并操作。

三、HBase   shell的使用

 create 'user-info',{NAME=>'base_info',VERSIONS=>3},{NAME=>'extra_info'}  
 put 'user-info','rk-100001','base_info:name','huang****'
 put 'user-info','rk-100001','base_info:age','30'  
 put 'user-info','rk-100001','base_info:address','Xinyang'   
 put 'user-info','rk-100001','base_info:tel','13000000000'   

 

scan 'user-info' 

四、eclipse中使用HBase

  1 // 与HBase数据库的连接对象
  2     Connection conn;
  3     @Before
  4     public void setUp() throws Exception {
  5 
  6         // 取得一个数据库连接的配置参数对象
  7         Configuration conf = HBaseConfiguration.create();
  8         // 设置连接参数:HBase数据库所在的主机IP
  9         conf.set("hbase.zookeeper.quorum", "master,node1,node2");
 10         // 设置连接参数:HBase数据库使用的端口
 11         conf.set("hbase.zookeeper.property.clientPort", "2181");
 12 
 13         // 取得一个数据库连接对象
 14         conn = ConnectionFactory.createConnection(conf);
 15     }
 16 
 17     @Test
 18     public void put() throws Exception {
 19         
 20         // 通过连接工厂创建连接对象
 21         //conn = ConnectionFactory.createConnection(conf);
 22         // 通过连接查询tableName对象
 23         TableName tname = TableName.valueOf("ns1:t1");
 24         // 获得table
 25         Table table = conn.getTable(tname);
 26 
 27         // 通过bytes工具类创建字节数组(将字符串)
 28         byte[] rowid = Bytes.toBytes("row3");
 29 
 30         // 创建put对象
 31         Put put = new Put(rowid);
 32 
 33         byte[] f1 = Bytes.toBytes("f1");
 34         byte[] id = Bytes.toBytes("id");
 35         byte[] value = Bytes.toBytes(102);
 36         put.addColumn(f1, id, value);
 37 
 38         // 执行插入
 39         table.put(put);
 40     }
 41 
 42     @Test
 43     public void bigInsert() throws Exception {
 44 
 45         DecimalFormat format = new DecimalFormat();
 46         format.applyPattern("0000");
 47 
 48         long start = System.currentTimeMillis();
 49         TableName tname = TableName.valueOf("ns1:t1");
 50         HTable table = (HTable) conn.getTable(tname);
 51         // 不要自动清理缓冲区
 52         table.setAutoFlush(false);
 53 
 54         for (int i = 1; i < 10000; i++) {
 55             Put put = new Put(Bytes.toBytes("row" + format.format(i)));
 56             // 关闭写前日志
 57             put.setWriteToWAL(false);
 58             put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("id"), Bytes.toBytes(i));
 59             put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("name"), Bytes.toBytes("tom" + i));
 60             put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("age"), Bytes.toBytes(i % 100));
 61             table.put(put);
 62 
 63             if (i % 2000 == 0) {
 64                 table.flushCommits();
 65             }
 66         }
 67         //
 68         table.flushCommits();
 69         System.out.println(System.currentTimeMillis() - start);
 70     }
 71     
 72     /**
 73      * 遍历
 74      */
 75     @Test
 76     public void scan() throws IOException {
 77         TableName tname = TableName.valueOf("ns1:t1");
 78         Table table = conn.getTable(tname);
 79         Scan scan = new Scan();
 80         scan.setStartRow(Bytes.toBytes("row5000"));
 81         scan.setStopRow(Bytes.toBytes("row8000"));
 82         ResultScanner rs = table.getScanner(scan);
 83         Iterator<Result> it = rs.iterator();
 84         while (it.hasNext()) {
 85             Result r = it.next();
 86             byte[] name = r.getValue(Bytes.toBytes("f1"), Bytes.toBytes("name"));
 87             System.out.println(Bytes.toString(name));
 88         }
 89     }
 90     
 91     /**
 92      * 动态遍历
 93      */
 94     @Test
 95     public void scan2() throws IOException {
 96         //Configuration conf = HBaseConfiguration.create();
 97         //Connection conn = ConnectionFactory.createConnection(conf);
 98         TableName tname = TableName.valueOf("ns1:t1");
 99         Table table = conn.getTable(tname);
100         Scan scan = new Scan();
101         scan.setStartRow(Bytes.toBytes("row5000"));
102         scan.setStopRow(Bytes.toBytes("row8000"));
103         ResultScanner rs = table.getScanner(scan);
104         Iterator<Result> it = rs.iterator();
105         while (it.hasNext()) {
106             Result r = it.next();
107             Map<byte[],byte[]> map = r.getFamilyMap(Bytes.toBytes("f1"));
108             for(Map.Entry<byte[],byte[]> entrySet : map.entrySet()){
109                 String col = Bytes.toString(entrySet.getKey());
110                 String val = Bytes.toString(entrySet.getValue());
111                 System.out.print(col + ":" + val + ",");
112             }
113 
114             System.out.println();
115         }
116     }

 

 参考:http://blog.csdn.net/sdksdk0/article/details/51680296

            http://blog.csdn.net/u011308691/article/details/51476383

posted @ 2018-01-03 12:19  薄荷加冰2060  阅读(285)  评论(0编辑  收藏  举报