想象一下,你正在开发一个电子商务系统,成千上万的人试图同时购买剩余的产品。然而,他们中的许多人可以继续结账并完成订单。当你检查库存时,你的产品数量为负。这是如何可能的,你应该如何解决这个问题?
让我们编码吧!您可能会想到的第一件事就是在结账前检查库存。也许是这样:
public void validateAndDecreaseSolution(long ProductId, int 数量 { 可选<stockentity> stockByProductId = stockRepository.findStockByProductId(productId); int stock = stockByProductId.orElseThrow().getStock(); int possibleStock = 库存 - 数量; if (股票 <p>您可以使用此验证,但当我们谈论每秒几百、几千、几百万甚至几十个请求时,这种验证是不够的。当 10 该请求同时到达代码,数据库为 stockByProductId 当返回相同值时,您的代码将崩溃。当 10 该请求同时到达代码,数据库为 stockByProductId 当你回到同一个值时,你的代码就会崩溃。当我们验证时,你需要一种方法来阻止其他请求。</p> <h3> 第一个解决方案 - 用于更新 </h3> <p>在 SELECT 添加锁定语句。我在这个例子中使用它 Spring Data 的 FOR UPDATE 完成此操作。正如 PostgreSQL 文档所说</p> <blockquote> FOR UPDATE 会导致 SELECT 语句检索到的行被锁定,就像更新一样。在当前交易结束之前,它们可以被其他交易修改或删除。 </blockquote> <pre class="brush:php;toolbar:false">@Query(value = "从股票 s 中选择 * WHERE s.product_id = ?1 FOR UPDATE", nativeQuery = true) 可选<stockentity> findStockByProductIdWithLock(Long ProductId); </stockentity>
public void validateandecreasesolution(long ProductId, int amount) { 可选<stockentity> stockByProductId = stockRepository.findStockByProductIdWithLock(productId); // ... 证实 stockRepository.decreaseStock(productId, 数量); } </stockentity>
在实际交易完成之前,所有使用产品ID对stocks表格的请求都将等待。这里的目标是确保您获得股票的最新更新价值。
立即学习“Java免费学习笔记(深入);
第二种解决方案 - pg_advisory_xact_lock这个解决方案和上一个类似,但是你可以选择什么是锁定键。我们将锁定整个交易,直到所有验证和库存减少完成。
public void acquirelockAndecreasolution(long ProductId, int amount) { 查看nativeQuery =entityManager.createNativeQuery("选择pg_advisory_xact_lock(:lockId)"); nativeQuery.setParameter("lockId",productId); nativeQuery.getSingleResult(); 可选<stockentity> stockByProductId = stockRepository.findStockByProductId(productId); // 必要时检查库存并抛出异常 stockRepository.decreaseStock(productId, 数量); } </stockentity>
交易结束后,下一个请求只会与同一ID的产品交互。
第三种解决方案 - WHERE 子句在这种情况下,我们不会锁定线路或事务。让我们允许这个事务继续,直到更新句子。请注意最后一个条件:库存 > 0.这将不允许我们的库存小于零。因此,如果两个人试图同时购买,其中一个会收到错误,因为我们的数据库不允许库存
@交易 @修改 @Query(nativeQuery = true, value = "更新库存 SET stock = stock - :quantity WHERE Product_id = :productId AND stock > 0") int reduceStockWhereQuantityGreaterThanZero(@Param("productId") Long ProductId, @Param("quantity") int amount);
第一个和第二个解决方案使用悲观锁作为策略。第三个是乐观锁。当您希望在执行任何涉及资源的任务时限制资源访问时,可以使用悲观锁定策略。在您完成过程之前,目标资源将被锁定以进行任何其他访问。小心锁!
使用乐观锁,您可以在没有任何障碍的情况下查询同一资源。当冲突不太可能发生时使用。通常,您会有一个与您的行相关的版本,当您更新行时,数据库会将您的行版本与数据库中的行版本进行比较。若两者相等,则变更将成功。如果没有,你必须再试一次。正如你所看到的,我在这篇文章中没有使用任何版本,但我的第三个解决方案不会阻止任何请求和使用 stock > 0 并发控制条件。
若要查看完整的代码,可以查看我的GitHub。
实现悲观锁定和乐观锁定的策略还有很多,比如你可以搜索更多 FOR UPDATE WITH SKIP LOCKED 的信息。
以上就是如何使用 Java 和 PostgreSQL 更多关于竞争条件的详细信息,请关注其他相关文章!
Todesk远程操作受限:文字复制粘贴失效!
如何使用 Java 和 PostgreSQL 处理竞争条件-java教程
代理服务器:网络中转站,保障数据安全与匿名。
电脑软件备份首选:高效、安全、易用的XX软件!
掌握 Java 的 SOLID 原则:实用指南-java教程
国行PS5备份港服,系统升级无忧!
买服务器还是租云?明智之选,云上先行!
掌握 Java 的 SOLID 原则:实用指南-java教程
将 Honsole 与 Spring Security 结合使用-java教程
System.out.println(\"Java简介\")-java教程
案例研究:查找目录大小-java教程
Java教程二进制输入/输出
AWS Lambda 上的 Spring Boot 应用程序 - 使用 Spring Cloud Function AWS java教程部分开发应用程序
java教程
如何在 JUnit 5 中模拟真实性 BeforeAll 和 AfterAll-java教程
外卖骑手 1 周超 3 二次交通违规将停止订单,广州新规敦促配送企业按最高限度进行配送 25km/h 设定时限-IT行业
作者
在哪里实施混合办公:从下周开始,每周三、五名员工可以灵活选择办公地点,无需审批——IT行业
Moka CTO 刘洪泽:在大模型时代,组织和人才结构将迎来新的变化——人工智能