• HBase


    Chapter 5. 数据模型

    Table of Contents

    5.1. 概念视图
    5.2. 物理视图
    5.3. 表
    5.4. 行
    5.5. 列族
    5.6. Cells
    5.7. 版本号

    5.7.1. HBase的操作(包括版本号操作)
    5.7.2. 现有的限制
    

    简单来说,应用程序是以表的方式在HBase存储数据的。表是由行和列构成的,全部的列是从属于某一个列族的。

    行和列的交叉点称之为cell,cell是版本号化的。

    cell的内容是不可切割的字节数组。

    表的行键也是一段字节数组,所以不论什么东西都能够保存进去,不论是字符串或者数字。HBase的表是按key排序的,排序方式之针对字节的。全部的表都必需要有主键-key.
    5.1. 概念视图

    以下是依据BigTable 论文稍加改动的样例。

    有一个名为webtable的表,包括两个列族:contents和anchor.在这个样例里面,anchor有两个列 (anchor:cssnsi.com, anchor:my.look.ca),contents仅有一列(contents:html)
    列名

    一个列名是由它的列族前缀和修饰符(qualifier)连接而成。比如列contents:html是列族 contents加冒号(:)加 修饰符 html组成的。

    Table 5.1. 表 webtable
    Row Key Time Stamp ColumnFamily contents ColumnFamily anchor
    “com.cnn.www” t9 anchor:cnnsi.com = “CNN”
    “com.cnn.www” t8 anchor:my.look.ca = “CNN.com”
    “com.cnn.www” t6 contents:html = “…”
    “com.cnn.www” t5 contents:html = “…”
    “com.cnn.www” t3 contents:html = “…”

    5.2. 物理视图

    虽然在概念视图里。表能够被看成是一个稀疏的行的集合。但在物理上,它的是区分列族 存储的。新的columns能够不经过声明直接添加一个列族.

    Table 5.2. ColumnFamily anchor
    Row Key Time Stamp Column Family anchor
    “com.cnn.www” t9 anchor:cnnsi.com = “CNN”
    “com.cnn.www” t8 anchor:my.look.ca = “CNN.com”

    Table 5.3. ColumnFamily contents
    Row Key Time Stamp ColumnFamily “contents:”
    “com.cnn.www” t6 contents:html = “…”
    “com.cnn.www” t5 contents:html = “…”
    “com.cnn.www” t3 contents:html = “…”

    值得注意的是在上面的概念视图中空白cell在物理上是不存储的,由于根本没有必要存储。

    因此若一个请求为要获取t8时间的contents:html。他的结果就是空。类似的。若请求为获取t9时间的anchor:my.look.ca。结果也是空。可是。假设不指明时间,将会返回最新时间的行,每一个最新的都会返回。比如,假设请求为获取行键为”com.cnn.www”。没有指明时间戳的话,活动的结果是t6下的contents:html,t9下的anchor:cnnsi.com和t8下anchor:my.look.ca。

    For more information about the internals of how HBase stores data, see Section 9.7, “Regions”.
    5.3. 表

    表是在schema声明的时候定义的。
    5.4. 行

    行键是不可切割的字节数组。

    行是按字典排序由低到高存储在表中的。一个空的数组是用来标识表空间的起始或者结尾。
    5.5. 列族

    在HBase是列族一些列的集合。

    一个列族全部列成员是有着同样的前缀。比方,列courses:history 和 courses:math都是 列族 courses的成员.冒号(:)是列族的分隔符。用来区分前缀和列名。

    column 前缀必须是可打印的字符,剩下的部分(称为qualify),能够又随意字节数组组成。列族必须在表建立的时候声明。column就不需要了。随时能够新建。

    在物理上,一个的列族成员在文件系统上都是存储在一起。

    由于存储优化都是针对列族级别的,这就意味着。一个colimn family的全部成员的是用同样的方式訪问的。

    5.6. Cells

    A {row, column, version} 元组就是一个HBase中的一个 cell。Cell的内容是不可切割的字节数组。
    5.7. 数据模型操作

    四个基本的数据模型操作是 Get, Put, Scan, 和 Delete. 通过 HTable 实例进行操作.
    5.7.1. Get

    Get 返回特定行的属性。

    Gets 通过 HTable.get 运行。
    5.7.2. Put

    Put 要么向表添加新行 (假设key是新的) 或更新行 (假设key已经存在)。 Puts 通过 HTable.put (writeBuffer) 或 HTable.batch (non-writeBuffer)运行。
    5.7.3. Scans

    Scan 同意多行特定属性迭代。

    以下是一个在 HTable 表实例上的演示样例。 假设表有几行键值为 “row1”, “row2”, “row3”, 另一些行有键值 “abc1”, “abc2”, 和 “abc3”. 以下的演示样例展示startRow 和 stopRow 能够应用到一个Scan 实例。以返回”row”打头的行。

    HTable htable = … // instantiate HTable

    Scan scan = new Scan();
    scan.addColumn(Bytes.toBytes(“cf”),Bytes.toBytes(“attr”));
    scan.setStartRow( Bytes.toBytes(“row”)); // start key is inclusive
    scan.setStopRow( Bytes.toBytes(“row” + (char)0)); // stop key is exclusive
    ResultScanner rs = htable.getScanner(scan);
    try {
    for (Result r = rs.next(); r != null; r = rs.next()) {
    // process result…
    } finally {
    rs.close(); // always close the ResultScanner!
    }

    5.7.4. Delete

    Delete 从表中删除一行. 删除通过HTable.delete 运行。

    HBase 没有改动数据的合适方法。所以通过创建名为墓碑(tombstones)的新标志进行处理。这些墓碑和死去的值。在主紧缩时清除。

    參考 Section 5.8.1.5, “Delete” 获取删除列版本号的很多其它信息。參考Section 9.7.5.5, “Compaction” 获取很多其它有关紧缩的信息。
    5.8. 版本号

    一个 {row, column, version} 元组是HBase中的一个单元(cell).可是有可能会有非常多的单元的行和列是同样的,能够使用版本号来区分不同的单元.

    rows和column key是用字节数组表示的,version则是用一个长整型表示。这个long的值使用 java.util.Date.getTime() 或者 System.currentTimeMillis()产生的。

    这就意味着他的含义是“当前时间和1970-01-01 UTC的时间差,单位毫秒。

    在HBase中,版本号是按倒序排列的,因此当读取这个文件的时候,最先找到的是近期的版本号。

    有些人不是非常理解HBase单元(cell)的意思。

    一个常见的问题是:

    假设有多个包括版本号写操作同一时候发起,HBase会保存全部还是会保持最新的一个?[16]
    
    能够发起包括版本号的写操作。可是他们的版本号顺序和操作顺序相反吗?[17]
    

    以下我们介绍下在HBase中版本号是怎样工作的。[18].
    5.8.1. HBase的操作(包括版本号操作)

    在这一章我们来细致看看在HBase的各个主要操作中版本号起到了什么作用。
    5.8.1.1. Get/Scan

    Gets实在Scan的基础上实现的。

    能够具体參见以下的讨论 Get 同样能够用 Scan来描写叙述.

    默认情况下。假设你没有指定版本号。当你使用Get操作的时候,会返回近期版本号的Cell(该Cell可能是最新写入的,但不能保证)。默认的操作能够这样改动:

    假设想要返回返回两个以上的把版本号,參见Get.setMaxVersions()
    
    假设想要返回的版本号不仅仅是近期的,參见 Get.setTimeRange()
    
    要向查询的最新版本号要小于或等于给定的这个值,这就意味着给定的'近期'的值能够是某一个时间点。能够使用0到你想要的时间来设置。还要把max versions设置为1.
    

    5.8.1.2. 默认 Get 样例

    以下的Get操作会仅仅获得最新的一个版本号。

        Get get = new Get(Bytes.toBytes("row1"));
        Result r = htable.get(get);
        byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // returns current version of value          
    

    5.8.1.3. 含有的版本号的Get样例

    以下的Get操作会获得近期的3个版本号。

        Get get = new Get(Bytes.toBytes("row1"));
        get.setMaxVersions(3);  // will return last 3 versions of row
        Result r = htable.get(get);
        byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // returns current version of value
        List<KeyValue> kv = r.getColumn(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // returns all versions of this column       
    

    5.8.1.4. Put

    一个Put操作会给一个cell,创建一个版本号,默认使用当前时间戳。当然你也能够自己设置时间戳。这就意味着你能够把时间设置在过去或者未来,或者随意使用一个Long值。

    要想覆盖一个现有的值,就意味着你的row,column和版本号必须全然相等。
    5.8.1.4.1. 不指明版本号的样例

    以下的Put操作不指明版本号,所以HBase会用当前时间作为版本号。

          Put put = new Put(Bytes.toBytes(row));
          put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), Bytes.toBytes( data));
          htable.put(put);
    

    5.8.1.4.2. 指明版本号的样例

    以下的Put操作,指明了版本号。

          Put put = new Put( Bytes.toBytes(row ));
          long explicitTimeInMs = 555;  // just an example
          put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), explicitTimeInMs, Bytes.toBytes(data));
          htable.put(put);
    

    5.8.1.5. Delete

    有三种不同类型的内部删除标记 [19]:

    Delete: 删除列的指定版本号.
    
    Delete column: 删除列的全部版本号.
    
    Delete family: 删除特定列族全部列
    

    当删除一行,HBase将内部对每一个列族创建墓碑(非每一个单独列)。

    删除操作的实现是创建一个墓碑标记。比如,我们想要删除一个版本号,或者默认是currentTimeMillis。就意味着“删除比这个版本号更早的全部版本号”.HBase不会去改那些数据,数据不会马上从文件里删除。

    他使用删除标记来屏蔽掉这些值。[20]若你知道的版本号比数据中的版本号晚,就意味着这一行中的全部数据都会被删除。

    參考 Section 9.7.5.4, “KeyValue” 获取内部 KeyValue 格式很多其它信息。
    5.8.2. 现有的限制

    关于版本号另一些bug(或者称之为未实现的功能),计划在下个版本号实现。
    5.8.2.1. 删除标记误标新Put 的数据

    删除标记操作可能会标记其后put的数据。

    [21]记住,当写下一个墓碑标记后,仅仅有下一个主紧缩操作发起之后,墓碑才会清除。

    假设你删除全部<= 时间T的数据。但之后,你又运行了一个Put操作,时间戳<= T。就算这个Put发生在删除操作之后,他的数据也打上了墓碑标记。这个Put并不会失败,但你做Get操作时,会注意到Put没有产生影响。仅仅有一个主紧缩运行后。一切才会恢复正常。

    假设你的Put操作一直使用升序的版本号,这个问题不会有影响。可是即使你不关心时间,也可能出现该情况。仅仅需删除和插入迅速相互尾随,就有机会在同一毫秒中遇到。


    5.8.2.2. 主紧缩改变查询的结果

    “设想一下,你一个cell有三个版本号t1,t2和t3。你的maximun-version设置是2.当你请求获取全部版本号的时候。仅仅会返回两个,t2和t3。假设你将t2和t3删除,就会返回t1。可是假设在删除之前,发生了major compaction操作。那么什么值都不好返回了。[22]”

    5.9. 排序

    全部数据模型操作 HBase 返回排序的数据。

    先是行。再是列族。然后是列修饰(column qualifier), 最后是时间戳(反向排序,所以最新的在前).
    5.10. 列的元数据

    对列族,没有内部的KeyValue之外的元数据保存。这样。HBase不仅在一行中支持非常多列。并且支持行之间不同的列。 由你自己负责跟踪列名。

    唯一获取列族的完整列名的方法是处理全部行。HBase内部保存数据很多其它信息,请參考 Section 9.7.5.4, “KeyValue”.
    5.11. 联合查询(Join)

    HBase是否支持联合是一个网上常问问题。简单来说 : 不支持。至少不想传统RDBMS那样支持(如 SQL中带 equi-joins 或 outer-joins). 正如本章描写叙述的,读数据模型是 Get 和 Scan.

    但并不表示等价联合不能在应用程序中支持。仅仅是必须自己做。 两种方法,要么指示要写到HBase的数据,要么查询表并在应用或MapReduce代码中做联合(如 RDBMS所展示,有几种步骤来实现。依赖于表的大小。如 nested loops vs. hash-joins). 哪个更好?依赖于你准备做什么,所以没有一个单一的回答适合全部方面。


    个人笔记
    这里写图片描写叙述
    Client
    • 包括訪问HBase的接口并维护cache来加快对HBase的訪问
    Zookeeper
    保证不论什么时候,集群中仅仅有一个master
    存贮全部Region的寻址入口。
    实时监控Region server的上线和下线信息。并实时通知Master
    存储HBase的schema和table元数据
    Master
    为Region server分配region
    负责Region server的负载均衡
    发现失效的Region server并又一次分配其上的region
    管理用户对table的增删改操作
    RegionServer
    • Region server维护region,处理对这些region的IO请求
    • Region server负责切分在运行过程中变得过大的region
    Region
    HBase自己主动把表水平划分成多个区域(region),每一个region会保存一个表
    里面某段连续的数据;每一个表一開始仅仅有一个region,随着数据不断插
    入表,region不断增大,当增大到一个阀值的时候,region就会等分会
    两个新的region(裂变);
    当table中的行不断增多,就会有越来越多的region。这样一张完整的表
    被保存在多个Regionserver 上。
    Memstore 与 storefile
    一个region由多个store组成,一个store相应一个CF(列族) store包括位于内存中的memstore和位于磁盘的storefile写操作先写入memstore,当memstore中的数据达到某个阈值,hregionserver会启动flashcache进程写入storefile,每次写入形成单独的一个storefile 当storefile文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本号合并和删除工作(majar),形成更大的storefile当一个region全部storefile的大小和超过一定阈值后,会把当前的region切割为两个,并由hmaster分配到相应的regionserver服务器,实现负载均衡

    client检索数据,先在memstore找,找不到再找storefileHRegion是HBase中分布式存储和负载均衡的最小单元。最小单元就表示不同的HRegion能够分布在不同的 HRegion server上。
    – HRegion由一个或者多个Store组成,每一个store保存一个columns family。


    – 每一个Strore又由一个memStore和0至多个StoreFile组成。如图:StoreFile以HFile格式保存在HDFS上。
    这里写图片描写叙述
    这里写图片描写叙述

  • 相关阅读:
    Oracle EBS Form调用JavaBean前期配置
    Oracle EBS Form Builder使用Java beans创建窗体
    将 Oracle Forms 集成到 Oracle ADF Faces 中
    Oracle EBS开发习惯
    支持MOAC功能的Form开发步骤
    Form的Trigger的优先级
    所有标准API
    EBS中Java并发程序笔记(1)
    ORACLE FORM中,如何使用警告?
    .Net Core3.0 WebApi 六: Sqlsugar+异步泛型仓储
  • 原文地址:https://www.cnblogs.com/llguanli/p/8392823.html
Copyright © 2020-2023  润新知