Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

27
Rails における コネクション数と シャーディングのお話 株式会社 Aiming エンジニア 土井 英範

Transcript of Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

Page 1: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

Rails におけるコネクション数と シャーディングのお話

株式会社 Aiming エンジニア 土井 英範

Page 2: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

About: 土井 英範• 株式会社 Aiming 開発グループマネージャーリードソフトウェアエンジニア

• エンジニアになって10年弱 • かかわったゲームタイトル4本くらいクライアントからサーバまで全般を経験してきた

• コンシューマゲーム、ブラウザゲーム、スマホのゲーム

• サーバ・クライアントプログラム

Page 3: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

Rubyist 編

Page 4: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

Active Record

Page 5: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割したい

Page 6: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割したい

•際限なく増えていくレコード •インデックスサイズの増加 •ユーザー増加に伴うクエリ回数の増加 •クエリ性能の低下

Page 7: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

User Table

User Table 1 User Table 2 User Table 3

分割基準 Range (ID: 1~100, 101~200 …)List (CountryCode: JP, US …) Hash ( ID mod 3 )

一つのテーブルを特定のルールで 複数のDBに分散する

↓分割↓

Page 8: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

Q. ActiveRecord で水平分割ってできるの?

Page 9: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

A. 一筋縄にはいかない

Page 10: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

Active Record のコネクションスイッチング

•establish_connection というメソッドがありますが

•能動的に接続を確立するためのものではなく実際の接続は行わない

• 指定されたクラスをキーに (クラス・メソッド) コネクションプールを作成するだけのもの

Page 11: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

establish_connection の挙動

•クラス定義の段階で指定するためスイッチングの用途に使えない

•安直に呼び出して切り替えるのも危険

class User < ActiveRecord::Base establish_connection :user_db # database.yml で定義されているとする … end

Page 12: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割するためのGem があります

Page 13: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割に利用できる Gem

•octopus • https://github.com/tchandy/octopus • 昔ある有名な Gem • @user = User.using(:shard1).find_by_name(“Joao") • こんな書き方ができる

Page 14: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割に利用できる Gem

•ActiveRecord::Turntable • https://github.com/drecom/activerecord-turntable • 高機能 •シャード間で ActiveRecord の id をキーとして分散できる •自動的にどのシャードでクエリを投げる必要があるかを解決してくれる

Page 15: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割に利用できる Gem

•Sengiri • https://github.com/mewlist/sengiri • ActiveRecordの挙動にあまり手をいれない作り •低機能、シンプル •土井の自作

Page 16: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

ActiveRecord とコネクション数の話

Page 17: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

too many connections

Page 18: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

見積もり方法

•プロセスベースのサーバならスレッド数は 基本 1 •※コード内に Ruby スレッド処理などがない前提 • Passenger ※Enterprise版だと Thread モデルも可能らしい • Unicorn

• スレッドベースのサーバ • Puma (ワーカープロセスも複数設定できる)

Page 19: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

見積もり方法

•サーバ台数 x プロセス数 x スレッド数 • 20台 x 5 process x 2 thread • = 200 connection

Page 20: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

その他

•管理ツールからのコネクション •バッチ処理・キュー処理からのコネクション

•これらも忘れずに接続数として見積もっておく

Page 21: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

database.yml•pool: 5 •プールサイズの設定はスレッドを利用する際の設定

• unicorn, passenger などのプロセスベースのサーバだと1 process に付き 1 connection

Page 22: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

水平分割した時の話

•Multi-DB アクセスする場合 •基本的に全てのDBにコネクションが張られると考えたほうが良い

• 5分割したら5つのDBに接続を張る可能性がある •各 Gem でどのような実装になっているかは未確認 •※Sengiriはつなぎっぱなしになっちゃいます

Page 23: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

DB1 DB2 DB3 DB4 DB5

イメージweb web

admin bat

Page 24: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

コネクション数が増加すると

•MySQLの場合 • http://dev.mysql.com/doc/refman/5.6/ja/thread-pool-plugin.html

Page 25: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

http://www.oracle.com/technetwork/jp/ondemand/database/mysql/mysql-perftun-1484759-ja.pdf

Page 26: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

コネクションプーリングの回避

•activerecord-refresh_connection • https://github.com/sonots/activerecord-refresh_connection

•ardisconnector • https://github.com/mewlist/ardisconnector • 自作 sengiri と連動

Page 27: Aiming飲み会 1-rails におけるコネクション数とシャーディングのお話

コネクションは切断したほうが良いか?

•結論 • RDB側のスレッドプーリングが使えるならコネクション数の増加については気にする必要は無いのかもしれない

•最大コネクション数は上限を常に意識した設定を行う