java 中 Rest Services 分布式环境中解决 Race condition 的不同方法

Different ways for solving Race condition in distributed environment in Rest Services in java

这是我现在面临的一个问题的描述

  1. 我想根据用户是否进行过给予促销折扣的交易来给予一些促销
  2. 促销折扣是交易的一定折扣
  3. 所以条件是,在处理交易之前,将检查他是否使用促销完成交易,并根据该金额计算。

问题是如果两个请求同时出现并且读取交易尚未完成,并且在两个请求上都应用了交易提升。

找到解决方案,https://dzone.com/articles/synchronized-by-the-value-of-the-object-in-java,但对分布式环境无效。

有什么不同的方法可以解决这样的程序。只是很好奇这个问题>

有多种方法可以实现这一点。使用可序列化事务隔离级别访问 table 是一种方法。但是,由于您提到该过程还涉及可能较长的 运行 外部调用,因此您可以采用这样的两阶段方法:

  • 开始交易
  • 使用“select for update”来搜索并锁定赋予用户晋升权利的记录。
  • 检查促销是否已被使用。如果是,提交交易,促销不可用。如果否,则提交事务。促销可用。
  • 拨打外部电话
  • 开始交易并再次进行促销检查,“select 用于更新”,但这次也插入使用促销的记录

分布式环境需要分布式锁。这里有很多选项,为此我们使用了 zookeeper,我的其他一些团队使用了 redis。我也知道(理论上)hazelcast也有这样的原理;我敢打赌还有更多。

在分布式环境中,您需要考虑一些稍微复杂的事情。如果“提供”锁定机制的服务死了怎么办,如果获得锁的客户端永远不会释放它(它可能死掉或永远在内部阻塞)等等。第一个有容错策略,第二个有容错策略第二个(释放超时或锁的“自动断开”)。

前段时间我在一家公司工作,该公司针对 MSSQL 数据库“手动”执行此操作。他们所做的(我只是该服务的消费者)是创建一个 java-agent 来检测字节码,并在某些执行点连接到数据库并尝试“CAS”(比较-and-swap) table 中的某一行。我现在不知道那个项目的信仰,但直到今天我仍然喜欢这个想法。

底线是有很多选项,真的。这在很大程度上取决于您所参与的基础架构和团队。