Javascript 在基于事件的系统中并发处理唯一性

Javascript 在基于事件的系统中并发处理唯一性,javascript,mysql,node.js,mutual-exclusion,Javascript,Mysql,Node.js,Mutual Exclusion,在我目前正在进行的项目中,我们面临着所谓的挑战。挑战有成员和参与者。成员是能够访问挑战的每个人(可以是单个用户或用户组),参与者以每个用户为基础跟踪参与统计数据 每次添加新的挑战成员时,将重新计算挑战参与者。这是基于事件发生的,因此质询成员会触发一个创建的事件,质询参与者会监听该事件 当同时创建两个质询成员时,问题就会出现,这意味着事件也会触发两次,并且代码的两次执行同时运行。举例说明: challenge.getMembers(); challenge.getParticipants();

在我目前正在进行的项目中,我们面临着所谓的挑战。挑战有成员和参与者。成员是能够访问挑战的每个人(可以是单个用户或用户组),参与者以每个用户为基础跟踪参与统计数据

每次添加新的挑战成员时,将重新计算挑战参与者。这是基于事件发生的,因此质询成员会触发一个
创建的
事件,质询参与者会监听该事件

当同时创建两个质询成员时,问题就会出现,这意味着事件也会触发两次,并且代码的两次执行同时运行。举例说明:

challenge.getMembers();
challenge.getParticipants();

// calculations

foreach member not in participants, create participant
如上所述,当上述代码同时运行时,问题就会出现,更具体地说,当第二次执行在第一次创建缺少的参与者条目之前到达
getParticipants
时。两次执行都会发现缺少一些参与者,并创建它们。这意味着对于某些用户,我们现在有重复的挑战参与者条目

现在我们解决这个问题的方法是在挑战参与者的
challenge\u id,user\u id
上有一个唯一的索引。但是,在违反约束时忽略错误确实有点脏。这也使得检查其他SQL错误变得更加困难,因为所有错误都只是传递给回调,然后我们必须检查错误字符串的内容,以确定应该处理的是我们喜欢的错误(唯一性冲突),还是我们不喜欢的错误(如语法错误)


这段代码将在多台服务器上运行,因此即使使用mutices,我们也不能保证代码不会同时运行。我们也不介意它为不同的挑战同时运行,只要它不为同一个挑战同时运行。有人对处理这种类型的并发合并有什么建议吗?

既然您说您不介意为不同的挑战同时运行代码,那么您可以在挑战表中有一个包含state的列。然后您将发出一个
更新挑战集state={locked},其中id={id}和state={unlocked}
。如果此查询成功且受影响的行等于1,则您可以继续更新参与者并随后解锁质询。如果查询不影响任何行,则质询可能正在由其他执行线程更新,因此您可能希望跳过此步骤或计划稍后重新运行


如果你走这条路线,你就需要小心地解锁你的挑战,并做一些事情来阻止他们被困,如果一个线程在更新过程中崩溃,并且不解锁它的挑战。例如,您可以使用
state={thread id}
,然后您可以检测哪些线程已死亡并解锁它们的挑战。

简单的解决方案(但可能不是太有效)是在数据库中为每个挑战维护一个锁,或者为所有服务器提供某种缓存/共享内存层。然而,更大的问题在于你的设计;添加新成员时,为什么要创建所有参与者?为什么不在添加每个成员时将其创建为参与者?此外,您应该在db上设置唯一的约束,以防万一,即使您觉得这种情况不应该发生。如果您的代码没有您认为的那么好,那么这是一个很好的回退。您的模式对于挑战、参与者和成员是什么样子的?