在 SQL Azure 联合上生成序列号的有效方法

Posted

技术标签:

【中文标题】在 SQL Azure 联合上生成序列号的有效方法【英文标题】:Efficient way to generate sequential numbers on SQL Azure Federations 【发布时间】:2012-03-27 10:14:39 【问题描述】:

考虑到 SQL Azure 联合不支持 IDENTITY 属性或 SEQUENCE,在插入记录时生成序列号的有效方法是什么?

例如,给定一个包含这些列的表:

CREATE TABLE [dbo].[Orders] (
    [TenantId] [uniqueidentifier] NOT NULL,
    [OrderId] [uniqueidentifier] NOT NULL,
    [OrderNumber] [int] NOT NULL
    CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED (
        [TenantId] ASC,
        [OrderId] ASC
    )
) FEDERATED ON ([FederationKey] = [TenantId])

对于为给定租户插入的每个订单,OrderId 应递增。例如,对于租户 A,OrderId 将是 1、2、3...,而对于租户 B,OrderId 也将是 1、2、3...,按独立顺序排列。理想情况下应该没有间隙。

TenantId 和 OrderId 是主键的组成部分。它们的值由应用程序设置,与生成序列的问题无关;只有 OrderId 有具有业务意义的序号。此外,TenantId 是联邦的分发密钥。

This MSDN Blog article 在选项 1 中描述了一种方法,即拥有一个保存序列的表并在隔离事务中使用存储过程来增加序列。每个租户都会在该表上拥有一条记录,保存该序列的最后使用值。

考虑到可扩展性、争用、资源锁定,这会是最佳方法吗?考虑到 SQL Azure 联合的限制,还有其他有用的技巧吗?

【问题讨论】:

【参考方案1】:

这里有 2 个额外的想法。

如果这对您的业务场景来说是可行的,那么一种方法是让一个单独的流程更新该字段以使其异步。对于这种方法,您需要让 OrderNumber 字段接受 NULL 值。要知道哪个订单先出现,以便获得正确的 OrderNumber,我还要添加一个 InsertedDate 字段。如果您有多个工作角色执行此任务以实现冗余,则异步处理会变得更加复杂,在这种情况下,您需要让每个进程为自己分配正在处理的记录(因此您还需要一个 OwnedBy 字段),在此期间添加一个并发测试UPDATE 以确保每个进程都在其自己的记录上执行,并在进程崩溃时使记录的分配过期(因此您还需要一个 AssignedOn 字段)以便它不会留下孤儿。不是很简单...

然后你就有了穷人的方法……当星星排列得恰到好处时,这可能就是你所需要的。如果您愿意采用乐观并发方法,请尝试在插入期间使用下一个 Number(首先为给定的 TenantId 和 OrderId 选择 MAX OrderNumber),然后执行插入。如果插入失败(因为您为此目的在 TenantId、OrderNumber 上添加了唯一索引),只需将 1 添加到 OrderNumber。这里真正的问题是重试的频率和这种方法失败的可能性。如果您有一个相对简化的业务流程,这实际上可能永远不会失败;但是,如果您从多个渠道不断添加订单,这可能是一种不可接受的方法。

【讨论】:

很好的答案,除了我在问题中引用的选项(使用存储过程使用单独的连接更新记录)之外,您的第一个替代方案以一些复杂性为代价提供了出色的可伸缩性和吞吐量;第二种选择非常简单,当流程被简化(例如使用消息队列)或每个租户的新订单创建率不太高时可能就足够了。【参考方案2】:

不确定需要多少努力才能适应您的场景,但也可以看看这个,看看您是否可以调整它:SnowMaker – a unique id generator for Azure (or any other cloud hosting environment)

【讨论】:

这是一个很好的资源。感谢您引起我的注意。本地批处理可以非常有效并且可以很好地扩展,但代价是序列中的间隙和数字不按时间顺序排列,这对于内部 ID 来说非常好,但在应用于业务控制数字时会引发(毫无根据的)担忧。 你还推荐使用这个吗?

以上是关于在 SQL Azure 联合上生成序列号的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

在 chromecast 接收器应用程序上生成或获取 UUID 或序列号

SQL Azure 联合和索引 - 性能说明

Azure SQL Active Directory集成身份验证,联合域

如何为 Azure Blob 存储中的文件夹生成共享访问签名?

从另一个类调用方法在 xcode 上生成 SIGABRT 错误

如何在 IIS 上生成负载?