在我正在进行的项目中,我们称之为挑战。挑战有成员和参与者。成员是可以访问挑战的每个人(可以是单个用户或用户组),参与者可以跟踪每个用户的参与统计信息。
每次添加新挑战成员时,都会重新计算挑战参与者。这发生在基于事件的情况下,因此挑战成员会触发一个created
事件,挑战参与者会侦听。
当同时创建两个质询成员时会出现问题,这意味着事件也会被触发两次,并且两次执行代码会同时运行。举例说明:
challenge.getMembers();
challenge.getParticipants();
// calculations
foreach member not in participants, create participant
如上所述,当上述代码同时运行时出现问题,更具体地说,当第一次执行在第一次创建缺少的参与者条目之前达到getParticipants
时。两个执行都看到一些参与者失踪,并创建它们。这意味着我们现在为某些用户提供了重复参与者的重复条目。
现在我们解决此问题的方法是在挑战参与者的challenge_id, user_id
上拥有唯一索引。然而,在违反约束时忽略错误确实感觉有点脏。它还使得检查其他SQL错误变得更加困难,因为所有错误都只是传递给回调,然后我们必须检查错误字符串的内容以查看它是否是我们喜欢的错误(唯一性违规),或者我们不喜欢的错误(例如错误的语法),应该处理。
此代码将在多个服务器上运行,因此即使使用mutices,我们也无法保证代码不会同时运行。我们也不介意它同时针对不同的挑战运行,只要它不会同时针对同一挑战运行。有没有人有处理这种类型的并发合并的建议?
答案 0 :(得分:0)
由于您说您不介意同时针对不同的挑战运行代码,因此您可以在挑战表中使用状态列。然后你会发出UPDATE challenges SET state = {locked} WHERE id = {id} AND state = {unlocked}
。如果此查询成功并且受影响的行等于1,那么您可以继续更新参与者并在之后解锁挑战。如果查询不影响任何行,那么挑战可能正由某个其他执行线程更新,因此您可能希望跳过此步骤或安排它稍后重新运行。
如果你走这条路,那么你需要小心解锁你的挑战并做一些事情,防止它们被卡住,如果其中一个线程在更新过程中崩溃并且没有解锁它的挑战。例如,您可以state = {thread id}
,然后您可以检测哪些线程已经死亡并解除他们的挑战。