在运行的RabbitMQ服务器用户PHP上,
我有一个事件,它会在"charge“队列中触发一条消息”将用户X帐户带到$5“。但是,许多事件可能会发送此消息,并且如果有多个工作人员在系统上工作,我可以看到一个问题,即出现竞争条件,用户获得双倍费用。
$accountBalance = -25.00 // starts
event 1: "Bring User X Account to $5"
event 1: check balance, $balance = -25.00
event 2: "Bring User X Account to $5"
event 1: $chargeAmount = 30
event 2: check balance, $balance = -25.00
event 1: Charge Card $30 // takes 3s
event 2: $chargeAmount = 30
event 2: Charge Card $30 // takes 6s
event 3: "Bring User X Account to $5"
event 3: check balance, $balance = -25.00
event 1: add transaction $30 // $accountBalance = 5.00
event 1: END
event 4: "Bring User X Account to $5"
event 4: check balance, $balance = 5.00
event 4: END
event 2: add transaction $30 // $accountBalance = 35.00
event 2: END
event 3: $chargeAmount = 30
event 3: Charge Card $30 // takes 3s
event 3: add transaction $30 // $accountBalance = 65.00
event 2: END
$accountBalance = 65.00正如你所看到的,4个事件进来了,而不是收费30美元一次,它收费三次。只有事件%4退出,但因为事件%1很快结束。
我尝试过锁的概念,但这有点含糊,因为每个worker可能都在一个独立的服务器上。
有没有容易使用的开箱即用的解决方案?
发布于 2015-10-24 04:24:37
您需要使用分布式锁来防止两个任务同时发生,同时使您的任务成为幂等任务。即使您有锁,任务也需要能够运行并检测到工作已完成并忽略。这两个概念协同工作。
您可以使用诸如memcached之类的东西来实现分布式锁定。例如,您可以尝试像LockBundle这样的东西。
$memcached = new Memcached();
$this->adapter = new MemcachedAdapter($memcached);
$lock = new Lock("test", $this->adapter);
$lock->acquire();
// Do stuff here //
$lock->release();只需使你的锁钥匙,无论你想要保护的粒度。但是,如果你想让一些东西对memcached崩溃具有弹性,那么围绕HA有一些问题。
您还可以使用数据库表构建类似的东西,在数据库表中,您在字段上有一个PK,并让流程尝试向表中插入值。PK将阻止任何第二次尝试,一旦第一次提交,随后的尝试将解除阻止并因违反PK而失败。
然后可能会使用Zookeeper之类的东西,尽管我从来没有这样做过。我认为这会比memcached更有弹性。
https://stackoverflow.com/questions/33310199
复制相似问题