More Related Content Similar to Mobage を支える Ruby の技術 ~ 複数DB編 ~ (20) More from Naotoshi Seo (11) Mobage を支える Ruby の技術 ~ 複数DB編 ~1. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
Mobageを支える
November 11th, 2014
!
Naotoshi Seo @sonots
DeNA Co., Ltd.
Rubyの技術
~複数DB編~
2. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
2
自己紹介
・瀬尾 直利 @sonots
・DeNA, Co., Ltd
・インフラの Dev
・Rubyist
・OSS 活動家
・Fluentd コミッタ
3. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
背景
3
!
Perl の会社と名高いこの DeNA でも
Ruby (on Rails) のプロジェクトが立ち
上がり始めている
4. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
インフラ要件の壁
4
!
• ホットデプロイ
• カスタムフォーマットのロガー
• デプロイサーバでビルドした gem を web
サーバにアプリコードと共に撒く
• 社内 rubygems ミラー
• Q4M 非同期ジョブキュー
• プロファイリングツール、調査ツール
5. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
複数DB対応
5
!
• Rails で複数DBに対応する必要性
• 冗長化・高速化
• 既存のインフラの仕組みにのっかる必要性
• 今回はここに特化した話
6. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
目次
6
!
• DB接続を都度接続に
• クライアントサイドDNSキャッシュ
• DBパスワード一元管理
• DBスキーマ一元管理ツール
• 複数DB接続
8. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
DeNAでの複数DB構成
8
!
• MySQL: Master/Slave
• DNSラウンドロビンでSlaveを振り分ける
• MHA で Master の高可用化
• DNS サーバには MyDNS を使用
9. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 1
MySQL
Slave 2
MySQL
Slave 3
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.4
10.1.1.2
sample_r
1回目
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 2 | 1 | sample_r | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
2回目
Slave参照: DNSラウンドロビン
10. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 1
MySQL
Slave 2
MySQL
Slave 3
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.4
2回目
Slave参照: 永続接続
ずっとココ!!
ダメ!
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 2 | 1 | sample_r | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
11. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 1
MySQL
Slave 2
MySQL
Slave 3
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.4
10.1.1.3sample_r
2回目
Slave参照: 都度接続
1/3 の確率
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 2 | 1 | sample_r | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
Good
12. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 2
MySQL
Slave 3
MySQL
Master 1
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.1
10.1.1.4
sample_w
MHA
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 1 | 1 | sample_w | 10.1.1.1 | 100 |
| 2 | 1 | sample_r | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
MySQL
Slave 1
13. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 2
MySQL
Slave 3
MySQL
Master 1
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.1
10.1.1.4
sample_w
MHA
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 1 | 1 | sample_w | 10.1.1.1 | 100 |
| 2 | 1 | sample_w | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
MySQL
Master 2
再接続 or
都度接続
14. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
DBWeb
DBを再起動
restart
再接続 or
都度接続
※ ただし、ActiveRecord の reconnect は正しく動かなかったり
※ そのため、アプリの再起動が必要だったりして、ツライ
15. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 1
MySQL
Slave 2
MySQL
Slave 3
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.4
Slaveダウン検知(check_slave)
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 2 | 1 | sample_r | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
10.1.1.3sample_r
再接続 or
都度接続
17. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
しかしActiveRecord
には都度接続オプションがない
17
20. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
activerecord-
refresh_connection
20
Rack レイヤーでリクエスト毎に接続を切るやつ
1行追加でおk
# config/application.rb
class Application < Rails::Application
config.middleware.swap ActiveRecord::ConnectionAdapters::ConnectionManagement,
"ActiveRecord::ConnectionAdapters::RefreshConnectionManagement"
end
https://github.com/sonots/activerecord-refresh_connection
http://blog.livedoor.jp/sonots/archives/38797925.html
22. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
クライアントDNSキャッシュ
22
!
• ruby 実装
• キャッシュしないと名前解決遅い
• 重み0なmasterへのfallback
23. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Slave 1
MySQL
Slave 2
MySQL
Slave 3
MySQL
Master 1
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.1
10.1.1.4
テーブルを
キャッシュ
select
DNSキャッシュ
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 1 | 1 | sample_w | 10.1.1.1 | 100 |
| 2 | 1 | sample_r | 10.1.1.2 | 100 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
10.1.1.2
ファイルに落とす
24. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
MySQL
Master 2
MySQL
Slave 2
MySQL
Slave 3
MyDNS
Web
10.1.1.2
10.1.1.3
10.1.1.4
重み0へのfallback
| id | zone | name | data | aux |
|----|------|----------|----------|-----|
| 1 | 1 | sample_w | 10.1.1.1 | 100 |
| 2 | 1 | sample_w | 10.1.1.2 | 0 |
| 3 | 1 | sample_r | 10.1.1.3 | 100 |
| 4 | 1 | sample_r | 10.1.1.4 | 100 |
MySQL
Master 1
10.1.1.1
weight:100
weight: 0
DNSプロトコルで引くと重み0のエントリが見えない。
Unbound などのDNSキャッシュを使えない。
25. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
ResolverMyDNS
25
resolver = ResolverMyDNS.new(
zone: 'mobage.local',!
cache_dir: "cache_dir/",!
host: 'localhost',!
username: 'root',!
passowrd: nil,!
database: 'mydns',!
)!
resolver.get_server 'foo.mobage.local'
#=> 10.1.1.10
MyDNSのテーブルエントリをクライアントサイド
でキャッシュして名前解決するやつ
@Spring_MT
26. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
26
@ryopeko
これアプリコード内でIPアドレス取得
して establish_connection に渡
す必要あるけど、めんどいよね?
そうすな∼
27. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
ResolverReplace
27
resolver = ResolverMyDNS.new(...)!
# Resolver を resolver_mydns にすげかえる!
ResolverReplace.load_plugin('mysql2')!
ResolverReplace.register!(!
getaddress: resolver.method(&:get_server),!
getaddresses: resolver.method(:get_server_list),!
error_class: ResolverMyDNS::Error,!
)
Rubyの名前解決を挿げ替えるやつ
https://github.com/sonots/resolver_replace
28. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
ResolverReplace
28
!
• ぶっちゃけると ruby が持っている
resolv-replace のパクリ
• resolv-replace は ruby の名前解決を
libc から Resolv クラスに置き換えるやつ
• 任意のクラスに置き換えられるように拡張
29. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
ResolverMyDNS
欲しい人???
29
ResolverReplace は
OSS になってる
https://github.com/sonots/resolver_replace
31. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
DeNAでのDBパスワード管理
31
!
• yaml で一元管理(インフラ管理. アプリ毎に管
理させない)
• DBIx::DBHResolver という perl モジュール
を通して取得する
• stage, sandbox など環境毎にパスワードが違
うが、同じコードで取得できる
32. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
dbhresolver
32
!
• 既存の yaml を処理して ActiveRecord が受け
取る形式で吐き出してくれる ruby gem
production:
<<: *default
<%= dbh.connect_spec('SAMPLE_R') %>
sample_r_production:
<<: *default
<%= dbh.connect_spec('SAMPLE_R') %>
sample_w_production:
<<: *default
<%= dbh.connect_spec('SAMPLE_W') %>
34. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
DeNAでのスキーマ管理
34
!
• git レポジトリで一元管理(インフラ管理. アプリ
毎に管理させない)
• SQL::Translator::Diff という perl モ
ジュールを使って実際のDBスキーマとの diff を
とった alter 文を作ってもらいマイグレーション
• ruby である必要はないのでそのまま利用
36. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
複数DB接続
36
!
• read/write 用モデルそれぞれ作ってゴ
リゴリ実装することもできる
• が、良い仕組みを使って実装を楽にしたい
37. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
37
ク社どうやってるの?
octopus辛みありそう...
switch_pointという
のがあってだな @sora_h
38. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
完全に実用段階!!!
38
SwitchPoint
詳しくはeagletmt先生の資料をご参照ください
39. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
SwitchPoint
39
SwitchPoint.configure do |config|
config.define_switch_point :db1,
readable: :db1_readonly,
writable: :db1_writable,
config.define_switch_point :db2,
readonly: :db2_readonly
end
class Book1 < ActiveRecord::Base
use_switch_point :db1
end
class Book2 < ActiveRecord::Base
use_switch_point :db2
end
https://github.com/eagletmt/switch_point
40. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
Adminsbar
40
http://admins.bar/3/
41. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
まとめ 複数DB編
41
!
• DB接続を都度接続に
• activerecord_refresh_connection
• クライアントサイドDNSキャッシュ
• resolver_mydns / resolver_replace
• DBパスワード一元管理
• DBスキーマ一元管理ツール
• 複数DB対応
• switch_point
42. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved.
その他インフラ要件の壁
42
!
• ホットデプロイ
• カスタムフォーマットのロガー
• デプロイサーバでビルドした gem を web
サーバにアプリコードと共に撒く
• 社内 rubygems ミラー
• Q4M 非同期ジョブ
• プロファイリングツール、調査ツール