2014年10月24日金曜日

multi_dbを使ってレプリケーションのDBに接続を振り分ける方法

最初、レプリケーションされた、DB環境でのマスターDBトスレーブDBの接続の振り分けにOctopusを使おうか考えて色々と調べてみましたが、
スレーブでトラブルが起きた時にも、スレーブDBを参照しにいこうとしてしまうようなので、
それは、いかがなものかと思い、こちらの、Git Hub - multi_dbに切り替えました。
このmulti_dbは、スレーブが停止しても、マスターを見るように切り替わってくれるので、その点安心です。
それでは、設定方法を説明していきます。

database.ymlにスレーブの設定追加

スレーブ用のDBの接続情報をdatabase.ymlに追加します。
追加する、スレーブのdatabase.ymlでの名前の命名ルールは以下のようにします。
[environment]_slave_database[_optional_name]
例えば、production環境の1番スレーブDBの場合は、以下のようにします。
production_slave_database_1
[environment]は、下記のいずれか
  • development
  • staging
  • production
[_optional_name] は、数字がわかりやすいとおもいます。また、スレーブ一台構成の時などは、省略も可能です。
  • _1
  • _2
実際の、database.ymlは以下のようになります。
development:
  adapter: postgresql
  encoding: utf8
  database: development_master
  pool: 5
  username: postgres
  password: <%= ENV['DB_PASSWORD'] %>
  port: 5432
  host: <%= ENV['DB_HOST'] %>
  timeout: 5000

production_slave_database: # that would be a slave
  adapter: postgresql
  encoding: utf8
  database: development_slave
  pool: 5
  username: postgres
  password: <%= ENV['DB_PASSWORD'] %>
  port: 5432
  host: <%= ENV['DB_HOST'] %>
  timeout: 5000

初期化処理の追加

passenger未使用の場合

config/environments/[environment].rbのconfig.after_initializeブロックの中にMultiDb::ConnectionProxy.setup! を追加。
config.after_initialize do
  MultiDb::ConnectionProxy.setup!
end
[environment]は、下記のいずれか
  • development
  • staging
  • production

passenger使用の場合

config/initializers/connection_proxy.rbに以下を追加
if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      # ... set MultiDb configuration options, if any ...
      MultiDb::ConnectionProxy.setup!
    end
  end
else # not using passenger (e.g. development/testing)
  # ... set MultiDb configuration options, if any ...
  MultiDb::ConnectionProxy.setup!
end
上記を追加した場合、config/environments/[environment].rbの設定は不要になります。

マスターのみを参照するモデルの指定

UserモデルとBookモデルはマスターしか参照しないという設定にする場合、下記のようにmaster_modelsにモデル名の配列を指定する。
MultiDb::ConnectionProxy.master_models = ['User', 'Book']
MultiDb::ConnectionProxy.setup!

動作確認

これまでの設定で、rails c で
 Blog.find(1)
とすると、下記のような結果が帰ってきます。
[MULTIDB] hijacking connection for Blog
Blog Load (6.6ms)  SELECT "blogs".* FROM "blogs" WHERE "blogs"."id" = $1 LIMIT 1  [["id", 1]]

スレーブの重み付け

複数スレーブ環境の場合、各スレーブに対して重み付けもできるようです。
production_slave_database_1:
  <<: *postgres
  host: my.slavedb_1
  weight: 1

production_slave_database_2:
  <<: *postgres
  host: my.slavedb_2
  weight: 10

production_slave_database_3:
  <<: *postgres
  host: my.slavedb_3
  weight: 5
上記のようにそれぞれに、weightを設定した場合、
リクエスト数が以下のようになる様です。
production_slave_database_1 6302クエリ
production_slave_database_2 62764クエリ
production_slave_database_3 30934クエリ
※上記実際に試していないので、公式ドキュメンとそのままです。
AWSでインスタンスのスペックの違いがあるときなんかは、こちらの設定が有効活用できるような気がします。

その他

テスト環境

テスト環境は、Octopasの時も、書きましたが、読み取り専用のユーザーを作成して簡易的にテストしても良いかと思います。
詳しくは、Octopusを使ってレプリケーションのDBに接続を振り分ける方法を参照してください。
本来であれば、ちゃんとレプリケーション環境で試すのが望ましいとおもいますが、、、、

0 件のコメント:

コメントを投稿

statistics

Arsip