数据多版本
表格存储的数据模型(官方文档)如下:
从图中我们可以看到表格存储支持的多版本是到属性列级别的,也就是每条记录中的不用列可以有不同的版本号。
最简单的方式就是每个版本的数据设定一个版本号,然后递增,比如第一次写入版本号为1,更新一次为2,再更新一次就是3,一次累加,在查询的时候我们就可以根据版本号来查询,比如查询当前值,或者第二次更新的值(即版本号等于3的数据)。
答案当然是肯定的,不光是1、2、3...是递增的,计算机里面的时间戳也是递增的,时间戳也就是 1970-1-1 00:00:00 UTC时间到当前写入时间的秒数,那么使用时间戳来作为数据的版本号既能起到标识各个版本数据的作用,还能够说明这个版本的数据的更新时间是什么时候,岂不是一举两得?
一定要注意,系统指定的版本号是毫秒哦!
一定要注意,系统指定的版本号是毫秒哦!
我们以上面提到的快递查询为例,为了支持快递状态的查询,一般情况下表的设计和数据是这样的:
使用多版本之后是这样的:
PS:上述的时间使用的是时间戳值,表格存储中是以毫秒为单位,换算成对应的时间为:
1473445407:2016/09/10 02:23:27
1473446531:2016/09/10 02:42:11
// 读一行
criteria.setTimeRange(new TimeRange(0, System.currentTimeMillis()));
Row row = getRowResponse.getRow();
criteria.setTimeRange(new TimeRange(System.currentTimeMillis() - 86400000, System.currentTimeMillis()));
最大版本数
用户可以设置一个数据表中给每个属性列最多保存的版本个数,用户将不能读到超过最大版本数的数据版本,系统也会在后台对这些版本的数据进行清理。
某互联网公司推出一款具有支付功能的APP,为了降低盗刷的风险,在每次支付时就需要运行一系列的风控计算架构设计。这些风控计算中,最基础的就是登录地址验证,保存用户最近10次的登录ip信息,对这10次ip进行校验,如果不是常用的ip或者区域差异太大,就需要用户重新解锁或者输入密码等。
int timeToLive = -1; // 数据永不过期
TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
//查询时设置一次查询出来的版本号
GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
数据生命周期
数据生命周期也就是表里面数据的存活时间,过时的数据就会被系统自动删掉,是不是既省钱又省事呢?
接下来我们来看看数据过期的规则吧!
表格存储会把每个属性列的版本号换算成毫秒后计算成距离1970-1-1 00:00:00 UTC的时间,并将该时间作为该个版本数据的诞生时间,比如:
版本号为1468944000,该版本的数据诞生时间就为1970-01-18 08:02:24
数据的过期时间
换句话说就是当前的时间换算成毫秒后减去该数据的版本号大于数据生命周期时,该数据就被认为是过期数据,继续举例说明:
过了 2016-07-21 00:00:00 之后,该数据就是过期数据了,我们将不再能读出这个版本的数据,并且表格系统后台将会启动清理任务,对过期数据进行清理。
1. 当前时间2016-07-21 00:00:01 换算为毫秒的时间戳为x,x=1469030401000
3. ttl = 86400,换算成毫秒z,z=86400000
数据生命周期的注意事项
TTL为86400时,在2016-07-21 00:00:00之后写入版本号为1468944000000的数据,将会写入失败。原因是该条数据即使写成功,由于已经过期我们也无法读到这一个版本的数据,所以表格存储对过期的数据写入将会直接拒绝。因为:
写入的版本号为t2 = 1468944000000
t1 - t2 = 86401000 > ttl,数据写入失败
在使用过程汇总,我们会发现以下比较"奇怪"的行为:
ts=1473332944000(2016/09/08 19:09:04),value=a
ts=1473408233000(2016/09/09 16:03:53),value=c
为了方便阅读,括号内为根据时间戳换算的字符串格式时间。
ts=1473408233000(2016/09/09 16:03:53),value=c
只能读到两个版本的数据,4个版本的数据中只有这两个版本号是在一天以内的,符合预期。
随后我们将该张表TTL调整回172800时,读取所有的数据发现:
ts=1473408233000(2016/09/09 16:03:53),value=c
只读到了3个版本的数据,并不是最初4个版本数据,说明版本数据 ts=1473332944000,value=a已经被系统回收。
有效版本偏差(MaxTimeDeviation)
服务端在处理写请求时会对属性列的版本号进行检查,当版本号小于当前写入时间减去MaxTimeDeviation或者大于等于当前写入时间加上MaxTimeDeviation的值时,该行数据写入失败,换句话说就是在我们写入自定义的版本号时,我们写入的版本号需要在一个范围内才能写入成功。
假设有效版本偏差为86400,在2016-07-21 00:00:00(毫秒时间戳为t0=1469030400000)写入数据时,数据的版本号就需要在下面的范围:[t1, t2)
t2 = t0 + 86400000 = 1469116800000,即2016/07/22 00:00:00
有效版本偏差作用
用户小A将数据表的属性设置为TTL=-1(数据永不过期),MaxVersions=100,在更新数据时,数据的版本号由程序从1开始累加,某个属性列更新了1000个版本,系统会保留最近的100个,版本号为[901,902,...999]。
假如小A设置了MaxTimeDeviation为86400,版本号过小的数据写入都会失败,这样就避免了将TTL从-1设置为非0值而带来的大批数据过期情况的发生。
关于更多表格存储的应用文章赶快戳这里吧!
