电子商务应用程序设计(例如:Amazon / ebay / flipkart):并发问题处理

时间:2018-12-30 09:04:04

标签: java database concurrency transactions e-commerce

我一直试图了解亚马逊如何处理并发写入问题,例如当多个用户尝试购买可用数量仅为一个的同一产品时。

考虑到“ 产品”表具有以下字段:

enter image description here

我正在寻找关于数据库事务和锁定的详细解释,或者是以其他更详细的技术术语来处理这种情况的其他方式。

假设有2位用户在购物车中添加了相同的产品,而1位用户继续付款:

a)

开始交易

从* ID = 1 AND STATUS =“可用”的产品中进行*更新;

在产品表中将数量字段更新为“ 0”并且状态=“售罄”

致电付款网关

如果付款超时 回滚

提交

结束交易

================================================ =========================== 虽然交易仍在进行中,但其他用户仍可以看到该产品可用,因为该产品仍未提交,他们也可以继续付款。

此外,如果有足够数量的产品可用,则锁定产品行可能会阻止其他用户尝试同时购买同一产品。

================================================ ==========================

如何处理此问题?

我阅读了下面的博客,该博客对数据库使用乐观锁定,但是发现很难深入了解如何精确实现。

Design eCommerce Website - Concurrency

1 个答案:

答案 0 :(得分:2)

让两个事务同时运行上述代码,分别命名为tx1和tx2。 tx1和tx2都将首先尝试运行

SELECT * FROM PRODUCT WHERE ID = 1 AND STATUS = "AVAILABLE" FOR UPDATE; 

此查询意味着还从结果集中获取行上的锁。自然,只有一项交易可以获取它,因此另一项交易必须等待。例如,如果tx1获得了锁,则tx2将等到tx1提交并释放锁。然后,tx2也将继续并提交,因为它只是将数量设置为0。结果,上述方法将无法按需工作,因为最后,两个用户都会收到有关其购买的成功消息。但是,如果您想保留此方法,则不是直接将数量减少为1,而是将数量减少为1,并对列指出其值不能降至0以下的约束。以这种方式,tx2将失败由于违反约束(记住ACID的C-一致性)并回滚,因此第二个用户将收到一条消息,表明他/她的购买失败。

或者,如果您不想为此特定示例实施额外的约束并直接设置数量,则可以采用乐观锁定,该锁定使用透明的行版本控制,并且在性能方面也较便宜。因此,对于ID为1的产品(我们将其称为P),tx1会生成P的新版本(P1),而tx2同时会生成P的另一个新版本(P2)。当tx1和tx2中的任何一个尝试提交时,系统将注意到P有新的未提交版本,即P1和P2,并且将仅批准其中一个。结果,可以选择P1作为接受的P的新版本,从而tx1成功并且购买成功,并且P2被拒绝,因此tx2被中止并回滚,并且第二用户收到有关其购买的失败消息。另请注意,也可能发生相反的情况,即P2被接受而P1被拒绝。

最后,关于乐观和悲观锁定,请考虑以下因素:

  1. 如果应用程序开发人员估计冲突不一定会频繁发生,则首选乐观锁定
  2. 如果您不希望由于频繁的并发更新而导致频繁的失败,请使用悲观锁定。

我个人会选择悲观锁定,但要修复上述事务,因为对于数量大于1的交易,乐观锁定仍会导致一个事务中止,而使用悲观锁定都可以成功地完成这两个事务,但会降低性能。

  

虽然上述交易仍在进行中,但其他用户仍可以看到该产品,因为该产品仍未提交,他们也可能   继续付款。

关于此,它可能与用户屏幕的刷新率有关。即使用户能够继续付款(前端有陈旧的数据),后端也应验证用户是否有资格进行购买,如果是,则继续购买(所有这些都通过一次交易完成) )

  

此外,如果有足够数量的产品可用,则锁定产品行可能会阻止其他用户尝试同时购买同一产品。

这是悲观锁定的关键点,性能下降是此操作的主要影响,但是,只要数量不达到0,就可以处理所有事务。在乐观锁定中,只有1会成功,其他会失败,从而提示用户再次尝试购买。