余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

非常详细!如何理解表格存储的多版本、生命周期和有效版本偏差

xiyangw 2023-10-11 17:14 136 浏览 0 评论

表格存储在8月份推出了容量型实例,直接支持了表级别最大版本号和生命周期,高性能实例也将会在9月中旬支持这两个特性。那么, 最大版本号 和 生命周期 以及特有的 有效版本偏差 该如何理解呢,在实际的使用上对我们又有什么帮助呢? 让我们来详细了解下吧!

数据多版本

想了解这三个概念都需要从数据多版本说起。当一行数据在写入后被多次更新,那么之前的每次更新其实都是一个历史版本,在很多场景下,历史更新的值是都需要能够查询的。比如大家都熟悉的物流快递,包裹从一个站点到下一个站点,一直到我们手中,中间的所有中转流程都是需要记录查询的,每到一个站点,实际上就是对快递状态的更新。

表格存储的数据模型(官方文档)如下:

从图中我们可以看到表格存储支持的多版本是到属性列级别的,也就是每条记录中的不用列可以有不同的版本号。

多个版本有了,那么该怎么标识这些不同版本的数据呢?

最简单的方式就是每个版本的数据设定一个版本号,然后递增,比如第一次写入版本号为1,更新一次为2,再更新一次就是3,一次累加,在查询的时候我们就可以根据版本号来查询,比如查询当前值,或者第二次更新的值(即版本号等于3的数据)。

那么,问题又来了,有些场景是需要记录数据更新的时间的,这种情况下是不是有更好的方法呢?

答案当然是肯定的,不光是1、2、3...是递增的,计算机里面的时间戳也是递增的,时间戳也就是 1970-1-1 00:00:00 UTC时间到当前写入时间的秒数,那么使用时间戳来作为数据的版本号既能起到标识各个版本数据的作用,还能够说明这个版本的数据的更新时间是什么时候,岂不是一举两得?

表格存储允许我们在写入数据时给每一个属性列指定版本号,如果不指定,那么在写入时服务端会根据当前时间的 毫秒单位时间戳(从1970-1-1 00:00:00 UTC计算起的毫秒数)为属性列生成版本号。我们指定的版本号系统也会按照毫秒换成时间戳来作为该条数据的诞生时间。

一定要注意,系统指定的版本号是毫秒哦!

一定要注意,系统指定的版本号是毫秒哦!

一定要注意,系统指定的版本号是毫秒哦!

多版本使用示例之快递状态查询

我们以上面提到的快递查询为例,为了支持快递状态的查询,一般情况下表的设计和数据是这样的:

使用多版本之后是这样的:

PS:上述的时间使用的是时间戳值,表格存储中是以毫秒为单位,换算成对应的时间为:

  • 1473441087:2016/09/10 01:11:27

  • 1473445407:2016/09/10 02:23:27

  • 1473444420:2016/09/10 02:07:00

  • 1473446531:2016/09/10 02:42:11

查询的时候可以可以指定查询所有的版本:

// 读一行

SingleRowQueryCriteria criteria = new SingleRowQueryCriteria(TABLE_NAME, primaryKey); // 设置读取所有版本

criteria.setTimeRange(new TimeRange(0, System.currentTimeMillis()));

GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));

Row row = getRowResponse.getRow();

或者查询版本号在最近一天范围的数据:

criteria.setTimeRange(new TimeRange(System.currentTimeMillis() - 86400000, System.currentTimeMillis()));

代码参考,使用起来是不是很方便呢?

最大版本数

数据版本多了之后,很多情况下只需要保留最近的若干个版本,而不需要保存全部版本,最大版本数就应孕而生。

用户可以设置一个数据表中给每个属性列最多保存的版本个数,用户将不能读到超过最大版本数的数据版本,系统也会在后台对这些版本的数据进行清理。

这样,最大版本数一方面可以自动清除不需要版本数据,另外一方面,可以在很多场景下简化使用方式,比如:

