0

问题

在使用 FCGI 将 rails 3.2.8 应用程序从 WEBrick 移动到 Apache 后,我遇到了问题。

该应用程序包含一个用 javascript 编写的游戏,它发送大量 AJAX 请求以更新服务器上的游戏统计信息。

使用 WEBrick 可以正常工作,但是现在我已经切换到 Apache,如果我对同一记录进行多次快速更新,它们似乎相互之间写得太多了。例如,如果我有 15 个 ajax 调用大致同时发送,每次请求将 'points' 值更新 5 分,则总分不会加起来为 75,我想要它,而是会有所不同较低的数字介于 5 到 45 之间。

我相信这是因为 apache 能够一次处理多个请求。

我认为正在发生的事情

  • StatisticsController 收到添加点的请求。
  • 控制器从数据库中打开统计记录的副本。
  • 该模型将当前记录的点数增加 5。
    • 在保存记录之前,控制器收到另一个添加点的请求。
    • 它打开了仍然保持旧积分总数的记录。
    • 它在旧的总分上增加了 5 分。
  • 第一个请求的记录保存。
    • 第二个请求的记录保存。

总点数只增加了 5 而不是 10。

我试过的

我尝试了各种“锁定”记录的方法,以防止在使用 ActiveRecord 回调编写的过程中打开它,但到目前为止还没有成功。

我已经尝试了几次网络搜索,但我还没有想出神奇的关键字来给我正在寻找的答案。

问题

有没有办法防止这些请求相互覆盖,或者有其他方法可以在服务器上处理吗?(我知道我可以将 javascript 统计信息编码为在发送另一个请求之前等待或合并请求,但在我看来,服务器应该能够处理尽可能多的请求。)

我完全有可能在我的方法上也走得很远,并且很乐意提出任何建议。

谢谢你。

4

1 回答 1

0

我设法使用与悲观锁定一致的事务块来完成这项工作。

代码现在如下所示:

  # GET /statistics/request.json
  def request
    # Begin a transaction
    Statistic.transaction do

      stat = Statistic.find(params[:id], lock: true) # Lock the record until we're done with the transaction.

      stat.total_points += 5

      stat.save!

      respond_to do |format|
        format.json { render json: stat }
      end
    end
  end

您还必须确保使用支持锁定的数据库引擎,在我的例子中 MySQL 运行 InnoDB。

特别感谢这篇文章让我明白了:悲观锁定似乎不适用于 mysql?

于 2012-11-13T17:11:29.847 回答