【问题标题】:Optimal solution for massive number of requests on one database table一张数据库表海量请求的最优解决方案
【发布时间】:2018-03-25 04:16:41
【问题描述】:

我们有一个系统,按照先到先得的原则为客户分配产品。

我们的产品表包含一个从零开始的递增主键,我们使用它来跟踪已分配的产品数量,即用户预订产品并分配 1,下一个用户获得 2,以此类推。

问题在于,可能有数十万用户在任何给定时间访问系统。所有人都将打到这张桌子。

由于我们需要确保每个客户只分配一个产品并跟踪分配了多少产品,我们为每个访问系统的客户使用行锁,以确保他们在下一个客户点击之前写入表系统 - 即执行先到先得的规则。

我们担心进入 SQL Server 2008 企业版的每个请求的处理时间和行锁的瓶颈。

我们不能使用多台服务器,因为我们需要确保主键的完整性,因此任何需要复制的东西都无法正常工作。

有没有人知道在处理一个数据库表上的大量请求时特别有效的任何好的解决方案?

更多信息:
有问题的表基本上只包含两个字段 - ID 和 CustomerID。解决方案是免费赠送一百万种产品——因此期望高需求以及为什么使用递增的主键作为键对我们来说是有意义的——一旦键达到一百万,就没有更多的客户可以注册。此外,产品都不同,因此分配正确的密钥很重要,例如前 100 位进入的客户收到的产品价值高于后 100 位等

【问题讨论】:

  • 明显的第一个问题;您是否从获取密钥的事务中剥离了所有其他内容?例如。在尝试获取钥匙之前,您知道所有您需要知道的事情,在做其他事情之前去桌子拿钥匙并解锁?
  • 嗨,卡尔,是的,没错。其他所有内容都去掉了 - 使交易尽可能轻量级 - 只需获取客户 ID,然后进行插入并向用户显示新的主键 - 恭喜,您是客户 xxxxx,您将获得免费奖品。

标签: sql sql-server database


【解决方案1】:

首先,为了消除密钥生成的问题,我会提前生成它们。它只有 1m 行,这意味着您不必担心管理密钥生成过程。这也意味着您不必担心意外生成太多行,因为一旦填满表,您将只执行 UPDATE,而不执行 INSERT。

这里的一个重要问题是,所有 1m 项是否都相同?如果是,那么键的顺序无关紧要(或者即使它们有顺序),所以当客户提交请求时,您只需“尝试”更新表,大致如下:

UPDATE TOP(1) dbo.Giveaway -- you can use OUTPUT to return the key value here
SET CustomerID = @CurrentCustomerID
WHERE CustomerID IS NULL

IF @@ROWCOUNT = 0 -- no free items left
PRINT 'Bad luck'
ELSE
PRINT 'Winner'

另一方面,如果 1m 项不同,那么您需要另一种解决方案,例如项目 1 是 X,项目 2-10 是 Y,11-50 是 Z 等等。在这种情况下,按照提交请求的顺序将客户分配给键很重要,因此您可能应该研究某种排队系统,也许使用服务代理。每个客户向队列中添加一个请求,然后存储过程一次处理一个请求,并为他们分配 MAX 空闲密钥,然后返回他们赢得的详细信息。

【讨论】:

  • SET ROWCOUNT 在 SQL 2008 中已弃用。改用 UPDATE TOP(1)msdn.microsoft.com/en-us/library/ms188774%28v=sql.100%29.aspx
  • @EdHarper 是的,这是一个很好的观点,我已经更新了我的示例。尽管 OP 的关键信息当然是,只要您只更新一个行,您更新哪一行并不重要。
  • 感谢 Pondlife。这些项目是不同的,所以听起来排队是要走的路,只是接受在高峰时间处理每个请求会有一些延迟。我正在考虑的另一种解决方案是将所有奇数放在一个数据库中,而将偶数放在另一个数据库中,然后有一个带有简单位开关的负载均衡器将交替的客户发送到一个数据库 - 对此有什么想法吗?我猜我可能会将瓶颈转移到负载均衡器上,这可能最终也需要队列?感谢您的帮助,非常感谢。
  • @CaisManai 我根本不会拆分数据,因为这样您就有太多变量无法确保系统会按您的预期处理数据。我想这取决于您要投入多少努力来确保“按顺序”处理请求,尽管“按顺序”在多层应用程序中实际上意味着什么本身就是一个有趣的问题。但我怀疑出于法律原因,您将需要(至少在理论上)能够向审核员展示您“公平”和“按顺序”处理请求,因此我会尽可能简化您的解决方案。
猜你喜欢
  • 2011-01-17
  • 1970-01-01
  • 2016-03-12
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多