某互联网公司推出一款具有支付功能的APP,为了降低盗刷的风险,在每次支付时就需要运行一系列的风控计算架构设计。这些风控计算中,最基础的就是登录地址验证,保存用户最近10次的登录ip信息,对这10次ip进行校验,如果不是常用的ip或者区域差异太大,就需要用户重新解锁或者输入密码等。

那么在常规的使用方式上,一方面在读取时需要设置Top 10的参数,另一方面就需要记录所有的登录ip信息,定期删除最近10次以外的数据,使用最大版本数后:

int timeToLive = -1; // 数据永不过期

int maxVersions = 10; //更新最大版本数为10.

TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);

UpdateTableRequest request = new UpdateTableRequest(TABLE_NAME);// 更新表的最大版本数

//查询时设置一次查询出来的版本号

criteria.setMaxVersions(10);

GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));

代码参考

数据生命周期

数据多版本介绍完了,那么就会来带另外个问题,某个版本的数据我可以调用DeleteRow来删除,但是6个月之前的数据呢,总不能一条一条的删除吧?所以**数据生命周期**就登场了!

数据生命周期也就是表里面数据的存活时间,过时的数据就会被系统自动删掉,是不是既省钱又省事呢?

在工业监控、IoT设备数据、车联网、日志数据等时间序列的应用场景下,由于数据量巨大,只需要为应用或者设备保存最近3个月或者是半年的数据提供在线访问,更早的数据基本没有实时访问的需求,在这些数据的管理上数据生命周期就排上用场了!

接下来我们来看看数据过期的规则吧!

数据的诞生时间

表格存储会把每个属性列的版本号换算成毫秒后计算成距离1970-1-1 00:00:00 UTC的时间,并将该时间作为该个版本数据的诞生时间,比如:

  • 版本号为1468944000000,该版本的数据诞生时间就为2016-07-20 00:00:00

  • 版本号为1468944000,该版本的数据诞生时间就为1970-01-18 08:02:24

进行计算时,会先除以1000哦,原因是版本号是以毫秒为单位的。

数据的过期时间

当数据的诞生时间距离当前时间超过了TTL,那么这个版本的数据就过期了。

换句话说就是当前的时间换算成毫秒后减去该数据的版本号大于数据生命周期时,该数据就被认为是过期数据,继续举例说明:

数据生命周期为86400(一天),也就是数据只保留一天,写入的数据版本为: 1468944000000 即2016-07-20 00:00:00 。

过了 2016-07-21 00:00:00 之后,该数据就是过期数据了,我们将不再能读出这个版本的数据,并且表格系统后台将会启动清理任务,对过期数据进行清理。

计算逻辑:

1. 当前时间2016-07-21 00:00:01 换算为毫秒的时间戳为x,x=1469030401000

2. 数据的版本号y, y=1468944000000

3. ttl = 86400,换算成毫秒z,z=86400000

4. x-y = 86401000 > 86400000 ,该版本数据过期。

数据生命周期的注意事项

数据写入版本号要求

TTL为86400时,在2016-07-21 00:00:00之后写入版本号为1468944000000的数据,将会写入失败。原因是该条数据即使写成功,由于已经过期我们也无法读到这一个版本的数据,所以表格存储对过期的数据写入将会直接拒绝。因为:

  1. 写入时间t1 = 2016/07/21 00:00:01 (毫秒时间戳为:1469030401000)

  2. 写入的版本号为t2 = 1468944000000

  3. 数据生命周期 ttl = 86400 * 1000 = 86400000 (换算为毫秒)

  4. t1 - t2 = 86401000 > ttl,数据写入失败

调整TTL的数据读取行为

在使用过程汇总,我们会发现以下比较"奇怪"的行为:

TTL=172800, 查看时间:2016-09-10 15:43:19 一个属性列原始数据:

  • ts=1473332944000(2016/09/08 19:09:04),value=a

  • ts=1473339339000(2016/09/08 20:55:39),value=b

  • ts=1473408233000(2016/09/09 16:03:53),value=c

  • ts=1473452389000(2016/09/10 04:19:49),value=d

