Upload
hiroaki-sano
View
2.166
Download
0
Embed Size (px)
Citation preview
トレタのMySQLMySQL casual #8 (小規模限定回)
2015/11/20 Hiroaki Sano
me• Name:
• 佐野裕章(Hiroaki Sano)
• Personal info: • https://hiroakis.com/blog/ • https://twitter.com/la_luna_azul • https://github.com/hiroakis
• Company: • SIer(2006/4-) • CyberAgent, Inc(2011/3-) • Toreta, Inc (2014/11-)
トレタ• 飲食店向け予約管理アプリケーション、一般ユーザ向けにウェブ予約も提供
• 顧客:レストラン、居酒屋などの飲食店
• 例えば…
• 俺の株式会社様(俺のイタリアン、俺のフレンチ…etc)
• 株式会社大庄様(庄や、やるき茶屋…etc)
• ローストホース様
• etc • ローンチは2013年12月
• 導入店舗数:3700店舗~
• 店舗あたりの月額課金
• オフィスは五反田
これを
こうじゃ
トレタのコンセプト
• 飲食店の予約管理、顧客管理をIT化
• 予約事故を防ぐ
トレタ
• アクセスのピーク
• 時刻:夕方6 pm JSTあたり
• 曜日:金曜日 > 他 > 土曜日 > 日曜日
• 夜の営業開始直後くらいに当日の予約確認をしていると思われる
トレタのMySQL
話すこと
• 経験上、大規模から小規模に変わった時に感じたことか、小規模ならでは(?)のことをば…
トレタ
MySQL Master
Engineyard
ブラウザiPad
MySQL Slave
MySQL Slave
Users
App
• サーバ側のコア機能はEngineyardで稼働
• 一部機能はAWS(S3, Route53..etc)やHerokuにも存在
• モニタリング、分析などはSaaSを利用Mackerel, NewRelic, BigQuery…etc
トレタのMySQL
MySQL Master
Appサーバ
MySQL Slave
MySQL Slave
Rails
HAProxy
Write
Read
Replication
TCP 127.0.0.1:3306
• MySQL on Engineyard
• MySQL5.6
• InnoDB
• m3.largeが3台(Master:Slave=1:2)
• ほとんどがRead
• スレーブは主にバッチの参照用、調査用、昇格用
• 小規模(だと思う)。
worker
小規模ならではのことってなんだろう
• トレタの場合…
• Likeフィルタによる全文検索が割と動く
• キューっぽい使い方をしても割と動く
• 大規模に比べると運用が楽(シンプルなので)
全文検索
全文検索
SELECT DISTINCT `reservations`.`id` FROM `reservations` LEFT OUTER JOIN `customers` ON `customers`.`id` = `reservations`.`customer_id` LEFT OUTER JOIN `customer_phones` ON `customer_phones`.`customer_id` = `customers`.`id` LEFT OUTER JOIN `customer_emails` ON `customer_emails`.`customer_id` = `customers`.`id` WHERE `reservations`.`restaurant_id` = XXXX AND ( concat(customers.last_name, customers.first_name) like '%さの%' OR concat(customers.last_name_reading,customers.first_name_reading) like '%さの%' OR customers.company_name like '%さの%' OR customers.note like '%さの%' OR reservations.note like '%さの%' OR customer_emails.email like '%さの%' OR ) ORDER BY `reservations`.`start_at` DESC LIMIT 10 OFFSET 0;
• Likeの部分一致検索
全文検索
• InnoDBのフルテキストインデックスは使っていない
• Mroongaも使っていない
• WHERE `reservations`.`restaurant_id` = XXXXでの絞り込み
• (レコード数が少なければ)案外なんとかなる
カジュアルな話:なぜ部分一致検索は遅くなりがちか
• ここで試しに本当にカジュアルな話も挟んでみます…
• select * from t where col like ‘%word%’ • 理由:インデックスが効かないから
• Indexing LIKE Filters • http://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-
tuning • インデックスとは索引。つまりそのままの意味。
• 前方一致のみインデックスが効く。
Likeフィルタで発生した事案• select * from t where col like ’{POST_DATA}%’
• 空のPOST_DATA
• select * from t where col like ’%’ • DBマスタのCPUが100%になってしまった
• バリデーション漏れ
MySQLでキューのようなことをする
MySQLでキューのようなことをする
MySQL Master
Appサーバ
MySQL Slave
MySQL Slave
Rails
HAProxy
Write
Read
Replication
TCP 127.0.0.1:3306
• 現地時間の午後3時に一部の顧客にメールを送る機能
• 定期的に各appサーバのworkerが一斉に動き出してMySQLに参照/更新を行う
• あるworkerが処理中のレコードは他のworkerに処理させたくない
• workerはsidekiq(非同期処理を行うgem)で実装
• 基本的には非同期的な処理を行っているがこのようなバッチ処理ぽいこともworkerにやらせている
worker
MySQLでキューのようなことをする
MySQL
WorkerWorkerWorkerWorker
CREATE TABLE `queues` ( `id` int(11) NOT NULL AUTO_INCREMENT, `reservation_id` int(11) NOT NULL, `status` tinyint(4) NOT NULL DEFAULT '0', `reminded_at` datetime DEFAULT NULL, `created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `index_reservation_remind_emails_on_reservation_id` (`reservation_id`), KEY `index_reservation_remind_emails_on_status_and_reminded_at` (`status`,`reminded_at`) ) ENGINE=InnoDB AUTO_INCREMENT=343046 DEFAULT CHARSET=utf8
select * from queues where status = 0 and reminded_at < now() => レコードが未処理(status=0) かつ現地時間午後3:00を過ぎているもの(reminded_at < now())を取得
update queues set status = 1 where id = ? and status = 0 => レコードを処理中としてマーキング(status=1) => ここでaffected_rowsが1なら自分が処理する 0だと他のworkerが処理するので何もしない => 処理に成功したらレコードを消す
• 参考
• http://qiita.com/masuyama/items/645b25f03dc9e321cb96
MySQLでキューのようなことをする
• 下記の記事で指摘があるように、正直、悪手ではある
• http://www.engineyard.co.jp/blog/2013/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you/
• が、レコードが大量でなければ問題なく動く。
大規模に比べると運用が楽
大規模と小規模の構成の違い(経験上)
大規模時代 今
バージョン 4.1, 5.0, 5.1, 5.5, 5.6 5.6
ストレージエンジン MyISAM, InnoDB, Blackhole InnoDB
インフラ大量のハイエンド物理サーバWrite Heavyな箇所にはフラッシュを活用
クラウドに3台
特徴
種々の課題に対応するためにインフラ、MySQL側やることが多くなりがち(だった)。シャーディング、レプリケーションフィルタによるテーブルの分散、InnoDBの圧縮の活用、カスケード構成…etc
業務アプリケーションのバックエンドなのでトラフィックはある程度予測できる。ウェブ予約で多少のスパイクあり。 コンフィグとしては基本的な設定をケアすれば良い。
大規模に比べるとシンプルなので運用が楽
• 小規模だから楽、というよりは構成がシンプルだから楽。
• 大規模になってもシンプルなアーキテクチャを保つべき。
• Railsのmigrationで運用が回る
まとめ• 小規模だと…
• 多少の悪手でも大丈夫
• Likeフィルタの部分一致検索
• キューもどき
• かといってインデックスが全く効かないのは危険
• ちゃんとインデックスを張る。インデックスを使うようなSQL投げる。
• ちゃんとモニタリングする
• 大規模よりは運用は楽
• 構成がシンプル
• 大規模になってもシンプルな構成を維持すべき
• ある程度の規模まではMySQL+著名なフルスタックフレームワークでビジネス要件が満たせるシステムが構築できている
迫り来る課題
• 悪手からの脱却
• その用途に最適化されたミドルウェアの導入etc
• Railsのmigrationに依存した運用からの脱却
• 生のalterがだんだんキツくなってくる
最後にサラリーマンとして言わせてください
We are hiring!https://toreta.in/recruit
おわり