データベースの負荷分散の方法の1つレプリケーションという方法があります。マスターDBへの変更をスレーブDBに同期するようにしておいて、書き込みのクエリはマスターDBへ、読み取りのクエリはスレーブDBへと振り分けることで負荷を分散しようというやり方です。
最初にこの方法を知った時は最強じゃんとか思ったんですが、そんな魔法のようなものではなくよく考えてうまく使う必要があります。例えばマスターの更新がスレーブに反映されるのにはタイムラグがあるので、マスターを更新した直後にスレーブを参照してデータがない、とか。まあとにかく色々工夫が必要です。
と、ここまで書いておいてなんですが、今日の記事ではレプリケーションの実践について書くわけではありません。もっとライトな「Railsでデータベースの接続先を変えるためのgemを紹介する」という話です。
いくつかのgemがありましたが、僕が選んだのはシンプルに使えそうだったpostamtというgemです。
有名なのはこっちかも?使った当時は導入に手間どってしまったのでパスしました。
postamtの導入
インストール
1# Gemfile
2gem 'postamt'
1$ bundle install
database.ymlの設定
database.ymlファイルにスレーブの情報を追加します。スレーブは複数でもよいです。。データベースの名前やユーザー名などを一緒にしておけばhostを書き換えるだけでOKです。
1development:
2 adapter: mysql2
3 host: db-master
4 database: hoge
5 user: hoge
6 password: hoge
7 pool: 5
8 timeout: 5000
9 slave1:
10 host: db-slave1
11 slave2:
12 host: db-slave2
ローカルでの動作確認でレプリケーション構成を作るのが面倒なときは、参照するDBは同じにしたまま読み取り専用のユーザーを作っておくことでシミュレート可能です。
postamtの使い方
アクション単位で分ける
READMEから転載w
1class UserController < ApplicationController
2 use_db_connection :slave, for: ['User'], only: [:search]
3
4 def search
5 # SELECTs here are sent to slave
6 # User#save and User.create would be sent to master anyways.
7 # Everything in a transaction block too.
8 @users = User.where(...) # sent to slave
9 @something_else = SomethingElse.first # sent to master
10 end
11
12 def create
13 @user = User.new(params[:user])
14 @user.save! # sent to master
15 end
16
17 def invoice
18 transaction do
19 @user = User.where(...) # sent to master
20 @invoices = Invoice.create(...) # sent to master
21 end
22 end
23end
モデルのデフォルトを指定する
1class User < ActiveRecord::Base
2 # ...
3 self.default_connection = :slave1
4end
5
6User.where(...) # slave1が使われる
DBを指定して実行する
1Postamt.on(:master) do
2 User.where(...) # masterが使われる
3end