为了方便阅读,括号内为根据时间戳换算的字符串格式时间。

当我们将该张表TTL调整为86400时,读取所有的数据发现:

  • ts=1473408233000(2016/09/09 16:03:53),value=c

  • ts=1473452389000(2016/09/10 04:19:49),value=d

只能读到两个版本的数据,4个版本的数据中只有这两个版本号是在一天以内的,符合预期。

随后我们将该张表TTL调整回172800时,读取所有的数据发现:

  • ts=1473339339000(2016/09/08 20:55:39),value=b

  • ts=1473408233000(2016/09/09 16:03:53),value=c

  • ts=1473452389000(2016/09/10 04:19:49),value=d

只读到了3个版本的数据,并不是最初4个版本数据,说明版本数据 ts=1473332944000,value=a已经被系统回收。

有效版本偏差(MaxTimeDeviation)

经过了上面对多版本、最大版本数和数据生命周期的说明,是不是已经理解了他们的作用,但是有效版本偏差是有什么作用呢?

服务端在处理写请求时会对属性列的版本号进行检查,当版本号小于当前写入时间减去MaxTimeDeviation或者大于等于当前写入时间加上MaxTimeDeviation的值时,该行数据写入失败,换句话说就是在我们写入自定义的版本号时,我们写入的版本号需要在一个范围内才能写入成功。

这个有效范围就是:[数据写入时间-有效版本偏差,数据写入时间+有效版本偏差)

假设有效版本偏差为86400,在2016-07-21 00:00:00(毫秒时间戳为t0=1469030400000)写入数据时,数据的版本号就需要在下面的范围:[t1, t2)

  • t1 = t0 - 86400000 = 1468944000000,即2016/07/20 00:00:00

  • t2 = t0 + 86400000 = 1469116800000,即2016/07/22 00:00:00

也就是说写入的数据版本号需要在当前时间前后86400秒以内。

有效版本偏差作用

有效版本偏差的意义清楚了,但是这个功能的作用是什么呢? 且听我慢慢道来。

用户小A将数据表的属性设置为TTL=-1(数据永不过期),MaxVersions=100,在更新数据时,数据的版本号由程序从1开始累加,某个属性列更新了1000个版本,系统会保留最近的100个,版本号为[901,902,...999]。

但某天小A发现生命周期也挺不错的,想试试看,于是就使用UpdateTable接口将TTL设置成了86400,然后就惊讶的发现 所有的数据都读不出来了 ,于是想起来数据的过期规则,连忙将TTL设置回 -1 ,但是发现本应该存在的 100个版本 的数据只剩下了零散的 20个 ,这个时候,其他80个数据已经被系统回收删除了。

假如小A设置了MaxTimeDeviation为86400,版本号过小的数据写入都会失败,这样就避免了将TTL从-1设置为非0值而带来的大批数据过期情况的发生。

因为MaxTimeDeviation是一个非0值,所以如果需要写入诸如1、2这样的版本号,将MaxTimeDeviation设置为一个非常大的正值就可以啦,比如设置为1788856773(2026/09/08 16:39:33),在2026/09/08 16:39:33之前都可以成功的写入版本号为1的数据,当然,需要在TTL=-1的情况下,否者会因为ttl对数据版本号的要求,写入仍然会被系统拒绝哦~

关于更多表格存储的应用文章赶快戳这里吧!

相关推荐

“三次握手,四次挥手”你真的懂吗?

记得刚毕业找工作面试的时候,经常会被问到:你知道“3次握手,4次挥手”吗?这时候我会“胸有成竹”地“背诵”前期准备好的“答案”,第一次怎么怎么,第二次……答完就没有下文了,面试官貌似也没有深入下去的意...

面试官问:三次握手与四次挥手是怎么完成的?

作者|饶全成来源|码农桃花源记得刚毕业找工作面试的时候,经常会被问到:你知道“3次握手,4次挥手”吗?这时候我会“胸有成竹”地“背诵”前期准备好的“答案”,第一次怎么怎么,第二次……答完就没有...

