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