【问题标题】:How do avoid race conditions in a Ruby on Rails application?如何避免 Ruby on Rails 应用程序中的竞争条件?
【发布时间】:2009-12-17 10:41:36
【问题描述】:

我正在开发一个 Rails 应用程序,其中每个子域都有一个单独的数据库。而我正在做这样的事情。

#app/controller/application_controller.rb
class ApplicationController < ActionController::Base
  before_filter :select_database

  private
  def select_database
    MyModel.use_database(request.subdomains.first)
  end
end

#app/model/my_model.rb
class MyModel < ActiveRecord::Base

  def self.use_database path
    establish_connection :adapter => 'sqlite3', :database =>
      File.join(RAILS_ROOT, "db", "sqlite3", path)
  end
end

现在,在production 模式下,请求按此顺序来执行。

  1. 请求“A”来自子域 a.example.netMyModel 与数据库“a”建立连接。
  2. 现在另一个请求“B”针对子域 b.example.net 并且MyModel 与数据库“b”建立连接。
  3. 现在,如果请求“A”尝试执行MyModel.find_*(),它将访问哪个数据库? “a”还是“b”?

我相信这就是我们所说的“线程安全”或“竞态条件”,如果是这样,那么在实现每个子域使用一个数据库的应用程序时,我们如何避免它?

在上述问题中,我的假设是同时执行两个请求是生产服务器的正常行为。或者有没有更好的方法。我对生产服务器没有太多经验,所以请指教。

【问题讨论】:

    标签: ruby-on-rails race-condition


    【解决方案1】:

    您似乎正在使用复制...但是我建议您观看 newrelic 的以下演员表,以更好地了解数据库扩展:

    Scaling Your Database - Part 1

    Scaling Your Database - Part 2

    【讨论】:

      【解决方案2】:

      如果有两个模型和两个数据库, 为什么不为每个数据库子类化 MyModel?

      class MyModelDomainA < MyModel
        DBA_PATH = "first/db/path"
        def self.use_database
          establish_connection :adapter => 'sqlite3', :database => File.join(RAILS_ROOT, "db", "sqlite3", DBA_PATH)
        end
      end
      # then in controller:
      def select_database
        # or whatever string-manipulation you need to do... 
        # even have a lookup hash to get the correct model?
        model_klass = "MyModel#{request.subdomains.first.capitalize}"
        model_klass.constantize.use_database
      end
      

      等等。 显然,这仅在您拥有少量固定数量的域/数据库对时才有效。 但如果是这样 - 这意味着进入 DomainA 的任何人都将始终访问 Domain A 的数据库 = 没有竞争条件。

      一般来说,我发现除非你正在破解内核代码,否则解决竞争条件的方法不是线程安全……而是重新思考问题。

      【讨论】:

      • 对于每个子域一个数据库,假设子域的数量是动态的。
      • 好的,在这种情况下,不是作为一个类方法(这将更新整个类),你能不能把它变成一个实例方法,即只与你手中的实际实例相关现在?每次都必须重新连接会慢一些……但它是可行的。
      • 另外,你也可以运行上面的代码......元编程的美意味着你实际上可以制作任意数量的“MyModelDomainA”样式类......在运行时.
      猜你喜欢
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-24
      相关资源
      最近更新 更多