所谓的 version 其实就是同一条数据插入不同的时间戳来实现的, 在 hbase 底层的存储是基于时间戳排序的, 所以每次我们查到的数据都是最新的版本, 除非我们指定了要读取特定的时间范围的数据.
我们知道 hbase 是一个多版本的管理系统, 在 0.96 的版本之前默认每个列是 3 个 version, 在 hbase 0.96 之后每个列是 1 个 version, 所谓的 version 其实就是同一条数据插入不同的时间戳来实现的, 在 hbase 底层的存储是基于时间戳排序的, 所以每次我们查到的数据都是最新的版本, 除非我们指定了要读取特定的时间范围的数据.
先看下 Hbase 里面 Put 和 Delete 命令的 api:
Put:
Delete:
如上, 常用的 pu 和 delete 方法基本都是第一个, 默认我们使用 Put 命令插入一条数据后, 它的时间戳取的是当前时间戳, 当然我们也可以自己设置时间戳, 但是我建议不要随便设置这个时间戳, 设置的不对有可能引起一些莫名奇妙的问题, 刚才说过 hbase 在读取的时候是按时间降序排序的, 每次读取到的都是最新的, 那么假如在 put 的时候设置这个时间戳为 Long.MAXVALUE, 那么后面你在插入, 删除或者更新的时候没有传入时间戳, 那么你就会惊奇的发现插入, 删除, 更新全部失效, 为什么?
因为你该次操作的时间戳小于 Long.MAXVALUE, 而且你的 version 只有一个, 所以 hbase 认为一个旧的版本是不能覆盖新的版本的, 同样删除也是, 你会发现无论你执行多少次删除命令, 该条数据就是不能够被删除掉.
注意, 在上面的 api 中 Put 和 Delete 的第二个方法都是带时间戳的, 大家不要误解, 这个时间戳不是 rowkey 的, 它这个时间戳是给下面的 column 用的, 也就是说如果插入一行数据, 这行数据中有多个列簇, 每个列簇下面都有多个列的话, 而且他们的时间戳都一样, 那么我就可以直接在 put 的第二个参数指定, 而不需要在每个 column 上指定, 当然如果我们在 column 上也指定了时间戳, 那么默认优先使用 column 上的时间戳.
总结:
hbase 的多版本存储特性是一个强大的功能, 在使用的时候应该注意尽量不要修改默认取当前时间戳的逻辑, 如果修改了那么在其他添加, 删除, 更新的时候都应该考虑当前的时间戳是否大于第一次插入时的时间戳, 如果不是, 那么本次修改就不会生效, 所以某一天当你删除一行 hbase 数据时, 发现它并没有被删除掉, 不要惊讶, 在代码没有问题的情况下, 最大的可能就是当前时间戳小于库里数据的时间戳, 这一点需要特别注意, 最后再重复一遍, 尽量不要在向 hbase 插入数据的时候设置自定义的时间戳, 除非业务场景需要.
来源: http://stor.51cto.com/art/201804/571073.htm