FreshConnectionが2.0になってPostgreSQLもサポート
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
production
や development
などの環境の中に、 slave
という項目を用意します。そこがスレーブDBの設定内容として使われます。
host
は実際にはロードバランサのホスト名やIPアドレスを指定します。 指定していない項目に関しては、マスターDBの設定が使われます。
上の例では、 slave
という名前のロードバランサが使われ、スレーブDBへ接続する際のユーザ名とパスワードはともに、 slave
になります。
adapter
や、 encoding
などの項目はマスターDBのものが使われます。ここではそれぞれが、 mysql2
と utf8
になります。
複数のスレーブ群を扱いたいとき
課金系などで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
これで、 AdminLog
も admin_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
の前に積んでください。