Azure 表存储上的自动增量
Posted
技术标签:
【中文标题】Azure 表存储上的自动增量【英文标题】:Auto-increment on Azure Table Storage 【发布时间】:2010-12-24 15:04:36 【问题描述】:我目前正在为 Azure 表存储开发一个应用程序。在那个应用程序中,我有一个插入相对较少的表(每天几千个),并且这些实体的主键将在另一个表中使用,该表将有数十亿行。
因此,我正在寻找一种使用自动递增整数而不是 GUID 作为小表中的主键的方法(因为它会节省大量存储空间,并且插入的可伸缩性并不是真正的问题)。
已经有一些关于该主题的讨论,例如在http://social.msdn.microsoft.com/Forums/en/windowsazure/thread/6b7d1ece-301b-44f1-85ab-eeb274349797。
但是,由于并发问题很难调试和发现,我对自己实现它有点不舒服。因此,我的问题是,是否有经过充分测试的实施?
【问题讨论】:
如果你真的很担心,在 SQL azure 中有一个表来生成标识值吗? 这是一个很好的建议。但是,这将迫使我设置我的 SQL 服务器,因为 Azure SQL 数据服务不支持标识列:shanmcarthur.net/cloud-services/…。 【参考方案1】:对于将在搜索中找到它的每个人,都有一个更好的解决方案。 Minimal time for table lock is 15 seconds - 太糟糕了。如果您想创建一个真正可扩展的解决方案,请不要使用它。使用Etag
!
在表中为 ID 创建一个实体(您甚至可以将其命名为 ID 或其他名称)。
1) 阅读。
2) 增量。
3) InsertOrUpdate WITH 指定ETag
(来自读取查询)。
如果最后一次操作 (InsertOrUpdate
) 成功,那么您将拥有一个新的、唯一的、自动递增的 ID。如果失败(HttpStatusCode
== 412 除外),则意味着其他一些客户端更改了它。因此,再次重复 1,2 和 3。
Read+InsertOrUpdate
的通常时间小于 200ms。我的测试工具with source on github。
【讨论】:
如何使用 EGT 来保证原子操作、读取和增量?这是一种可行的方法吗? docs.microsoft.com/en-gb/azure/storage/…【参考方案2】:请参阅 Josh Twist 的 UniqueIdGenerator class。
【讨论】:
那篇博文太棒了! 文章中的代码现在可以在这里找到:docs.microsoft.com/en-us/archive/msdn-magazine/2010/november/…【参考方案3】:我还没有实现这个,但正在努力......
您可以使用下一个要使用的 ID 为队列播种,然后在需要时将它们从队列中取出。
您需要保留一个表格来包含添加到队列中的最大数字的值。如果你知道你不会使用大量的整数,你可以让一个工作人员每隔一段时间醒来,并确保队列中仍然有整数。您还可以使用一个已使用的 int 队列,工作人员可以检查以密切关注使用情况。
您也可以连接该工作人员,因此如果当您的代码需要一个 id 时队列为空(偶然),它可能会中断工作人员的小睡以尽快创建更多密钥。
如果该调用失败,您将需要一种方法(告诉工作人员您将为他们完成工作(锁定),然后让工作人员获取下一个 id 并解锁)
-
锁
获取从表中创建的最后一个键
增加并保存
解锁
然后使用新值。
【讨论】:
但是队列如何保证不会创建重复的 id?我从download.microsoft.com/download/5/2/D/… 可以理解的是,如果工作进程在处理队列消息时失败,则会再次将消息添加到队列中。因此,您需要使工作者角色上的工作具有幂等性。如果两个不同的工作角色使用相同的消息(即相同的 ID),我看不出如何使该消息具有幂等性。 如果您只有 1 个woker 创建 id,则 dups 将被放入队列中。将 id 从队列中拉出时,获取消息,然后在使用消息的内容 (id) 之前删除消息。这应该确保没有 id 被多次使用。似乎更糟糕的情况是您可能会丢失密钥,但您的唯一性应该仍然很好。 上面的第二句话应该是:“如果你只有 1 个创建 id 的woker,那么 dups 就不会被放入队列中......”【参考方案4】:我发现防止重复 ID 并让您自动递增的解决方案是
lock (lease) a blob 并让它充当逻辑门。
然后读取值。
写入增量值
释放租约
在您的应用/表格中使用该值
如果您的工作人员角色在该过程中崩溃,那么您的商店中只会丢失一个 ID。恕我直言,这比重复更好。
这是史蒂夫·马克思关于这种方法的code sample and more information
【讨论】:
【参考方案5】:如果您确实需要避免使用 guid,您是否考虑过使用基于日期/时间的方法,然后利用分区键将并发风险降至最低。
您的分区键可以是用户、年、月、日、小时等,而行键可以是日期时间的其余部分,时间跨度足够小以控制并发性。
当然,您必须问问自己,以 Azure 中的日期为代价,避免使用 Guid 是否真的值得所有这些额外的努力(假设 Guid 可以正常工作)。
【讨论】:
以上是关于Azure 表存储上的自动增量的主要内容,如果未能解决你的问题,请参考以下文章