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

76de73a1dae79a86bb99a813bd8e8e0a?s=30&d=http%3a%2f%2fkaeruspoon%.net2f2014%2fimages%2fno imageTsukasa OISHI

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_masterActiveRecord::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 の前に積んでください。