如果一个购物网站只有 1 种产品可用,而 2 个人同时尝试购买,谁会得到该产品?服务器将如何确定用户的优先级。对亚马逊上的闪购感到好奇,翻转卡丁车"。哪种算法?
以下是幕后可能发生的情况,使用任何现代应用程序框架都很容易实现。
我假设您的情况是:
- 登录到您系统的两个用户表示他们
U1
并U2
- 选择一个产品
- 只有一种产品可用
- 他们都点击了添加到购物车/立即购买/结帐
- 将服务一个用户,并通知另一个用户该产品不再可用
假设T1
和T2
是他们单击结帐按钮时时间的纳秒表示形式。T1
和T2
相等的机会非常低,但有可能。
在您的情况下,Web 服务器将在两个不同的线程(TH1
和TH2
中为用户生成的请求提供服务。这是极不可能的,因为在任何给定时间,您的系统中都有数百个用户,但假设您有多个内核,TH1
和TH2
由 CPU 的两个不同内核提供服务并非不可能。
因此,TH1
和TH2
都将尝试保留您的产品。
现在你需要在你的PRODUCT
中拥有/引入两个属性(想想MySQL列):VERSION
和CHECKED_OUT
。
TH1
和TH2
将同时启动自己的事务,例如TR1
和TR2
,假设您将InnoDB作为数据库引擎。
TR1
和TR2
都将:
- 从数据库表中读取
PRODUCT
以及VERSION
和CHECKED_OUT
:{id: 1, version: 0, checked_out: 0, ...}
并将其传输到服务器。 - 在服务器中,
TR1
和TR2
都将增加之前读取的VERSION
值,并执行 Update 语句,指出UPDATE PRODUCT SET CHECKED_OUT = 1, VERSION = 1 WHERE ID = 1 AND VERSION = 0
- DB 将锁定行,执行
UPDATE
并以顺序方式返回修改行的编号,因为UPDATE
应在单个线程中执行。请注意,此线程是DB自己的线程,而不是TR1
和TR2
。 - 在这里,如果我假设
TR1
,即TH1
在TR2
之前被服务,即由DB的UPDATE
线程TH2
,那么TR1
后面的业务逻辑将得到更新的行数等于1,而TR2
的行数将得到0。 - 这反过来意味着
U1
可以检查产品,而U2
会收到一条很好的道歉信息。