java 中 Rest Services 分布式环境中解决 Race condition 的不同方法
Different ways for solving Race condition in distributed environment in Rest Services in java
这是我现在面临的一个问题的描述
- 我想根据用户是否进行过给予促销折扣的交易来给予一些促销
- 促销折扣是交易的一定折扣
- 所以条件是,在处理交易之前,将检查他是否使用促销完成交易,并根据该金额计算。
问题是如果两个请求同时出现并且读取交易尚未完成,并且在两个请求上都应用了交易提升。
找到解决方案,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 中的某一行。我现在不知道那个项目的信仰,但直到今天我仍然喜欢这个想法。
底线是有很多选项,真的。这在很大程度上取决于您所参与的基础架构和团队。
这是我现在面临的一个问题的描述
- 我想根据用户是否进行过给予促销折扣的交易来给予一些促销
- 促销折扣是交易的一定折扣
- 所以条件是,在处理交易之前,将检查他是否使用促销完成交易,并根据该金额计算。
问题是如果两个请求同时出现并且读取交易尚未完成,并且在两个请求上都应用了交易提升。
找到解决方案,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 中的某一行。我现在不知道那个项目的信仰,但直到今天我仍然喜欢这个想法。
底线是有很多选项,真的。这在很大程度上取决于您所参与的基础架构和团队。