2014年10月24日金曜日

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

DBがレプリケーションの構成になっている場合、更新系のクエリーをマスターDBへ、参照系のクエリーをスレーブDBへクエリを投げるようして、DBの負荷分散をさせる方法です。
RailsのGemでそれを、やってくれるGem octopus (Git Hub - tchandy/octopus) があるので、これを使った実装は説明します。

インストール

gemのインストールは、Gemfileに以下を追加して、bundle install
Gemfile
# DB master slave振り分け
# https://github.com/tchandy/octopus
gem 'ar-octopus'

DBの接続先の設定

接続先の設定は、config/shards.ymlに行って行きます。
公式のConfigファイルの設定に関するWikiはこちら

全クエリの振り分け

更新のクエリは、マスターDB、参照のクエリはスレーブDBと全てのクエリに対して設定を行う場合は、下記。
octopus:
  replicated: true
  environments:
    - development
    - staging
    - production
  development:
   development_slave:
      database: development_slave_db
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000

  staging:
    staging_slave1:
      database: staging_slave_db
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000

  production:
    production_slave1:
      database: production_slave1
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000
    production_slave2:
      database: production_slave2
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000

モデル毎の振り分け

モデル毎に、マスター、スレーブを使うかを決める場合は、こちら。
fully_replicated: false を指定する。
octopus:
  replicated: true
  fully_replicated: false
  environments:
    - development
    - staging
    - production
  development:
   development_slave1:
      database: development_slave_db
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000

  staging:
    staging_slave1:
      database: staging_slave_db
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000

  production:
    production_slave1:
      database: production_slave1
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000
    production_slave2:
      database: production_slave2
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: postgres
      password: password
      port: 5432
      host: localhost
      timeout: 5000
config/shards.ymlの他に、modeleから、replicated_model() メソッドを呼び出します。
#This class is replicated, writes to master and reads to slave.
class Cat < ActiveRecord::Base
  replicated_model()
end

接続の確認

上記まで、設定が完了していれば、rails c で
Cat.find(1)
とすれば、 下記のような、ログがとれるはずです。
[Shard: development_slave1]  Cat Load (0.4ms)  SELECT "cats".* FROM "cats" WHERE "cats"."id" = $1 LIMIT 1  [["id", 1]]

直接DBを選択する場合

usingメソッドを呼び出します。

マスターに投げる場合

Cat.using(:master).find(1)

スレーブに投げる場合

Cat.using(:development_slave1).find(1)
または、ブロックを使って。
Octopus.using(:development_slave1) do 
 Cat.count
end

テスト環境の構築

テスト環境にもマスターDB、スレーブDBを作るのが環境的にはベストかもしれませんが、状況によって作れないこともあると思うので、
そんな時は、読み取り専用のユーザーを作るの楽かと思います。

読み取り専用ユーザーの作成

postgresでの読み取り専用ロールの作り方は以下
CREATE ROLE read_only_user LOGIN REPLICATION PASSWORD 'password';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only_user;

shards.ymlの設定変更

下記のように、databaseをマスターDBに向けて、usernameをread_only_userに変更すれば、OKです。
octopus:
  replicated: true
  fully_replicated: false
  environments:
    - development
    - staging
    - production
  development:
   development_slave:
      database: development_master_db
      adapter: postgresql
      encoding: utf8
      pool: 5
      username: read_only_user
      password: password
      port: 5432
      host: localhost
      timeout: 5000

障害発生時の対応

もし、マスターDBに以上が発生した場合などに、取り合えず、振り分け処理を停止したい時は - production をコメントアウトするのが有効かと思います。
octopus:
  replicated: true
  fully_replicated: false
  environments:
#    - development
#    - staging
#    - production
  development:
   development_slave:
最低限、productionのみコメントにすれば、OKかと思います。
また、開発環境やステージング環境で、レプリケーション不要なんて時もコメントアウトしておけば、振り分け処理はおこなわれません。

0 件のコメント:

コメントを投稿

statistics

Arsip