简体   繁体   English

在 Rest 中解决分布式环境中竞态条件的不同方法 java 中的服务

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

Here is a description of a problem that I am facing right now这是我现在面临的问题的描述

  1. I want to give user some promotion based on whether he has done a transaction in which he has been given a promotional discount我想根据用户是否进行交易并获得促销折扣来给他一些促销
  2. Promotional discount is some percent off on the transaction促销折扣是交易的一些折扣
  3. So the condition is, before processing transactions, it will be checked whether he as done a transaction using a promotion or not, and based on that amount will be calculated.所以条件是,在处理交易之前,将检查他是否使用促销进行了交易,并根据该金额进行计算。

Problem is if two request comes at the same time and reads that a transaction has not been done, and on both the transaction promotion is applied.问题是如果两个请求同时出现并读取事务尚未完成,并且在这两个请求上都应用了事务提升。

Found a solution, https://dzone.com/articles/synchronized-by-the-value-of-the-object-in-java , but not valid for distributed environment.找到了解决方案https://dzone.com/articles/synchronized-by-the-value-of-the-object-in-java ,但对分布式环境无效。

What are can be different ways to solve such a program.解决此类程序的不同方法是什么。 Was just very curious on this problem >只是对这个问题很好奇>

Distributed environments require distributed locks.分布式环境需要分布式锁。 And there are a lot of options from here, we have used zookeeper for this, some other team of mine used redis .这里有很多选择,我们为此使用了zookeeper ,我的其他一些团队使用redis I also know (theoretically) that hazelcast has such a principle also;我也知道(理论上) hazelcast也有这样的原理; I bet there are many more.我敢打赌还有更多。

There are some things you need to consider in a distributed environment that slightly complicate things.在分布式环境中,您需要考虑一些使事情稍微复杂的事情。 What if the service that "provides" the locking mechanism dies, what if the client that acquired a lock never releases it (it might die or block internally forever), etc. There are fault tolerant policies for the first and there are mechanisms for the second (a timeout for release or an "auto-disconnect" of the lock).如果“提供”锁定机制的服务死掉了,如果获得锁的客户端永远不会释放它(它可能永远死掉或在内部永远阻塞),等等。首先有容错策略,并且有机制第二(释放超时或锁的“自动断开”)。

Some time ago I worked for a company that did this "by hand" against a MSSQL database.前段时间,我在一家公司工作,该公司针对 MSSQL 数据库“手动”执行此操作。 What they did (I was only a consumer of that service), is create a java-agent that would instrument byte-code and, at some points of execution would connect to a database and try to "CAS" (compare-and-swap) a certain row in a table.他们所做的(我只是该服务的消费者)是创建一个 java-agent 来检测字节码,并在某些执行点连接到数据库并尝试“CAS”(比较和交换) 表格中的某一行。 I don't know the faith of that project now, but I still love the idea to this day.我现在不知道那个项目的信念,但直到今天我仍然喜欢这个想法。

Bottom line is that there are many options, really.底线是有很多选择,真的。 It highly depends on your infrastructure and team that you are involved in.这在很大程度上取决于您参与的基础架构和团队。

There are different ways this can be achieved.有不同的方法可以实现这一点。 Accessing the table using serializable transaction isolation level is one way.使用可序列化事务隔离级别访问表是一种方法。 However, since you mentioned the process involves potentially long running external calls as well, then you can do a two-phase approach like this:但是,由于您提到该过程也可能涉及长时间运行的外部调用,因此您可以执行如下两阶段方法:

  • Start a transaction开始交易
  • Use "select for update" to search and lock the record that entitles the user with a promotion.使用“选择更新”来搜索和锁定授权用户进行促销的记录。
  • Check if the promotion is used already.检查促销是否已被使用。 If yes, commit the transaction, promotion is not available.如果是,则提交交易,促销不可用。 If no, commit the transaction.如果否,则提交事务。 Promotion is available.有促销活动。
  • Do your external calls打你的外线电话
  • Start a transaction and do the promotion check again, with "select for update", but this time, insert the record for using the promotion as well启动事务并再次进行促销检查,使用“select for update”,但这次也插入使用促销的记录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM