おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

FreshConnectionが2.0になってPostgreSQLもサポート

Large

FreshConnectionのバージョンが2.0系になりました。
このバージョンから、MySQLに加えてPostgreSQLもサポートするようになります。
たぶん、他のRDBMSでも動くんじゃないかな。でもテストしていないのでわかりません。

開発を始めたのは2011年なのですが、暇なときにとろとろコーディングしているのでそれほど進化はしていません。
改めてFreshConnectionについて簡単に説明します。

FreshConnection?

スレーブDBへのアクセスを可能にするgemです。けっこう大きなサイトでも使われているようです。
RailsはひとつのDB(マスターDB)へのアクセスしかできませんが、FreshConnectionを使うことでスレーブDBへのアクセスが可能になります。
使い方はすごくシンプルです。何も覚えなくても大丈夫です。
更新系のクエリは自動でマスターDBへ投げられ、参照系のクエリは自動でスレーブDBへ投げられます。使うときにマスターなのかスレーブなのかを意識する必要がありません。

User.find_by(id: params[:id]) # スレーブDBへ  
User.create(params[:user])   # マスターDBへ  

# トランザクション内の処理はすべてマスターDBへ  
User.transaction do  
  u = User.first  
  ....  
end  

参照系のクエリをマスターDBに投げたいときは、 read_master を使います。

User.read_master.find_by(id: params[:id]) # マスターDBへ  

read_master は ActiveRecord::Relation のメソッドなので、クエリ生成の中でメソッドチェインすることができます。

User.includes(:address).read_master.where(age: 18).limit(10) # マスターDBへ  

覚えることはこれだけなので、とても簡単です。

マスターDBにしか存在しないテーブルがある場合

モデルで以下のように master_db_only! と宣言しておけば、すべてのアクセスがマスターDBにだけ投げられます。

class Hoge < ActiveRecord::Base  
  master_db_only!  
end  

ロードバランサ

FreshConnectionは、スレーブDB群の前にロードバランサが置かれていることを想定しています。

Rails ------------ Master DB  
             |  
             |                     +------ Slave1 DB  
             |                     |  
             +---- Loadbalancer ---+  
                                   |  
                                   +------ Slave2 DB  

スレーブDBの死活監視やアクセスの振り分けはすべてロードバランサにまかせることで、スレーブDBの管理が容易になります。
ロードバランサを使えない環境の人は、 FreshConnectionに簡単なロードバランサの機能を備えた EbisuConnection を使うことができます。 EbisuConnectionも使い方はFreshConnectionと同じです。

設定方法

スレーブDBの設定は、 config/database.yml で行います。

production:  
  adapter: mysql2  
  encoding: utf8  
  reconnect: true  
  database: kaeru  
  pool: 5  
  username: master  
  password: master  
  host: localhost  
  socket: /var/run/mysqld/mysqld.sock  

  slave:  
    username: slave  
    password: slave  
    host: slave  

productiondevelopment などの環境の中に、 slave という項目を用意します。そこがスレーブDBの設定内容として使われます。
host は実際にはロードバランサのホスト名やIPアドレスを指定します。 指定していない項目に関しては、マスターDBの設定が使われます。
上の例では、 slave という名前のロードバランサが使われ、スレーブDBへ接続する際のユーザ名とパスワードはともに、 slave になります。
adapter や、 encoding などの項目はマスターDBのものが使われます。ここではそれぞれが、 mysql2utf8 になります。

複数のスレーブ群を扱いたいとき

課金系などでDBクラスタをわけたいときがあると思います。
マスターDBに関しては、対象のモデルでestablish_connectionをすればいいですね。
同様にFreshConnectionも別のスレーブ群を、establish_fresh_connection という宣言で定義できます。

class AdminUser < ActiveRecord::Base  
  establish_fresh_connection :admin_slave  
end  

establish_fresh_connection の引数に、対象となるスレーブ群の名前を指定します。
config/database.yml では以下のように対象のスレーブ群を指定します。

production:  
  adapter: mysql2  
  encoding: utf8  
  reconnect: true  
  database: kaeru  
  pool: 5  
  username: master  
  password: master  
  host: localhost  
  socket: /var/run/mysqld/mysqld.sock  

  slave:  
    username: slave  
    password: slave  
    host: slave  

  admin_slave:  
    username: admin_slave  
    password: admin_slave  
    host: admin_slaves  

admin_slave で指定した設定が、 establish_fresh_connection :admin_slave を宣言したモデルで使われます。
establish_fresh_connection は、継承した子クラスからも見えるので、親クラスでだけ宣言しておけば問題ありません。

class AdminDb < ActiveRecord::Base  
  self.abstract_class = true  
  establish_fresh_connection :admin_slave  
end  

class AdminLog < AdminDb  
end  

これで、 AdminLogadmin_slave のスレーブ群を使用するようになります。

サポートするActiveRecordのバージョン

4.0.x、4.1.x、4.2.x が対象になります。
5.0.0.beta3でも動いているので、正式に5.0.0がリリースされたら、すぐに対応版がリリースできると思います。
3.2で使いたいときは、バージョン1.0.0 以前のものを使用してください。

インストール

Gemfileに以下を追加するだけです。

gem "fresh_connection"  

Rails以外のRackアプリで使いたいとき

FreshConnection::Rack::ConnectionManagement という Rackミドルウェアが存在するので、 ActiveRecord::ConnectionAdapters::ConnectionManagement の前に積んでください。