三次握手和四次挥手的高阶面试题,建议收藏

昨天村长的讲解,真是一语点醒,这样的解释胜过死记硬背。但对于学习者,如果不能有直观感受,可能还是觉得不接地气,今天介绍两个工具,一个是网络抓包工具Wireshark,一个是linux命令tcpdum...

三次握手和四次挥手到底是个什么鬼东西

之前总有是有面试官喜欢问,你知道什么是三次握手么?什么是四次挥手么?为什么握手需要三次,挥手需要四次呢?今天我们就来详细的聊一下这个。1.什么是TCPTCP协议,简单称呼一下的话,那就是传输控制协议,...

加深理解TCP的三次握手与四次挥手

在了解三次握手和四次挥手之前,先要知道TCP报文内部包含了那些东西。熟悉了解TCP报文对日后学习网络和排除方面有很大的帮助,所以,今天为了加深对三次握手的理解,从新去认识TCP报文格式。TCP报文格式...

三次握手 与 四次挥手_三次握手四次挥手大白话

三次握手:①首先Client端发送连接请求报文②Server段接受连接后回复ACK报文,并为这次连接分配资源。③Client端接收到ACK报文后也向Server段发生ACK报文...

动画讲解TCP的3次握手,4次挥手,让你一次看明白

专注于Java领域优质技术,欢迎关注作者:老钱占小狼博客TCP三次握手和四次挥手的问题在面试中是最为常见的考点之一。很多读者都知道三次和四次,但是如果问深入一点,他们往往都无法作出准确回答。本篇尝试...

linux下实现免密传输文件或登录到其他服务器

使用scp传输文件到其他服务器的时候,提示需要输密码,如下:[root@18csetup]#scpLINUX.X64_180000_db_home.zip192.168.133.120:/u0...

Linux如何通过salt免密SCP传输上百台机的脚本?看chatGPT的回答

如何通过salt免密SCP传输上百台机的shell脚本”,下面是chatGPT给出的结果。scp批量免密脚本给出的详细shell脚本如下:#!/bin/bash#源文件路径和目标路径SRC_...

Linux/Mac scp命令上传文件_将hdfs上的文件下载到本地的命令是

语法scp[可选参数]file_sourcefile_target参数说明:-1:强制scp命令使用协议ssh1-2:强制scp命令使用协议ssh2-4:强制scp命令只使用IPv4寻...

Linux常用功能——文件远程传输_linux 远程传输文件

scp是securecopy的简写,是linux系统下基于ssh登陆进行安全的远程文件拷贝命令,用于在Linux下进行远程拷贝文件的命令。和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器...

使用 scp 命令定时拉取服务器备份文件

我们的服务器,每周五必须要做下备份,但总是忘记执行备份这件事情,或者是服务器备份做了,但没有做异地备份。所以通过定时任务自动备份,备份成功之后,在其它服务器上面通过定时任务scp命令自动拉取备份文...

windows下最轻便的FTP/SCP文件管理器

这次推荐的工具叫做winscp,这个工具如果是IT从业人员,又是做服务端相关工作的话,可能无人不知,如果是刚入门,推荐立马上手试试。如果看了觉得有用,欢迎收藏、点赞、关注。官方网站:https://w...

我不是网管 - Linux中使用SCP命令安全复制文件

SCP是linux发行版中的命令行工具,用于通过网络安全地跨系统复制文件和目录。SCP代表安全复制,因为它使用ssh协议复制文件。拷贝时,scp命令建立ssh连接到远程系统。换句话说...

WinSCP软件双系统(Win-Linux)文件传输教程

WinSCP软件是windows下的一款使用ssh协议的开源图形化SFTP客户端,也就是一个文件传输的软件,它有什么优点吗,咱们嵌入式开发中经常会将windows中的文件复制到linux系统当中,比较...

取消回复欢迎 发表评论: