我正在努力解决库存分配和并发的经典问题,我想知道是否有人可以指导我在这种情况下的最佳实践。
我的情况是,我们准备了一个带有多个“插槽”的订单,这些“插槽”将在流程的某个阶段由独特的库存物品填充,此时我想确保没有人将相同的唯一单元分配给一个插槽不同的顺序。例如,一个用户下周四想要一辆面包车,所以我保留了一个“面包车”插槽,但在稍后的时间点,我将一辆特定的车辆从院子里分配到这个插槽。我想确保两个不同的运营商下周四不能将同一辆货车分配给两个不同的客户。
我们已经有一个库存可用性检查流程,我们比较一个日期范围内的两个表的汇总,将这两个表相加的结果(一个是进货,另一个是出货)告诉我我们是否有我想要的特定项目想在这个日期分配给这个插槽,但我想防止另一个用户在同一时间点将相同的项目分配给他们自己的插槽。
我已经在这个站点上进行了一些谷歌搜索和研究,看起来我需要一个“悲观锁定”解决方案,但我不确定如何有效地实施。
分配过程将从具有实体框架的 Web API(使用 .Net 的其余 api)调用,我考虑了以下两种解决方案:
选项 1 - 让数据库处理它
在分配点,我开始一个事务并在用于评估库存可用性的两个表上获得一个排他锁。
该过程确认库存可用性,将单元分配到插槽,然后释放锁定。
我认为这将防止两个用户试图将相同的唯一单元分配给两个不同的订单的竞争条件,但我不喜欢为需要查询这些表的每个其他进程锁定两个表,直到分配过程完成,因为我认为这个可能会对尝试读取这些表的其他进程造成瓶颈。在这种情况下,我认为尝试执行重复分配的第二个进程应该排队,直到第一个进程释放锁,因为它无法查询可用性表,并且当它执行时它将无法通过可用性检查并报告缺货警告 - 如此有效地阻止第二个订单分配相同的库存。
从理论上讲,这听起来可行,但我有两个担忧;第一个是它会影响性能,第二个是我忽略了一些东西。我也是第一次在这个项目中使用 Postgres(我通常是一个 SQL Server 人),但我认为 Postgres 仍然具有执行此操作的功能。
选项 2 - 使用某种手动锁定
我认为我的情况类似于票务网站在音乐会或电影院的销售过程中遇到的情况,我看到他们设置了计时器,说“您的票将在 5 分钟内到期”,但我不知道他们是如何实现的后端的系统。他们是否在分配过程开始之前创建一个“保留”库存表,并在它们上设置某种到期时间,然后将其他尝试分配相同单位的用户“列入黑名单”,直到该计时器到期?
很抱歉,介绍很长,但我想完全解释这个问题,因为我已经看到很多关于类似场景的问题,但没有什么能真正帮助我决定如何继续。
我的问题是这两个选项中的哪一个(如果有的话)是“正确的方法”?
编辑:我见过的与这个问题最相似的是如何处理库存和并发,但它没有讨论选项 1(可能是因为这是一个糟糕的主意)