HBase中的时间维度

HBase是一个类Bigtable系统,按照Google的论文对
Bigtable的定义是“一种稀疏的,分布式的,持久的多为维度的有序Map。这个Map由row key,column
key和timestamp做为索引,Map中的值是连续的byte数组”。HBase的多维度,包括table和column family等。

不是所有维度都是等同的,不同的维度有其特殊的意义。例如,row这个维度用于region切分,所以可以增长到海量。而column则不用于分
片,和row不同的是,一个row中的多个columns的put或者delete操作是一个原子事务(当然,同一个原子事务中不可能同事put和
delete)。而这篇文章将重点关注时间维度。

1. 基本概念

在Bigtable论文中,一个{row key,column
key}对应的是一个cell。每个cell可能包含多个版本的数据,以timestamp索引,这就是本文要讲述的时间索引。

1.1 时间/版本维度中的key

Row key)和column key(在HBase中也称为qualifier)是bytes类型,而时间维度的key则是long
integer类型,比较典型的是使用
java.util.Date.getTime()或者System.currentTimeMillis()来做为时间维度的key。

时间维度的各个版本是倒序排列后存储的,所以从storefile中读取的时候,最先读到的就是最新的时间,这个特性在系统设计的时候如果能有效利用,会非常有用。

下面我们从几个核心操作get,put和delete来看看时间维度的具体细节。

1.2 Get

默认情况下,Get操作会返回每个cell的timestamp值最大的版本(但这并不一定代表是最新写入的版本,后面会提到)。这个默认行为可以通过下面两种方式改变:
1.
通过设置 Get.setMaxVersions()可以返回多个版本的数据。
2. 通过设置
Get.setTimeRange()可以返回其他时间范围的版本。

如果要返回除最新版本之外的某个特定版本,可以通过组合上面两个条件来达成,首先设置时间范围为0到希望返回的时间,然后设置最多返回一个版本即可。

1.3 Put

每次执行Put,对应的cell都会插入一个新的版本。默认使用的是currentTimeMillis。应用也可以使用自定义的值来做为每个列的
timestamp,只需要是一个long
integer的值即可,不一定是时间,如果是时间,也可以是过去或者未来某个时间,所以前面说到方Get返回的是timestamp最大值的版本,而不
一定是最新写入的版本。

HBase的架构中,数据文件的写入只能附加(Append)而不能修改。数据文件只有在执行compact操作是才重写。数据文件中存储的是键值
对,其中键是{row key,column
key,timestamp}的组合键,每次put新的值的时候,会产生新的键值对附加在数据文件中,即时你使用一个已经存在的timestamp也一
样。因此短时间内对同一行做操作可能导致大量的键值对存储到文件中,根据gc的策略,下一次执行compact的时候才会回首老的版本。

1.4 Delete

关于Delete和时间维度有很多事要讲。

1.4.1 GC(垃圾收集)

HBase有两种方式回收旧的版本

1. 可以设置最多可以保留的版本数量。如果超过,则最老的版本会被抛弃,默认设置是3个版本,这个可以在创建Column
Family时通过HColumnDescriptor.setMaxVersions(int versions)设置,因此这个是Column
Family级别的。当然这个限制中读取的时候是逻辑限制,即时生效,但老版本的物理删除还是需要等到major
compact操作中执行。将这个值设置为1并不是说就禁用了多版本,每次Put的时候还是同样的会生成新的版本,只是最后只保留一个版本而已。

2. 可以设置TTL(Time To Live),如果版本存在的时间超过TTL,则会被删除。默认的TTL是forever。通过
HColumnDescriptor.setTimeToLive(int seconds)可以设置TTL,物理清除版本还是要等到major
compact,但Get/Scan等读取操作逻辑是即时生效的。需要注意的是,如果row中所有的cell都被TTL失效以后,这一行记录就被删除了
(HBase中不需要显示的建立或者删除行,如果行中的cell有值,行就存在)。

