10

我正在使用 StorageClient 库更新 AzureTableStorage 中的对象

    context.UpdateObject(obj);
    context.SaveChangesWithRetries(obj);

当我这样做时,有没有办法在obj不向服务器发出另一个请求的情况下获取新的时间戳?

谢谢

斯图尔特

4

5 回答 5

14

为了补充Seva Titov 的回答:报告的摘录至少在 2013 年 5 月之前有效,但截至 2013 年 11 月它已经改变(强调添加):

Timestamp 属性是在服务器端维护的 DateTime 值,用于记录上次修改实体的时间。表服务在内部使用 Timestamp 属性来提供乐观并发。Timestamp 的值是一个单调递增的值,这意味着每次修改实体时,该实体的 Timestamp 值都会增加。不应在插入或更新操作上设置此属性(该值将被忽略)。

现在该Timestamp属性不再被视为不透明,并且记录在每次编辑后其值都会增加 - 这表明Timestamp现在可以用于跟踪后续更新(至少对于单个实体而言)。

尽管如此,截至 2013 年 11 月,当您更新实体时,仍需要向表存储发出另一个请求以获取新的时间戳(请参阅更新实体REST 方法的文档)。只有在插入实体时,REST 服务才会返回带有时间戳的整个实体(但我不记得这是否由 StorageClient/Windows Azure 存储库公开)。

于 2013-11-09T19:44:00.377 回答
13

MSDN 页面有一些关于 Timestamp 字段的使用指南:

时间戳属性

Timestamp 属性是在服务器端维护的 DateTime 值,用于记录上次修改实体的时间。表服务在内部使用 Timestamp 属性来提供乐观并发。您应该将此属性视为不透明的:不应读取它,也不应在插入或更新操作时设置它(该值将被忽略)。

这意味着它实际上是表存储的实现细节,您不应该依赖 Timestamp 字段来表示上次更新的时间戳。

如果您想要一个保证表示上次写入时间的字段,请创建新字段并在每次更新操作时设置它。我知道这是维护该字段的更多工作(和更多存储空间),但这实际上会自动解决您的问题 - 如何取回时间戳,因为您在调用 context.UpdateObject() 时已经知道它。

于 2011-03-31T23:17:06.653 回答
4

Timestamp属性实际上是一个Lamport 时间戳。它保证总是随着时间的推移而增长,虽然它被呈现为一个DateTime价值,但实际上并非如此。

在服务器端,即 Windows Azure 存储,每次更改都会执行以下操作:

nextTimestamp = Math.Max(currentTimestamp + 1, DateTime.UtcNow)

这就是它的全部。当然,它肯定会以交易方式发生。所有这一切的重点是提供一个逻辑时钟(单调函数),可用于确保事件的顺序以预期的顺序发生。

这是实际WAS 论文版本的链接,虽然它不包含有关时间戳方案的任何信息,但它有足够的内容,您很快就会意识到您只能从中得出一个合乎逻辑的结论。其他任何事情都是愚蠢的。此外,如果您对 LevelDB、Cassandra、Memtables 等有任何经验,您会发现 WAS 团队也走同样的路。

虽然我应该补充说明一下,因为 WAS 提供了一个强一致性模型,维护时间戳的唯一方法是在锁定和密钥下进行,因此您无法猜测正确的下一个时间戳。您必须向 WAS 查询信息。没有办法解决这个问题。但是,您可以保留旧值并假定它没有改变。WAS 会告诉您是否存在,然后您可以以任何您认为合适的方式解决竞争条件。

于 2017-03-14T06:05:36.160 回答
0

我不这么认为,据我所知 Timespan 和 Etag 是由 Azure Storage 本身设置的。

于 2011-03-31T21:46:25.463 回答
0

我正在使用Windows Azure 存储 7.0.0

您可以检查操作结果以获取eTagTimespan属性:

var tableResult = cloudTable.Execute(TableOperation.Replace(entity));
var updatedEntity = tableResult.Result as ITableEntity;

var eTag = updatedEntity.ETag;
var timestamp = updatedEntity.Timestamp;
于 2016-04-10T23:48:14.340 回答