我们知道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插入数据的时候设置自定义的时间戳,除非业务场景需要。