在 Rails 中处理分片数据库的最佳方法是什么?分片应该在应用层、活动记录层、数据库驱动层、代理层还是其他什么地方处理?各自的优缺点是什么?
9 回答
FiveRuns 有一个名为DataFabric的 gem ,它执行应用程序级别的分片和主/从复制。这可能值得一试。
我假设对于分片,我们谈论的是水平分区而不是垂直分区(这里是 Wikipedia 上的区别)。
首先,在考虑水平分区之前,尽可能地拉伸垂直分区。在 Rails 中很容易让不同的模型指向不同的机器,对于大多数 Rails 站点来说,这会让你走得更远。
对于水平分区,在理想情况下,这将在 Rails的应用程序层处理。但是,虽然这并不难,但在 Rails 中也不是微不足道的,而且当您需要它时,通常您的应用程序已经超出了可行的范围,因为您到处都有 ActiveRecord 调用。没有人,开发人员或管理人员,喜欢在你需要它之前就开始工作,因为每个人都宁愿处理用户现在将使用的功能,而不是在你的流量爆炸后多年可能不会发挥作用的分区。
ActiveRecord 层……据我所见并不容易。需要大量猴子修补到 Rails 内部。
在Spock,我们最终使用自定义 MySQL 代理来处理这个问题,并将其作为Spock 代理在 SourceForge 上开源。ActiveRecord 认为它正在与一台 MySQL 数据库机器交谈,而实际上它正在与代理交谈,然后代理与一个或多个 MySQL 数据库交谈,合并/排序结果,并将它们返回给 ActiveRecord。只需要对 Rails 代码进行一些更改。查看 Spock Proxy SourceForge 页面了解更多详细信息以及我们选择这条路线的原因。
将 Rails 连接到多个数据库并不是什么大问题——您只需为覆盖连接属性的每个分片创建一个 ActiveRecord 子类。如果您需要进行跨分片调用,这将变得非常简单。然后,当您需要在分片之间进行调用时,您只需编写一些代码。
我不喜欢 Hank 拆分 rails 实例的想法,因为除非你有一个大的共享库,否则在实例之间调用代码似乎很有挑战性。
此外,在开始分片之前,您应该考虑做一些类似Masochism的事情。
为了让 Rails 与复制环境一起工作,我建议使用 my_replication 插件,它有助于在运行时将数据库连接切换到其中一个从属服务器
rails 6.1 提供了切换每个数据库连接的能力,因此我们可以进行水平分区。
- 分片在三层配置中声明如下:
production:
primary:
database: my_primary_database
adapter: mysql2
primary_replica:
database: my_primary_database
adapter: mysql2
replica: true
primary_shard_one:
database: my_primary_shard_one
adapter: mysql2
primary_shard_one_replica:
database: my_primary_shard_one
adapter: mysql2
replica: true
- 然后模型通过 shards key 与 connected_to API 连接
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
shard_one: { writing: :primary_shard_one, reading: :primary_shard_one_replica }
}
end
- 然后模型可以通过 connected_to API 手动交换连接。如果使用分片,则必须同时传递角色和分片:
ActiveRecord::Base.connected_to(role: :writing, shard: :shard_one) do
@id = Person.create! # Creates a record in shard one
end
ActiveRecord::Base.connected_to(role: :writing, shard: :shard_one) do
Person.find(@id) # Can't find record, doesn't exist because it was created
# in the default shard
end
参考:
在我看来,最简单的方法是在 rails 实例和 DB 分片之间保持 1:1。
代理层更好,它可以支持所有的程序语言。
例如:Apache ShardingSphere 的代理。
Apache ShardingSphere 有 2 种不同的产品,ShardingSphere-JDBC 用于应用层,仅适用于 Java 语言,ShardingSphere-Proxy 用于代理层,适用于所有程序语言。
仅供参考:https ://shardingsphere.apache.org/document/current/en/user-manual/shardingsphere-proxy/
取决于导轨版本。正如@Oshan 所说,较新的 rails 版本提供了对分片的支持。但是,如果您无法更新到较新的版本,您可以使用 octopus gem。宝石链接 https://github.com/thiagopradi/octopus