Google的BigTable
Apache的Cassandra、HBase
.META.存储的是用户表的信息(元数据)即:在哪一个用户的哪一个region里
在HBase物理模型中客户端检索数据时,先在内存中找,找不到时再去磁盘中找
Client如何从HBase中查询数据
zookeeper file中记录了-ROOT-表的Location
-ROOT-
记录了.META表的Region信息
-ROOT- 只有一个Region
将.META中的Region映射到Region Server上
该表主要存储了.META服务器位置以及映射了那些META Region
.META
记录了用户表的Region信息
.META可以有多个Region
包括Region中数据起止行信息,Region“在线”状态等
保存Region Server的地址
WAL
预写日志文件,操作先记录进日志,然后数据才写入。
Client初始化一个修改数据的操作,put或者delete,这些操作封装在一个KeyValue实例对象中,发送给HRegionServer,当达到一定的大小后,HRegionServer将其发送给HRegion。在这个过程中,数据会被先写入到WAL,之后被写入实际存储的MemStore中
WAL的重要作用是灾难修复,当服务器崩溃后,就可以回复崩溃前的数据。如果WAL写入失败,那么整个操作都将认为失败
HRegion是HBase分布式存储和负载均衡的最小单元,但并不是存储的最小单元
HRegion由一个或多个Store组成,每个Store保存一个列族,一个列族称为一个Store,包含一个MemStore
列族是HDFS对应的最细粒度的文件夹,文件夹的名字就是列族的名字,里面存储一定数量的StoreFile
HFile是StoreFile在HDFS上的底层实现
Store存储是HBase的核心,其中由两部分组成,一部分是MemStore,一部分是StoreFile
HBase的两种逻辑模式:
逻辑模式1:
逻辑模式2:
Hbase的表结构:表名,列族名(只包含这两种,列限定符等不属于hbase表结构
表名:数据类型String,HBase用表来组织数据
行健:数据类型byte[],数据在表里的唯一标识,在表中数据按row存储
列族:数据类型String,row里的数据按照列族分组,列族会影响到HBase数据的物理存放,物理上将同“族”数据存储在一起,必须先定义且不易修改,每个row拥有相同列族,但不需要在每个列族 存储数据
列限定符:数据类型byte[],列族中的数据通过列限定符来定位,不必事先定义,不必在不同的row之间保持一致
单元:数据类型byte[],行健,列族和列限定符一起确定一个单元,单元里存储的是单元值
时间版本:数据类型long,单元值有时间版本,用时间戳(Timestamp)标识,默认数量3个
删除记录的过程
HBase中删除记录的命令为delete,该命令标记记录在表中状态为已删除状态,但该记录并不从表中删除,知道split或者compact操作发生时才真正从表中删除
PageFilter、SingleColumnValueFilter、FilterList
PageFileter:分页过滤器(专用过滤器)
有时候调用PageFilter返回的行数可能会大于定义的行数,因为分布式的原因,每一个Region都会调用一个PageFilter,假设定义返回行数为20,有3个Region,最后结果至多是60条
SingleColumnFilter:列值过滤器(专用过滤器)
用一列的值决定是否一行数据被过滤
FilterList:过滤器列表
FilterList.Operator 可选枚举项:
MUST_PASS_ALL 所有过滤器都允许包含这个值
MUST_PASS_ONE 只有一个过滤器允许包括这个值
比较过滤器:
基于列限定符的过滤器:QualifierFilter
列前缀过滤器:ColumnPrefixFilter
比较器:
完全匹配:BinaryComparator
从左端开始前缀匹配:BinaryPrefixComparator
create 'scores','grade'
向"scores"表加入一行数据,rowkey为"zkb",列族为"grade",列限定符为"class",值为"5" put 'scores','zkb','grade:class','5'
查询整行数据 get'scores','zkb'
查询列族grade的数据 get'scores','zkb’,'grade'
查询列族grade中列class的数据 get'scores','zkb’,'grade:class'
全表查询 scan 'scores'
按rowkey的范围查询 scan 'scores',{STARTROW=>'001',STOPROW=>'005'}
删除记录 delete 'scores','001','grade:class'
删除表,在删除表之前要disable,防止删除过程中访问该表 disable 'scores' drop 'scores'
public void scan(String tablename) throws Exception{ HTable table = new HTable(conf,tablename); Scan s = new Scan(); ResultScanner rs = table.getScanner(s); for(Result r : rs){ byte[] row = r.getRow(); byte[] value = r.getValue(Bytes.toBytes("grade"),Bytes.toBytes("class")); System.out.println("Scan:" + Bytes.toString(row) + " is in class " + Bytes.toString(value)); } rs.close(); table.close(); }
public void get(String tablename,String row) throws Exception{ HTable table = new HTable(conf,tablename); Get g = new Get(Bytes.toBytes(row)); Result result = table.get(g); byte[] value = result.getValue(Bytes.toBytes("grade"), Bytes.toBytes("class")); System.out.println("Get:" + row + "=> class is " + Bytes.toString(value)); table.close(); }
public void put(String tablename,String row,String columnFamily,String column,String data) throws Exception{ HTable table = new HTable(conf,tablename); Put p1 = new Put(Bytes.toBytes(row)); p1.add(Bytes.toBytes(columnFamily),Bytes.toBytes(column), Bytes.toBytes(data)); table.put(p1); System.out.println(row +" putted"); table.close(); }
public void createTable(String strTab, String[] arrCF) throws Exception{ HBaseAdmin admin = null; admin = new HBaseAdmin(conf); if(admin.tableExists(strTab)){ System.out.println(strTab + "already exists"); }else{ HTableDescriptor ts = new HTableDescriptor(strTab); for (int i = 0 ; i< arrCF.length; i++){ ts.addFamily(new HColumnDescriptor(arrCF[i])); } admin.createTable(ts); System.out.println(strTab + " is created"); } dmin.close(); }
public void deleteTable(String strTab) throws Exception{ HBaseAdmin admin = null; admin = new HBaseAdmin(conf); if(!admin.tableExists(strTab)){ System.out.println(strTab + " is not exists"); }else{ admin.disableTable(strTab); admin.deleteTable(strTab); System.out.println(strTab + " is deleted"); } admin.close(); }