【Rails6.1】水平シャーディング機能を試す

ZAICOでは、Android・iOS・Rubyエンジニアを絶賛募集中です! 詳しくは、採用ページをご覧ください。

好きな場所で働こう

こんにちは!

私の地元では桜が散ったところがほとんどで、新緑の季節が待ち遠しいです。

ZAICOは全社員リモートワークということもあり、所々によって季節の移り変わりが少しずれていて(桜の見頃なんてまさにそう)、各地の話を聞くのもまた面白いですね。

今回はRails6.1の水平シャーディング機能を試します。なお、少し前に「モデルでのコネクション自動切り替えを試す」という記事を書いていますので、そちらもお読みいただけると幸いです。

前提条件

  • Ruby 2.6.6
  • Rails 6.1.3
  • APIモードを利用

データベース・replicaの設定

database.yml

development:
  zaicodb:
    <<: *default
    database: zaicodb_development
    port: 3306
  zaicodb_shard_one:
    <<: *default
    database: zaicodb_development
    port: 3307

$ bundle exec rails db:create

データベース接続先の設定

app/models/application_record.rb

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

  # 追記
  connects_to shards: {
    default: { writing: :zaicodb, reading: :zaicodb },
    shard_one: { writing: :zaicodb_shard_one, reading: :zaicodb_shard_one }
  }
end

モデルやマイグレーションを用意(検証用)

$ bundle exec rails g model User name:string

$ bundle exec rails db:migrate

コントローラを用意(検証用)

class UsersController < ApplicationController
  def create
    user = User.new(users_params)
    user.save!
    ApplicationRecord.connected_to(role: :writing, shard: :shard_one) do
      user = User.new
      user.name = 'This is shard one'
      user.save!
      render json: user
    end
  end
  # ...その他省略
end

どのシャードを参照しているかログで確認できるようにする

各種記事でも紹介がある、arproxyというgemを利用します。

Gemfile

gem 'arproxy' # 追記

config/initializers/arproxy.rb

class QueryTracer < Arproxy::Base
  def execute(sql, name=nil)
    shard = ApplicationRecord.current_shard
    name = "#{name} [#{shard}]"
    super(sql, name)
  end
end

Arproxy.configure do |config|
  config.adapter = "mysql2" # A DB Apdapter name which is used in your database.yml
  config.use QueryTracer
end
Arproxy.enable!

current_shardメソッドで、どのシャードを指し示してるか確認することが可能で、今回ならdefault・shard_oneのどちらかがログに出力されます。

ActiveRecord::Core (api.rubyonrails.org)

動作確認

$ curl -X POST -H ‘Content-Type: application/json’ -d ‘{“name”: “zaico hanako”}’ localhost:3000/users

1つ目のinsertはdefaultを向き、2つ目のinsertではshard_oneを向いています。

【default】

【shard_one】

特に設定していない場合は、データベースのMySQLのAUTO_INCREMENTによってidが決まるので、それぞれのデータベースで採番されていくようです。そのためここは別途調整が必要かもしれません。

これがRails標準で備わるようになってとても驚いていますが、筆者が試していないRailsの機能はまだまだありますので、これからもこのブログで試していこうと思います。

以上、水平シャーディング機能を試した内容でした!

参考記事

Ruby on Rails 6.1 の水平シャーディング対応 & Octopusからの移行事例 – Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Ruby on Rails 6.1の主要な新機能・変更点 – Qiita

ZAICOでは、新しいテクノロジーの力でモノの状態・流れを把握する仕組みに一緒に取り組む仲間を募集しております。
詳しくは、採用ページをご覧ください。

好きな場所で働こう