我们在网页游戏中有一个按钮,供用户收集奖励。只应点击一次,收到请求后,我们会将其标记为在DB中收集。
我们已经阻止了客户端中的按钮反复点击。但是,如果人们在短时间内多次向我们的服务器重新发送包裹,那将无济于事。
我想要的是一种从服务器端阻止它的方法。
我们在服务器方面使用Playframework 2(2.0.3-RC2),到目前为止它是无状态的,我很想使用Set来保护这样:
if processingSet has userId then BadRequest
else put userId in processingSet and handle request
after that remove userId from that Set
然后我不得不面对像Updating Scala collections thread-safely这样的问题,并且一旦我们有多个服务器支持负载均衡,仍然无法阻止用户。
我正在考虑的一种可能性是在DB中使用一个表来代替上面的processingSet,但是每个请求会产生1+ DB操作,是否有更好的解决方案〜?感谢〜
答案 0 :(得分:3)
在这种情况下,额外的DB操作是相对“便宜”的解决方案。如果您打算永久保存按钮状态,则应使用它。
如果该按钮仅在一段时间内被禁用(例如,直到游戏结束),您还可以考虑使用cache API,但请记住,这并非专用于应该长时间存储的解决方案时间(不应被视为数据库替代方案)。
答案 1 :(得分:3)
鉴于您正在使用Mongo,因此没有跨越单独集合的事务,我认为您可以使用atomic operation实现此保护 - 即“if current current”,这实际上是CompareAndSwap。 / p>
假设您有一个类似“奖励”的集合,它具有“已收集”属性,您可以将收集的标志更新为true,前提是它当前为假,如果该操作没有失败,您可以继续应用奖励知道对于任何其他请求,相同的操作将失败。