文章目录
在HBase 0.98版本之后,HBase引入了一种额外的元数据(meta data)——tag来标识一个cell( HBASE-8496)。本文就主要介绍一下什么是cell tag。
如何标识一个cell?
首先,先来介绍一下HBase是如何来定位一个cell的。HBase通过以下几个要素来定位一个cell:表(table),行(rowkey),列族(column family),列标识(column qualifier),时间戳(timestamp)。这存在的一个问题是,无法对每个cell单独进行细粒度的参数设置,比如无法对某个cell设置TTL,无法对某个cell设置ACL,无法对某个cell设置visibility。对于cell的所有设置必须都是基于行或者列进行的。
cell tag的设计
为了解决以上的问题,HBase 0.98版本之后,引入了HBase cell tag这一设计。首先,重新设计了HFile,将HFile的版本升级到了version 3。HFileV3兼容了之前的HFile版本,只是在key-value存储结构之后增加了tag length和tags array两端。tag length标明了tag array的长度,tag array则是tag的具体内容。设计如下所示:
<keylength><valuelength><keyarray><valuearray><taglength><tagarray>
此外,每个cell可以包含多组tag,我们对tag array进行进一步细分,可以得到每组tag的数据结构。
<2 byte tag length><1 byte type code><tag>
在HBase 2.3版本中,Cell接口类实现了以下三种方法,帮助外部客户端获取cell的tag。当然这些方法在HBase 2版本中已经被置为deprecated状态,并将在HBase 3中被删除。
/**
* Contiguous raw bytes representing tags that may start at any index in the containing array.
* @return the tags byte array
* @deprecated As of HBase-2.0. Will be removed in HBase-3.0. Tags are are now internal.
*/
@Deprecated
byte[] getTagsArray();
/**
* @return the first offset where the tags start in the Cell
* @deprecated As of HBase-2.0. Will be removed in HBase-3.0. Tags are are now internal.
*/
@Deprecated
int getTagsOffset();
/**
* HBase internally uses 2 bytes to store tags length in Cell.
* As the tags length is always a non-negative number, to make good use of the sign bit,
* the max of tags length is defined 2 * Short.MAX_VALUE + 1 = 65535.
* As a result, the return type is int, because a short is not capable of handling that.
* Please note that even if the return type is int, the max tags length is far
* less than Integer.MAX_VALUE.
*
* @return the total length of the tags in the Cell.
* @deprecated As of HBase-2.0. Will be removed in HBase-3.0. Tags are are now internal.
*/
@Deprecated
int getTagsLength();
HBase 2.3支持的cell tag种类
根据HBase 2.3 TagType类代码所示,HBase当前支持7种Tag,用户可以从客户端显式设定cell的ACL,TTL,Visibility等属性。
public final class TagType {
// Please declare new Tag Types here to avoid step on pre-existing tag types.
public static final byte ACL_TAG_TYPE = (byte) 1;
public static final byte VISIBILITY_TAG_TYPE = (byte) 2;
// public static final byte LOG_REPLAY_TAG_TYPE = (byte) 3; // deprecated
public static final byte VISIBILITY_EXP_SERIALIZATION_FORMAT_TAG_TYPE = (byte)4;
// mob tags
public static final byte MOB_REFERENCE_TAG_TYPE = (byte) 5;
public static final byte MOB_TABLE_NAME_TAG_TYPE = (byte) 6;
// String based tag type used in replication
public static final byte STRING_VIS_TAG_TYPE = (byte) 7;
public static final byte TTL_TAG_TYPE = (byte)8;
}
如何添加和获取cell的tag?
在默认情况下,HBase不会为cell添加任何tag,并且目前HBase shell客户端也不支持添加和获取cell tag。因此,假如我们需要单独为某个cell添加tag,或者获取某个cell tag的时候,必须通过HBase Java客户端进行。
添加cell tag
我们以设定cell TTL tag为例,如下所示,在创建put对象的时候,只需要调用setTTL方法即可对这个put对象中的所有cell设置TTL。
Put putExample = new Put("rowkey".getBytes())
.addColumn("columnfamily".getBytes(), "column qualifier".getBytes(), "value".getBytes());
putExample.setTTL(TTL_time);
table.put(putExample);
获取cell tag
当我们创建get请求获取HBase result之后,可以通过如下代码获取cell的tag。
Get get = new Get(Bytes.toBytes(<key>));
Result rs = table.get(get);
if (rs!=null) {
Cell cell = rs.getColumnCells(..);
Iterator<Tag> i = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
while (i.hasNext()) {
Tag t = i.next();
if (TagType.TTL_TAG_TYPE == t.getType()) {
long ts = cell.getTimestamp();
assert t.getTagLength() == Bytes.SIZEOF_LONG;
long ttl = Bytes.toLong(t.getBuffer(), t.getTagOffset(), t.getTagLength());
System.out.println(ttl);
}
}
}
cell tag和column family attribute的优先级
默认情况下,HBase不会对cell设置任何tag,因此加入该cell所在的column family设置的attribute会对该cell生效。当cell显式设定了tag之后,cell tag的优先级会高于column family attribute的优先级。