【HBase】10-版本

一个{行,列,版本}元组在HBase中指定了一个单元格。可以有无限个单元格,其中行和列相同,但单元格地址只在版本维度上不同。

虽然行和列键表示为字节,但是版本是使用一个长整数指定的。通常,这么长的时间包含由java.util.Date.getTime()或System.currentTimeMillis()返回的时间实例,即:当前时间与1970年1月1日UTC午夜之间的差,以毫秒为单位。

HBase版本维度是按递减顺序存储的,因此在从存储文件读取数据时,首先找到最新的值。

在HBase中,单元格版本的语义有很多混淆。特别是:

  • 如果对单元格的多次写操作具有相同的版本,则只有最后一次写操作是可获取的。
  • 按照非递增的版本顺序编写单元格是可以的。

下面我们将描述HBase中的版本维度目前是如何工作的。本文中提到的在现有时间戳上重写值的限制已不再适用于HBase。

1、指定要存储的版本数

为给定列存储的最大版本数是列模式的一部分,在表创建时指定,或者通过alter命令,通过HColumnDescriptor.DEFAULT_VERSIONS指定。在HBase 0.96之前,保留的默认版本数是3,但是在0.96和更新版本中已经更改为1。
示例修改列族的最大版本数,这个例子使用HBase Shell来保持列族f1中所有列的最多5个版本。您还可以使用HColumnDescriptor。

hbase> alter ‘t1′, NAME => ‘f1′, VERSIONS => 5

修改列族的最小版本数,还可以指定每个列族存储的最小版本数。默认情况下,它被设置为0,这意味着该特性是禁用的。下面的示例通过HBase Shell将列族f1中的所有列上的最小版本数设置为2。您还可以使用HColumnDescriptor。

hbase> alter ‘t1′, NAME => ‘f1′, MIN_VERSIONS => 2

从HBase 0.98.2开始,通过设置hbase.column.max.version,可以为所有新创建的列保留的最大版本数指定一个全局默认值。在hbase-site.xml版本。

2、版本和HBase操作

2.1、Get/Scan

get是在扫描之上实现的。下面关于Get的讨论同样适用于扫描。
默认情况下,也就是说,如果您没有指定显式版本,那么在执行get时,将返回版本最大的单元格(可能是已写入的最新版本,也可能不是,请参阅后面的内容)。默认行为可以通过以下方式修改:

  • 要返回多个版本,请参见Get.setMaxVersions()
  • 要返回最新版本以外的其他版本,请参见Get.setTimeRange()

要检索小于或等于给定值的最新版本,从而在某个时间点给出记录的“最新”状态,只需使用从0到所需版本的范围,并将最大版本设置为1。

2.2、默认Get行为的例子

下面的Get将只检索行的当前版本

public static final byte[] CF = "cf".getBytes();
public static final byte[] ATTR = "attr".getBytes();
...
Get get = new Get(Bytes.toBytes("row1"));
Result r = table.get(get);
byte[] b = r.getValue(CF, ATTR);  // returns current version of value

2.3、版本化Get的例子

下面的Get将返回该行的最后3个版本。

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

2.4、Put

执行put总是在某个时间戳上创建单元格的新版本。默认情况下,系统使用服务器的currentTimeMillis,但是您可以自己在每个列级别上指定版本(=长整数)。这意味着您可以指定过去或未来的时间,或者将长值用于非时间用途。

要覆盖现有值,请将put放在与要覆盖的单元格的行、列和版本完全相同的位置。

隐式版本的例子
下面的Put将由HBase根据当前时间隐式地进行版本控制。

public static final byte[] CF = "cf".getBytes();
public static final byte[] ATTR = "attr".getBytes();
...
Put put = new Put(Bytes.toBytes(row));
put.add(CF, ATTR, Bytes.toBytes( data));
table.put(put);

明确的版本的例子

下面的Put显式设置了版本时间戳。

public static final byte[] CF = "cf".getBytes();
public static final byte[] ATTR = "attr".getBytes();
...
Put put = new Put( Bytes.toBytes(row));
long explicitTimeInMs = 555;  // just an example
put.add(CF, ATTR, explicitTimeInMs, Bytes.toBytes(data));
table.put(put);

警告:HBase内部使用版本时间戳进行实时计算之类的事情。通常最好不要自己设置这个时间戳。更喜欢使用单独的行时间戳属性,或者将时间戳作为行键的一部分,或者两者兼而有之。

2.5、Delete

有三种不同类型的内部删除标记。

  • 删除:用于列的特定版本。
  • 删除列:用于列的所有版本。
  • 删除列族:用于特定列族的所有列

删除整个行时,HBase将在内部为每个ColumnFamily(而不是每一列)。

删除工作通过创建墓碑标记。例如,假设我们要删除一行。为此,您可以指定一个版本,或者默认情况下使用currentTimeMillis。这意味着删除所有版本小于或等于这个版本的单元格。HBase从不修改数据,因此,例如delete不会立即删除(或标记为已删除)存储文件中与delete条件相对应的条目。而是写了一个所谓的墓碑,用来掩盖被删除的值。当HBase执行重大压缩时,将对墓碑进行处理,以实际删除死值以及墓碑本身。如果删除行时指定的版本大于该行中任何值的版本,则可以考虑删除完整的行。

除非在列族中设置了KEEP_DELETED_CELLS选项(请参阅保存已删除的单元格),否则删除标记将在存储的下一个主要压缩过程中被清除。要在可配置的时间内保持删除,可以通过hbase.hstore.time.to.purge.deletes属性在hbase-site.xml中设置删除TTL。如果没有设置hbase.hstore.time.to.purge.delete,或者设置为0,那么所有的删除标记,包括那些将来带有时间戳的标记,都将在下一个主要压缩过程中被清除。否则,将保留带有时间戳的删除标记,直到主要压缩发生在由标记的时间戳表示的时间加上以毫秒为单位的hbase.hstore.time.to.purge.delete的值之后。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>