11

在 Rails 中处理分片数据库的最佳方法是什么?分片应该在应用层、活动记录层、数据库驱动层、代理层还是其他什么地方处理?各自的优缺点是什么?

4

9 回答 9

13

FiveRuns 有一个名为DataFabric的 gem ,它执行应用程序级别的分片和主/从复制。这可能值得一试。

于 2008-09-07T08:47:30.657 回答
9

我假设对于分片,我们谈论的是水平分区而不是垂直分区(这里是 Wikipedia 上的区别)。

首先,在考虑水平分区之前,尽可能地拉伸垂直分区。在 Rails 中很容易让不同的模型指向不同的机器,对于大多数 Rails 站点来说,这会让你走得更远。

对于水平分区,在理想情况下,这将在 Rails的应用程序层处理。但是,虽然这并不难,但在 Rails 中也不是微不足道的,而且当您需要它时,通常您的应用程序已经超出了可行的范围,因为您到处都有 ActiveRecord 调用。没有人,开发人员或管理人员,喜欢在你需要它之​​前就开始工作,因为每个人都宁愿处理用户现在将使用的功能,而不是在你的流量爆炸后多年可能不会发挥作用的分区。

ActiveRecord 层……据我所见并不容易。需要大量猴子修补到 Rails 内部。

Spock,我们最终使用自定义 MySQL 代理来处理这个问题,并将其作为Spock 代理在 SourceForge 上开源。ActiveRecord 认为它正在与一台 MySQL 数据库机器交谈,而实际上它正在与代理交谈,然后代理与一个或多个 MySQL 数据库交谈,合并/排序结果,并将它们返回给 ActiveRecord。只需要对 Rails 代码进行一些更改。查看 Spock Proxy SourceForge 页面了解更多详细信息以及我们选择这条路线的原因。

于 2008-09-11T01:56:42.403 回答
8

对于像我这样没有听说过分片的人:

http://highscalability.com/unorthodox-approach-database-design-coming-shard

于 2008-09-04T19:31:47.327 回答
2

将 Rails 连接到多个数据库并不是什么大问题——您只需为覆盖连接属性的每个分片创建一个 ActiveRecord 子类。如果您需要进行跨分片调用,这将变得非常简单。然后,当您需要在分片之间进行调用时,您只需编写一些代码。

我不喜欢 Hank 拆分 rails 实例的想法,因为除非你有一个大的共享库,否则在实例之间调用代码似乎很有挑战性。

此外,在开始分片之前,您应该考虑做一些类似Masochism的事情。

于 2008-09-23T14:28:58.430 回答
1

为了让 Rails 与复制环境一起工作,我建议使用 my_replication 插件,它有助于在运行时将数据库连接切换到其中一个从属服务器

https://github.com/minhnghivn/my_replication

于 2011-09-20T18:17:48.880 回答
1

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

参考:

于 2021-08-25T10:19:35.707 回答
0

在我看来,最简单的方法是在 rails 实例和 DB 分片之间保持 1:1。

于 2008-09-04T16:50:52.720 回答
0

代理层更好,它可以支持所有的程序语言。

例如:Apache ShardingSphere 的代理。

Apache ShardingSphere 有 2 种不同的产品,ShardingSphere-JDBC 用于应用层,仅适用于 Java 语言,ShardingSphere-Proxy 用于代理层,适用于所有程序语言。

仅供参考:https ://shardingsphere.apache.org/document/current/en/user-manual/shardingsphere-proxy/

于 2021-10-13T15:39:23.110 回答
0

取决于导轨版本。正如@Oshan 所说,较新的 rails 版本提供了对分片的支持。但是,如果您无法更新到较新的版本,您可以使用 octopus gem。宝石链接 https://github.com/thiagopradi/octopus

于 2021-10-13T19:59:17.737 回答