在 Rails 中访问只读数据库的最佳方法

var*_*lan 2 activerecord ruby-on-rails heroku master-slave

我们的应用程序部署在具有 Unicorn 和主从数据库配置的 Heroku 上,所有应用程序请求(读取和写入)都发送到主数据库。

我们需要的是将部分read流量重定向到跟随者(从属)数据库。

为了实现这一目标,我们添加了read_only_database_connection.rb-

class ReadOnlyDatabaseConnection < ActiveRecord::Base
  self.abstract_class = true
end
Run Code Online (Sandbox Code Playgroud)

并添加了一个mixinswitch_connection.rb

module SwitchConnection
  def readonly_db_connection    
    current_conf = ReadOnlyDatabaseConnection.connection_config
    begin
      ReadOnlyDatabaseConnection.establish_connection(READONLY_CONFIG).tap do
        puts "Primary DB -> Follower DB"
      end

      yield
    ensure
      ReadOnlyDatabaseConnection.establish_connection(current_conf).tap do
        puts "Follower DB -> Primary DB"
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后在application_controller.rb,我做了 -

include SwitchConnection
around_filter :readonly_db_connection, only: [:index, :show]
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?是否有更好或更安全的方法将所有流量重定向showindex只读数据库?

gka*_*ats 5

我认为继承自的对象ActiveRecord::Base应该负责处理数据库。您可以拥有检查只读从属数据库的模型。

class ReadOnlyModel < ActiveRecord::Base
  establish_connection 'readonly_db'

  def readonly?
    true
  end
end

class Controller
  def index
    @models = ReadOnlyModel.all
  end
end

# in config/database.yml
readonly_database:
  adapter: #...
Run Code Online (Sandbox Code Playgroud)

如果您想使用相同的表名(我怀疑您这样做),您可以使用table_name方法。

class Model < ActiveRecord::Base
end

class ReadOnlyModel < ActiveRecord::Base
  self.table_name :models
end
Run Code Online (Sandbox Code Playgroud)

这是该方法的文档readonly?