Rails 6中的功能更新:多个数据库和状态管理

290 阅读4分钟

Rails 6.0最近分享了其惊人的增强功能,尽管大多数人会认为这些是功能升级。

在我看来,两者都是正确的,因为在rails 6.0之前,多个数据库的实际状态甚至不被认为是一个已完成的功能。

所以,让我们深入了解一下Rails < 6的状态!Rails 6引入的变化和它目前的路线图。

Rails 5状态

ActiveRecord支持多个数据库,但Rails < 6并没有提供管理这些数据库的方法。如前所述,你需要以真正的手工方式处理一切(是的,一切),必须为seeds,db:prepare,db:migrate 等创建自己的任务。

你还需要创建一种生成器来处理你的二级数据库迁移,遵循惯例。最后(好像你做的自定义工作还不够多),你需要创建一个初始化器来配置你与新数据库的连接。

所以,ActiveRecord确实支持多个数据库,但它是一个完整的、真正的混乱,除非绝对必要,否则你应该避免。

Rails 6.0状态

新东西

  • 多个主数据库和每个数据库的副本。

这很了不起,因为现在你可以在你的database.yml ,像这样轻松地配置它:

development:
  primary:
    database: my_primary_database
    user: root
    adapter: sqlite3
  primary_replica:
    database: my_primary_database
    user: root_readonly
    adapter: sqlite3
    replica: true
  animals:
    database: my_animals_database
    user: animals_root
    adapter: sqlite3
    migrations_paths: db/animals_migrate
  animals_replica:
    database: my_animals_database
    user: animals_readonly
    adapter: sqlite3
    replica: true

看看你如何为每个数据库定义你的迁移路径,以及你如何有能力使用多个适配器(仍在为这个假设进行POC工作)。

一个用这个迁移的例子是:rails g migration CreateCats name:string --database animals ,有这样的输出:

  Running via Spring preloader in process 97210
    invoke  active_record
    create    db/animals_migrate/20200819181625_create_cats.rb
  • 为你正在使用的模型自动切换连接。

你只需要在你的中间件中激活它以实现自动切换:

config.active_record.database_selector = { delay: 2.seconds }
config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session

你也可以手动决定你的连接上下文:

ActiveRecord::Base.connected_to(role: :reading) do
  # all code in this block will be connected to the reading role
end
  • 根据HTTP动词和最近的写入量,在主站和副本之间自动切换:

正如我们在Rails中所习惯的那样,这也是标准化的。

"如果应用程序收到一个POST、PUT、DELETE或PATCH请求,应用程序将自动写到主站。在写完后的指定时间内,应用程序将从主服务器上读取。

对于一个GET或HEAD请求,应用程序将从副本中读取,除非最近有一个写入。

  • 用于创建、删除、迁移和与多个数据库交互的Rails任务:

第一个大的评论,通常的rails db:create ,现在会创建两个数据库,所以通常的rails db:migrate ,也会迁移两个数据库。

你需要指定你想使用哪个数据库,比如rails db:create:primaryrails db:migrate:secondary ,如果你只想修改一个。

所以,对于你的自定义任务,你可能还需要指定你要使用的数据库。

待定的任务

  • 对于Sharding来说,现在有一些宝石来完成这个任务,所以在集成到Rails上之前,我们应该继续使用宝石(没有真正的交易)。
  • 当跨集群连接时,Rails指出。"应用程序不能跨数据库连接。Rails 6.1将支持使用has_many关系和创建2个查询,而不是连接,但Rails 6.0将要求你手动将连接分割成2个选择。"

所以,我们只需要等待Rails6.1!

  • 负载平衡复制似乎是一个有趣的功能,我希望能看到即将到来的这方面的消息。
  • 对于多个数据库的模式缓存的转储,它指出。"如果你使用模式缓存和多个数据库,你需要写一个初始化程序,从你的应用程序中加载模式缓存。这不是我们能在Rails 6.0中及时解决的问题,但希望能在未来的版本中很快解决这个问题"

所以,这似乎是一个在即将到来的版本中要解决的琐碎问题。

Rails 6.1的未来状态

正如你可能知道的,Rails 6.1就快到了,所以,我将仔细检查一下这个新版本中所说的要发布的内容,以及实际要发布的内容。

这里有一些不错的公开PR,现在:

所以,总结起来就是:

  • Sharding现在是一个WIP的东西,我们可能希望在Rails 6.1中看到它的存在。
  • 仍然在等待跨集群的连接(或者我在评论中错过了)。
  • 还在等待负载均衡。
  • 模式缓存现在是一个东西

一些个人想法

我是一个非关系型数据库的超级粉丝,所以,我很想看到一些MongoDB+Postgres的混合版本,比如说。随着引入的变化,我想我们很快就能找到一种方法来正确地使用它。

我的疑惑是:"ActiveRecord应该支持非关系型数据库吗?"或者 "在ActiveRecord之外有更多的轨道工作吗?"