PHPカンファレンス 2017 でお話できなかったので、PHP勉強会@東京で【MySQLで画像を扱うメリット・デメリットと障害・解決事例】として登壇してきました

f:id:Mamy1326:20171027015745p:plain

エンジニアの @mamy1326 です。 気づいたら 入社エントリー から3ヶ月近く経過してますね。これはいかん!

というわけで登壇報告も兼ねて、エントリーを。

PHPカンファレンス 2017 で登壇予定が…

PHPカンファレンス 2017 にて MySQLで画像を扱うデメリットと特殊パターン としてお話する予定だったのですが、諸般の事情 1 でキャンセルすることになってしまい… もやもやする日々を送っていたのですが、PHP勉強会@東京 の中の人からお誘いを頂き、2017年10月25日に登壇させて頂くことができました。

【登壇】MySQLで画像 を扱うメリット・デメリットと障害・解決事例

というわけで、少し改題して、登壇してきました。 2

テーマ

  • MySQLの BLOB型 に実際に画像をたくさん保存した事例を元に
  • 起こった障害と解決事例を紹介し
  • MySQL(RDB)で画像(大きなバイナリデータ)を扱うことの
  • メリット、デメリットをお話し
  • RDB、プログラムの責務
  • サービスの特性と要件を熟考
  • 適切に運用を設計して行きましょう

というお話を、20分枠でさせて頂きました。

BLOB型 is 何?

Binary Large Object の略で、RDBにバイナリデータを格納する場合のデータ型です。 MySQLの場合、扱えるデータ型の種類は以下になります。 3

型名 扱える最大長(バイト)
TINYBLOB 255 (28 - 1)
BLOB 65,535 (216 - 1)
MEDIUMBLOB 16,777,215 (224 - 1)
LONGBLOB 4,294,967,295、または4GB (232 - 1)

持ち帰って頂きたかったこと

  • 適切なBLOB型の使い方
  • うっかりバイナリデータを扱って痛い目にあわない方法
  • 画像を含む、大きめもしくは大量のバイナリデータをRDBで扱うデメリット
  • 画像を含む、バイナリデータを扱う場面
  • ユーザーが運用でどう振る舞うか想定する
  • 責務、サービスの特性を考えて、運用設計をするのは大事
  • データの寿命はアプリより長い

いずれかを持ち帰って頂けたら幸いです。

伝えきれなかったこと

20分という時間の都合で、伝えきれなかったこともありました。 そこで、ブログを借りて書いてみます。

現在ならどう画像保存するかの話

障害当時、クラウドを利用していないサービスでした。質問も頂きましたが、現在でしたらAWS前提だと

  • S3にアップ し、CloudFrontを通して配信する

と思います。

レイテンシの話

障害の話では、どこにボトルネックがあり、ユーザーの画面でタイムアウトとなっていたのかを、ざっくり流しただけでした。

f:id:Mamy1326:20171027025319p:plain
スライド54ページ 本番でのネットワークの流れ

本当は、以下のようにお話する想定でした。

  • クライアントからWebサーバーへのリクエストは当初さばけていた
  • WebサーバーからDBサーバーへのネットワークも逼迫していなかった
  • DBサーバーでのWRITEは当初さばけていた
  • 一度に大量の画像を伴う、大量のリクエストがきた
  • DBサーバーのディスクIO(WRITE)が遅くなった
  • WRITE遅延により 画像を含むデータがWeb-DB間のネットワークを圧迫、帯域が100%に
  • WebサーバーのプロセスがDB処理待ちでタイムアウトとなる

どのようにデータが流れ、ネットワークを圧迫していくのか。ボトルネックになっていくのか。そう言った話は別の機会にしてみたいですね。

適切なBLOB型の使い方

発表ではBLOBに画像のバイナリデータをWRITEして障害が起きた話を元に、メリットデメリットをお話しました。 が、適切な使い方まではしっかり話せませんでしたので、いくつか紹介します。

  • アイコンなどの小さな画像
  • 1レコード1画像なら…(発表後にもご指摘頂きました)