对于上面的两种回收方式,会有一种有趣的场景,假设你对一个cell插入了三个版本t1,t2,t3,而最大版本数设置是2,这时候请求所有版本,
则只有t2和t3会返回,这是正常的。但这时如果删除t2或者t3,再请求所有版本,则t1可能又会出现在结果中了。当然,在major
compact操作之后,就不会有这个问题了。因此major compact并不是对用户透明的操作,可能会影响用户的查询结果。

1.4.2 Manule delete

中HBase中执行delete操作时,有两种方式可以删除某个特定的版本

1. 删除某个timestamp之前的所有老版本
2. 删除某个timstamp点的版本

delete操作可以针对row,column
family,或者column,只有最后一种情况下可以删除某个timestamp点的版本。而针对row和column
family的delete,则只能删除某个timestamp之前的所有版本。

举个例子,假设我们要删除一整行数据,你可以指定timestamp,或者使用currentTimeMillis,那“删除某个
timestamp之前的所有老版本”意味着什么呢?HBase并不会去修改原有数据,因此删除不是立即在原数据对应的文件中执行物理删除或者物理标记删
除,而是将删除的记录保存中所谓的tombstone中,当HBase执行major compact的时候,再根据tombstone去执行物理删除。

如果你指定的timestamp比row中最新的版本大,则相当于删除了整行数据。

2. 使用timestamp

从上面的描述可以看到,时间维度主要是用户多版本的,但你也可以在应用中把它当作column外的另外一个维度来使用,不同的是它的key是长整数型,目前这种方式还存在一些bug,因此还不是很推荐。

在jira中,有两个和时间维度有关的bug值得比较有意思

1. 利用时间维度多版本实现HBase多数据中心复制,参看HBASE-1295 (PDF附件的第四页)
或者这个邮件。
2. HBASE-2406的一个评论提到,如果要在多个表中获得一致性数据(如二级索引表),可以通过向多个表写入相同的timestamp版本来实现。

3. 限制

由于一些bug或者“不可预期的行为”,时间维度目前还有一些问题需要解决。

1. HBASE-1485 和HBASE-2406中
提到的覆写已经存在的timetamp版本的值的问题(在0.90版本中已经解决),换句话说,根据{row key ,column key,
timestamp}修改某个cell的值,实际会产生一个新的键值对,对于HBase来说就会存在两个相同timestamp的key,判断最大
timestamp版本就会有问题。当然,通过HBASE-2649中提到的写入到HFile的时间序可以解决这个问题。

2. HBASE-2256中
提到的delete覆盖put(即使put操作发生在delete之后)的问题。由于delete只是记录tombstone,物理删除需要等到 major
compact操作,因此有一种情况,你删除了所有<=T的版数据,然后又put了一条<=T的数据,还是会被tombstone标记为删
除。当然,如果你使用的是递增的timestamp不会有这个问题,但如果使用系统时间,而delete和put间隔时间非常短,还是有一定几率两个操作
的timestamp是相同的,这时候杯具依然会存在。

转载自:http://www.cnblogs.com/JemBai/archive/2012/07/21/2602439.html

时间: 2024-08-28 08:37:41

HBase中的时间维度的相关文章

mysql中生成时间维度表

利用mysql常用日期函数生成时间维度表,效率最高,最简单,无需其他的一些工具支持.生成结果示例如下图: # time span SET @d0 = "2012-01-01"; SET @d1 = "2012-12-31"; SET @date = date_sub(@d0, interval 1 day); # set up the time dimension table DROP TABLE IF EXISTS time_dimension; CREATE T

hbase中regionserver进程没过一段时间就会down

各位,哪位大神帮忙看一下,cdh5.9.2环境中hbase中的regionserver服务没过一段时间就会down 本人已经确认不是时间同步问题,下面是具体的regionserver日志信息 2018-05-05 15:12:42,461 INFO org.apache.hadoop.hbase.util.VersionInfo: HBase 1.2.0-cdh5.9.22018-05-05 15:12:42,480 INFO org.apache.hadoop.hbase.util.Versi

