Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Redis&;Java中的多线程应用程序帮助!_Java_Multithreading_Transactions_Redis - Fatal编程技术网

Redis&;Java中的多线程应用程序帮助!

Redis&;Java中的多线程应用程序帮助!,java,multithreading,transactions,redis,Java,Multithreading,Transactions,Redis,我们有一个应用程序,目前正在线程化(大约50个线程)来处理事务 我们已经建立了一个redis数据库,并使用DECRBY从用户帐户中扣除积分 以下是该过程的一个示例: 1. Get amount of credits for this transaction 2. Get current credit amount from from Redis: GET <key> 3. If amount of credits exceeds amount cost of transaction

我们有一个应用程序,目前正在线程化(大约50个线程)来处理事务

我们已经建立了一个redis数据库,并使用
DECRBY
从用户帐户中扣除积分

以下是该过程的一个示例:

1. Get amount of credits for this transaction
2. Get current credit amount from from Redis: GET <key>
3. If amount of credits exceeds amount cost of transaction continue
4. DECRBY the transaction amount from Redis.
1。获取此交易的信用额度
2.从Redis获取当前信用额度:获取
3.如果信用额度超过交易成本额度,则继续
4.从Redis中扣除交易金额。
我在这里遇到的问题很明显,当用户积分达到0时,它确实会使事务失败(很好),但由于线程化,它允许大约10-20个事务通过

我曾想过用Redis设置
WATCH、MULTI、EXEC
,然后重试,但这不会造成瓶颈(我认为这就是所谓的竞争条件),因为线程将不断地争取完成事务


有什么建议吗?

在我看来,这不是最传统的方法(最常用的方法可能是在RDBMS中使用锁),但是使用
WATCH,MULTI,EXEC
看起来很像,对我来说也不太奇怪

我假设Redis的作者打算这样使用
WATCH
。性能含义显然取决于这件事是如何实现的(我不知道),但我打赌它会表现得相当好


这是因为在您的情况下,对相同密钥的争用似乎很少甚至几乎没有(用户疯狂地为他/她自己发布事务的可能性有多大?),第一次交换操作的成功率将非常高。因此,重试只会在极少数情况下发生。由于Redis似乎是一个可靠的框架,他们也可能知道自己在做什么(即,争用较少=Redis的工作容易,因此它可能可以处理!)。

锁定是您需要的。由于DB锁非常昂贵,您可以使用SETNX在Redis中实现一个简单的锁定方案,还可以避免竞争条件。这里有很好的解释-。但您仍然需要在应用程序级别实现重试。

您可以尝试使用框架提供的基于Redis的Java锁对象实现,而不是使用WATCH-MULTI命令重试。使用WATCH-MULTI时,每次尝试都会对Redis发出不必要的请求,这比已经获得的锁慢得多

以下是代码示例:

Lock lock = redisson.getLock("transationLock");
lock.lock();
try {
  ... // instructions
} finally {
   lock.unlock();
}

您是否希望我们确认向代码中添加事务/同步(这是正确性所必需的,您似乎知道),可能会引入争用,因此可能会影响性能?是的,会的。问题的重点是什么?我想知道的是,如果我使用WATCH、MULTI、EXEC,并重试,这是做事情的最佳方式吗?同时,确认使用此方法对性能造成的伤害。