Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Mobage を支える Ruby の技術 ~ 複数DB編 ~

20,217 views

Published on

Published in: Technology
  • Be the first to comment

Mobage を支える Ruby の技術 ~ 複数DB編 ~

  1. 1. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. Mobageを支える November 11th, 2014 ! Naotoshi Seo @sonots
 DeNA Co., Ltd. Rubyの技術 ~複数DB編~
  2. 2. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 2 自己紹介 ・瀬尾 直利 @sonots ・DeNA, Co., Ltd ・インフラの Dev ・Rubyist ・OSS 活動家 ・Fluentd コミッタ
  3. 3. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 背景 3 ! Perl の会社と名高いこの DeNA でも Ruby (on Rails) のプロジェクトが立ち 上がり始めている
  4. 4. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. インフラ要件の壁 4 ! • ホットデプロイ • カスタムフォーマットのロガー • デプロイサーバでビルドした gem を web サーバにアプリコードと共に撒く • 社内 rubygems ミラー • Q4M 非同期ジョブキュー • プロファイリングツール、調査ツール
  5. 5. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 複数DB対応 5 ! • Rails で複数DBに対応する必要性 • 冗長化・高速化 • 既存のインフラの仕組みにのっかる必要性 • 今回はここに特化した話
  6. 6. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 目次 6 ! • DB接続を都度接続に • クライアントサイドDNSキャッシュ • DBパスワード一元管理 • DBスキーマ一元管理ツール • 複数DB接続
  7. 7. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. DB接続を都度接続にすべし 7 要件1
  8. 8. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. DeNAでの複数DB構成 8 ! • MySQL: Master/Slave • DNSラウンドロビンでSlaveを振り分ける • MHA で Master の高可用化 • DNS サーバには MyDNS を使用
  9. 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. 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. 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. 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. 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. 14. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. DBWeb DBを再起動 restart 再接続 or 都度接続 ※ ただし、ActiveRecord の reconnect は正しく動かなかったり ※ そのため、アプリの再起動が必要だったりして、ツライ
  15. 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 都度接続
  16. 16. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. すべて都度接続で解決 16
  17. 17. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. しかしActiveRecord には都度接続オプションがない 17
  18. 18. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 18 なんだってーーーΩΩΩ
  19. 19. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 作りました 19
  20. 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
  21. 21. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. クライアントDNSキャッシュ 21 要件2
  22. 22. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. クライアントDNSキャッシュ 22 ! • ruby 実装 • キャッシュしないと名前解決遅い • 重み0なmasterへのfallback
  23. 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. 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. 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. 26. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 26 @ryopeko これアプリコード内でIPアドレス取得 して establish_connection に渡 す必要あるけど、めんどいよね? そうすな∼
  27. 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. 28. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. ResolverReplace 28 ! • ぶっちゃけると ruby が持っている resolv-replace のパクリ • resolv-replace は ruby の名前解決を libc から Resolv クラスに置き換えるやつ • 任意のクラスに置き換えられるように拡張
  29. 29. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. ResolverMyDNS 欲しい人??? 29 ResolverReplace は OSS になってる https://github.com/sonots/resolver_replace
  30. 30. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. DBパスワード管理 30 要件3
  31. 31. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. DeNAでのDBパスワード管理 31 ! • yaml で一元管理(インフラ管理. アプリ毎に管 理させない) • DBIx::DBHResolver という perl モジュール を通して取得する • stage, sandbox など環境毎にパスワードが違 うが、同じコードで取得できる
  32. 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') %>
  33. 33. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. マイグレーション 33 要件4
  34. 34. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. DeNAでのスキーマ管理 34 ! • git レポジトリで一元管理(インフラ管理. アプリ 毎に管理させない) • SQL::Translator::Diff という perl モ ジュールを使って実際のDBスキーマとの diff を とった alter 文を作ってもらいマイグレーション • ruby である必要はないのでそのまま利用
  35. 35. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 複数DB接続 35 要件5
  36. 36. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 複数DB接続 36 ! • read/write 用モデルそれぞれ作ってゴ リゴリ実装することもできる • が、良い仕組みを使って実装を楽にしたい
  37. 37. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 37 ク社どうやってるの? octopus辛みありそう... switch_pointという のがあってだな @sora_h
  38. 38. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. 完全に実用段階!!! 38 SwitchPoint 詳しくはeagletmt先生の資料をご参照ください
  39. 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. 40. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. Adminsbar 40 http://admins.bar/3/
  41. 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. 42. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. その他インフラ要件の壁 42 ! • ホットデプロイ • カスタムフォーマットのロガー • デプロイサーバでビルドした gem を web サーバにアプリコードと共に撒く • 社内 rubygems ミラー • Q4M 非同期ジョブ • プロファイリングツール、調査ツール
  43. 43. Copyright (C) 2014 DeNA Co.,Ltd. All Rights Reserved. We're hiring!! 43

×