Rails 6 + Heroku 中的多数据库访问

问题描述 投票:0回答:1

有一个在 Heroku 中运行的 Rails 5 应用程序;它有两个 DB,一个 Primary 和一个 Follower(只读),follower 是 Primary 的副本。在某些应用领域,我们使用关注者来获取数据。以前,rails 不支持 Multi DB,因此我们使用 Gem Octopus。然而,他们将其置于维护模式,因为 Rails 6 支持多数据库。

我们使用不同的方式通过章鱼访问关注者数据库,例如:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end
class SetupController < ApplicationController
  around_action :select_follower

  def select_follower(&block)
    Octopus.using(ENV['FOLLOWER_DB'], &block)
  end

  def method1
   // enter code here
  end
end
@customer = Customer.using(FOLLOWER_DB).find(params[:id])
Octopus.using(:master) do
  SidekiqWorker.perform_async(param1, param2)
end

运行良好,已经运行了 5 年多。

最近,我们将 Rails 应用程序从 Rails 5 迁移到 Rails 6,并用多数据库设置替换了 octopus。

数据库.yml

production:
 primary:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>
 secondary:
  <<: *default
  url: <%= ENV['FOLLOWER_DATABASE_URL'] %>
  migrations_paths: db/secondary_migrate

应用程序/模型/application_record.rb

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: { writing: :primary, reading: :primary }
end

应用程序/模型/ secondary_application_record.rb

class SecondaryApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: { writing: :secondary, reading: :secondary }
end

然后,当我们尝试访问关注者时,就像我们对章鱼所做的那样,就像

class DashboardController < ApplicationController

  around_action :select_secondary_db

  def select_secondary_db(&block)
    SecondaryApplicationRecord.connected_to(role: :reading, &block)
  end

  def method1
   // enter code here
  end
end

SecondaryApplicationRecord.connected_to(role: :reading) do
  Customer.find_by_id(params[:id])
end

在所有这些新方式中,日志显示查询在主数据库中运行,没有任何内容通过跟随者/辅助数据库运行。小学始终存在的情况可能是什么?

ruby-on-rails heroku ruby-on-rails-6 octopus
1个回答
0
投票

我同意@engineersmnky,你的问题是继承问题之一。

我认为你不需要水平分片。只需使用文档中讨论的上下文切换

ActiveRecord::Base.connected_to(role: :reading) do
  Customer.find_by_id(params[:id])
end

我个人从未见过辅助抽象类的单独实现。这可以工作如果你总是希望

Customer
从关注者那里阅读:

class Customer < SecondaryApplicationRecord
end

但是,如果该 id 刚刚写入主节点而追随者尚未写入,则这可能会出现问题。

请注意,Rails 可以提供智能上下文感知切换,因此您可能会进行超出需要的微调:

如果应用程序收到 POST、PUT、DELETE 或 PATCH 请求,应用程序将自动写入写入器数据库。在写入后的指定时间内,应用程序将从主数据库读取。对于 GET 或 HEAD 请求,应用程序将从副本中读取,除非最近有写入。

如果您的

Customer.find_by_id(params[:id])
位于控制器
GET
操作(如
index
)中,则 Rails 会自动从
:reading
跟随器读取(如果写入后已过了指定时间)。

当不在控制器中工作时,我的团队只是根据需要使用手动上下文切换。

© www.soinside.com 2019 - 2024. All rights reserved.