淘宝在hbase中的应用和优化

本文来自于NoSQLFan联合作者@koven2049,他在淘宝从事Hadoop及HBase相关的应用和优化.对Hadoop.HBase都有深入的了解,本文就是其在工作中对HBase的应用优化小结,分享给大家. 目 录 [ - ] 前言 原因 应用情况 部署.运维和监控 测试与发布 改进和优化 将来计划 前言 hbase是从 hadoop中分离出来的apache顶级开源项目.由于它很好地用java实现了google的bigtable系统大部分特性,因此在数据量猛增的今天非常受到欢迎.对于淘宝而言

【HBase】zookeeper在HBase中的应用

转自:http://support.huawei.com/ecommunity/bbs/10242721.html Zookeeper在HBase中的应用 HBase部署相对是一个较大的动作,其依赖于zookeeper cluster,hadoop HDFS. Zookeeper作用在于: 1.hbase regionserver 向zookeeper注册,提供hbase regionserver状态信息(是否在线). 2.hmaster启动时候会将hbase系统表-ROOT- 加载到 zook

《BI项目笔记》创建时间维度(2)

创建步骤:   序号 选择的属性 重命名后的名称 属性类别 1 DateKey DateKey 常规 2 Month Key Month Key 月份 3 English Month Name English Month Name 每年的某一月 4 Month Number Of Year Month Number Of Year 常规 5 Calendar Quarter Key Calendar Quarter Key 季度 6 Calendar Quarter Calendar Quart

《BI项目笔记》创建时间维度(1)

原文:<BI项目笔记>创建时间维度(1) SSAS Date 维度基本上在所有的 Cube 设计过程中都存在,很难见到没有时间维度的 OLAP 数据库.但是根据不同的项目需求, Date 维度的设计可能不大相同,所以在设计时间维度的时候需要搞清楚几个问题: 你的业务涉及到的最低的细节级别是什么?比如按季度查看报表还是按月份,或者按周,或者再甚者按天.这个细节级别需要弄清楚,比如在一些销售数据统计,有的时候可能更多按季度或者按月来查看报表.但在有的监控一些机器运行数据的统计,可能会按照小时或者分

Spark读取Hbase中的数据_云帆大数据分享

Spark读取Hbase中的数据 大家可能都知道很熟悉Spark的两种常见的数据读取方式(存放到RDD中):(1).调用parallelize函数直接从集合中获取数据,并存入RDD中:Java版本如下: 1 JavaRDD<Integer> myRDD = sc.parallelize(Arrays.asList(1,2,3)); Scala版本如下: 1 val myRDD= sc.parallelize(List(1,2,3)) 这种方式很简单,很容易就可以将一个集合中的数据变成RDD的初

ZooKeeper原理及其在Hadoop和HBase中的应用

简介 ZooKeeper是一个开源的分布式协调服务,由雅虎创建,是Google Chubby的开源实现.分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅.负载均衡.命名服务.分布式协调/通知.集群管理.Master选举.分布式锁和分布式队列等功能. 基本概念 本节将介绍ZooKeeper的几个核心概念.这些概念贯穿于之后对ZooKeeper更深入的讲解,因此有必要预先了解这些概念. 集群角色 在ZooKeeper中,有三种角色: Leader Follower Observer 一

Hbase中的BloomFilter(布隆过滤器)

(1)     Bloomfilter在hbase中的作用 Hbase利用bloomfilter来提高随机读(get)的性能,对于顺序读(scan)而言,设置Bloomfilter是没有作用的(0.92版本以后,如果设置了bloomfilter为rowcol,对于执行了qualifier的scan有 一定的优化) (2)     Bloomfilter在hbase中的开销 Bloomfilter是一个列族(cf)级别的配置属性,如果在表中设置了bloomfilter,那么hbase会在生成sto