【问题标题】:Database sharding and Rails数据库分片和 Rails
【发布时间】:2023-03-08 12:57:01
【问题描述】:

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

【问题讨论】:

    标签: ruby-on-rails database activerecord sharding


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我假设我们谈论的是水平分区而不是垂直分区 (here are the differences on Wikipedia)。

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

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

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

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

      【讨论】:

      • +1 用于在表级别拉伸垂直分区。使用 ActiveRecord,为了将“热”数据与其他数据隔离开来,将表拆分为具有较少列的几个表是相当轻松的。如果您使用的是 MySQL,这会产生很大的不同。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

        此外,在开始分片之前,您应该考虑执行Masochism 之类的操作。

        【讨论】:

          【解决方案5】:

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

          https://github.com/minhnghivn/my_replication

          【讨论】:

            【解决方案6】:

            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
            
            • 然后通过分片键将模型与 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
            

            参考:

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

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

                例如:Apache ShardingSphere 的代理。

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

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

                【讨论】:

                  【解决方案9】:

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

                  【讨论】:

                    猜你喜欢
                    • 2012-11-20
                    • 2021-08-31
                    • 2012-03-21
                    • 2014-01-13
                    • 2020-05-15
                    • 2010-11-05
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-01-29
                    相关资源
                    最近更新 更多