当HBase表配置Search索引后,带时间戳的写入将会被禁止掉(非索引列不会禁止带时间戳写入),会抛出User defined timestamp is not allowed when external index is enabled...的Exception。

  • 默认不支持自定义时间戳写入。
  • 不支持多版本。
  • 有限支持表TTL。

1. 自定义时间戳

  1. 使用的场景一定要带入时间戳;
  2. 写入HBase的数据是通过BDS同步过来(如主备同步,RDS的增量导入等),BDS有可能会加上写入时间戳。

可以通过使用HBaseue Shell访问增强版集群修改表的Mutability属性为MUTABLE_ALL来打开对自定义时间戳的支持。打开时间戳支持会有一些性能损耗,但通常不会非常明显。

# 打开时间戳支持
hbase(main):002:0> alter 'testTable', MUTABILITY=> 'MUTABLE_ALL'
# 关闭时间戳支持
hbase(main):002:0> alter 'testTable', MUTABILITY=> 'MUTABLE_LATEST'

2. 多版本

当HBase表配置Search索引后,如果数据表有多版本,会导致HBase与Search实例的数据不一致。需要通过使用HBaseue Shell访问增强版集群显示的将HBase表版本修改为1。另外,也不再支持删除指定的某个版本,这种删除行为将会被禁止。举例来说

    //如果构造的Delete对象不加任何Family和Qualifier,则代表删除整行 --支持
    Delete delete = new Delete(Bytes.toBytes("row"));
    //删除f:q1这一列 --支持
    delete.addColumns(Bytes.toBytes("f"), Bytes.toBytes("q1"));
    //删除时间戳在ts1和ts1之前的所有数据  -- 开自定义时间戳(MUTABLE_ALL)后支持
    delete.addColumns(Bytes.toBytes("f"), Bytes.toBytes("q1"), ts1);
    //删除f这个family里所有的列 --支持
    delete.addFamily(Bytes.toBytes("f"));
    //删除f这个family里时间戳在ts1和ts1之前的所有列数据 -- 开自定义时间戳(MUTABLE_ALL)后支持
    delete.addFamily(Bytes.toBytes("f"), ts1);
    //删除f:q1这一列的最新版本  --不支持
    delete.addColumn(Bytes.toBytes("f"), Bytes.toBytes("q1"));
    //删除f:q1这一列中时间戳(版本)为ts1的数据  --不支持
    delete.addColumn(Bytes.toBytes("f"), Bytes.toBytes("q1"), ts1);

注意: 为了防止数据不一致,在HBase中执行删除某一行后,Search中对应的Document不会删除,而是会删除这个Document中除了id这个field(Rowkey映射)以外的其他所有field。一般情况下,用户都是带一定条件去查询Search,不会命中这种只有id的行。但如果查询到只有id的行,代表此行已经删除,用户需要自行过滤。我们后续将考虑使用Search的TTL功能在一定时间后自动删除这些行。

3. TTL

HBase和Search都支持数据TTL过期,但是HBase的TTL机制与Search的TTL机制不一样,HBase是单个KV过期,而Search中只能按照Document(对应HBase的一行)过期,而且过期的时间不会完全一致。如果业务中需要支持TTL,可以单独联系云HBase答疑或提工单。