が、これ以上の適切な使い方、まだ遭遇したことありませんので、経験ある方がコメントください!

特殊パターン

これは特殊パターンである、と明言してませんでした。メリットの中でも話しましたが、以下のパターンだと考えています。

  • カルテへの添付画像など、暗号化・セキュアに取り扱う必要がある
  • 要件により、画像の履歴(監査)・バージョン管理をしたい 4

要件によるのかな、ということは言えると考えています。

何がベストなのか?

スライドでは1枚、発表時にも4項目でお話しした内容でしたが、補足してみます。

f:id:Mamy1326:20171027024044p:plain
スライド104ページ 何がベストなのか

  • 特殊な要件の場合に使う
    • お客さんへの説明、ユーザーの利用シーンの想定をしっかり行う
    • 要件を鵜呑みにするのではなく、特殊なパターンか否かを適切に判断することがベスト
  • パフォーマンス・コストとのトレードオフ
    • 手間やコストをかけてでも実装すべきかを適切に判断することがベスト
    • さらに、運用コスト(将来的な資源面でのコストも含む)も計画でき、納得頂いていることがベスト
  • 設計・実装をしっかり計画
    • 当たり前のことですが、だろうで思考を放棄せず、設計・実装、その先の運用をしっかり計画することがベスト
    • 疑問を持ったら、必ず深く掘り下げることがベスト
  • RDBの本来の責務を考慮
    • RDBだけでなく、プログラム、キャッシュなどの責務を適切に考慮することがベスト
    • サービスの特性、画像を含むバイナリデータがどう扱われるか・扱いたいのかを適切に考慮することがベスト

常にベストを尽くしたいな、といつも思います。

実際の運用シーンを深く考える

提供した機能がどう使われるか、開発者目線ではなく、利用者目線で深く厳しく考える必要があると思います。

  • ユーザーさん、お客さんは、そこに機能がある限り、フルパワーで限界まで使い倒します 5
  • 一度に登録できる画像が20個あれば、結論として、使います。開発者の想定を必ず超えてきます
  • 同じく、最大接続ユーザー数も想定を必ず超えてきます。そのサービスが成長していくならば
  • ストレージ、メモリ、CPU、資源はいつか枯渇します

ところで、PHP勉強会@東京とは…?

シナジーカフェ GMO Yours さんで毎月開催されている、50人規模の勉強会です。

  • コアなPHPerも、これから始めるPHPerも誰でも気軽に参加できる
  • PHPにちょっとでも関連すれば大丈夫 6
  • フロントエンドからインフラまで多様な場所 7

いつもいい出会いと話がある、学びの多い場所です。人生初の登壇の機会を得たのもPHP勉強会@東京ですし、イノベーター・ジャパンに入社する遠いきっかけとなったのもPHP勉強会@東京でした。

そして、ただただ感謝

PHPカンファレンス 2017 実行委員会のみなさま、僕のセッションを視聴したいと思ってくださっていたみなさま、5人揃って登壇したかったチームメンバーのみんなには、本当に申し訳なかったとともに、直前でのキャンセルを受理してくださって本当に感謝です。

そして、実行委員会の中の人でもあった PHP勉強会@東京 での登壇のお声がけをして頂けて、本当に感謝しています。今後も継続して貢献していかねば、と気持ちを新たにさせて頂きました。

これからも、個人としても会社としても、アウトプットの場を広げていきたいと思います。


  1. 幼稚園の運動会が雨で10月8日(日)に順延

  2. 登壇中にも質問を頂き、発表後にも5分くらい質疑応答があったり、個人的にはすごく盛り上がりました

  3. MySQL公式のBLOB 型と TEXT 型 に詳しい記述があります

  4. ただし、パフォーマンスを犠牲にする可能性が高いので、適切に解説した上で設計・実装・運用する必要がある

  5. 少ないですが、極端な例で、1G以上の画像を連続でリクエストされた経験があります

  6. 何度か登壇させて頂いてますが、僕は一度もPHPメインの話をしておりません(汗

  7. 飲み物も軽食も豊富ですが、単なる飲み会じゃないよ!