インターンシップの学生向けの講義資料です。
pixivを支える技術2014
View Slide
自己紹介● 高山温○ @edvakf● 2012年の3月に入社しました● pixivチームのリーダーをしています● 最近はグロースチームでpixivのプレミアムやアクティブユーザーまわりの数字を追いかける他、難しい事をプラットフォームチームにお願いするお仕事をしています
pixivという会社の事業の1つとしてpixivというウェブサービスがある他にはピクシブ百科事典、pixiv comic、BOOTH、Cure、World Cosplayなど
ウェブサービスとはHTTPを通じて● 情報を格納したり● 情報を取り出すことを特定のロジックに基づいて行うシステムのこと
ウェブサービスに必要なもの● 情報の格納場所● 情報を格納したり取り出すロジック● HTTPでやりとりする仕組み
つまりウェブサービスは● ストレージ● アプリケーション● HTTPサーバーで成り立っている
pixivというウェブサービス● ストレージ○ MySQL○ KyotoTycoon○ WebDav (ファイルシステム)○ Apache Solr○ Apache Traffic Server○ (Redis)○ (MongoDB)● HTTPサーバー○ Apache○ nginx● サーバーサイドアプリケーション○ PHP○ (Go)● クライアントサイドアプリケーション○ HTML+JavaScript○ iOSアプリ○ Androidアプリ● バッチ○ PHP○ (C++)○ (Scala)
pixivというアプリケーションには1. サーバーサイドウェブアプリケーション2. クライアントサイドアプリケーション3. バッチがあり、1と3はほぼすべてPHP「バッチもpixivというアプリケーションの重要な一部」
ここまでで質問?
Question:● pixivの平均レスポンスタイムは?● MySQLの1 SELECTの時間は?● 1ページにMySQLのクエリは何個?● 100ms● 5ms● 20個
コネクションの確立の時間MySQLへのリクエスト1回だけなら5msぐらいだが、同じコネクションで10回リクエストすれば2回目からは1〜2msぐらいになる→TCPコネクションは少ないほどよい
Question:● 1リクエスト内でCPUを一番使う処理は何?● それはどのぐらい時間がかかってる?● テンプレートエンジン● レスポンスタイムの30%〜40%
つまりpixivのサーバーサイドウェブアプリケーションは● MySQLが50%● テンプレートエンジンが40%● KTが5%● その他のCPU処理が5%
フレームワークは?pixivはPHPのフレーワークを採用していない。最大の理由は、最初に作られたときにフレームワークを使ってなかったから。フレームワークを使ったらあと50msぐらいは増えるし、今からの全面導入は微妙かも。
Aside: DRYにするべきところ● DRY(don't repeat yourself)するかしないか、その判断基準について● DRYにしない選択肢もあることを意識している○ DRYにするべきところがDRYになっていないこともあるのが課題
Question:ウェブアプリケーションのレスポンスを速く返すのに最も効果的な方法は?
Question:ウェブアプリケーションのレスポンスを速く返すのに最も効果的な方法は?● インデックスの使われないクエリをなくす● キャッシュする
ウェブアプリのキャッシュ戦略キャッシュと言ってもレイヤーも方法も色々● 304 Not Modified● LocalStorage (JavaScript)● KVS (memcached / redis)● Shared Memory Cache● Fragment Cache (Rails)● Proxy Cache (Apache, nginx)
pixivのキャッシュ戦略サーバーサイドウェブアプリのレイヤーでは● KyotoTycoon (KT)○ memcachedプロトコルのキャッシュサーバー● APC○ PHPのShared Memory Cache○ アプリケーションサーバーのローカルキャッシュpixiv engineering blog: pixivのデータストア/キャッシュ戦略
その他のpixivのキャッシュ● 304はPHPのリクエストでは返していない○ 投稿画像やCSSなどの静的ファイルには多用● AjaxリクエストをLocalStorageにキャッシュ○ pixivポップボードのキャッシュの仕組みとFacebookのUIの話● MySQLのクエリキャッシュ○ テーブルに更新クエリがあるたびに破棄される○ 更新の多いテーブルでは意図的にオフにしてる● Solrへのリクエストをnginxでキャッシュ
Aside: Solrについて● オープンソースの検索エンジン● MySQLからバッチでSolrに流し込んでいる○ pixivでは唯一Scalaで書かれたコード● PHPからはHTTPで通信○ HTTPはインターネットとのやりとりの他にもミドルウェアとのやりとりにも使われる○ HTTPであることで、nginxのような普通のプロキシが使える
Question:pixivというサービスがキャッシュと相性が悪い理由は何?
Question:pixivというサービスがキャッシュと相性が悪い理由は何?● ロングテールなアクセス● R18見る設定やマイピク限定画像など、1つのビューでも出る要素の組み合わせが複雑● アクセスが多すぎてキャッシュが無くなると一気にMySQL(など)にクエリが流れる
ロングテール(80:20の法則)全データの20%が80%のアクセスを占める→キャッシュのヒット率がとても悪いpixivではロングテールなデータは最小限しかキャッシュせずにMySQLを直接参照するキャッシュしてもKTだけで、APCは使わない
バッチによるキャッシュ(?)生成バッチで生成してKTに入れてるデータがあるランキング, レコメンデーション, BloomFilter, コンテストデータ, 人気タグ, etc.計算量が多い場合や、pixiv本体とは疎結合にしたい別アプリケーションで、KTのデータだけでpixivとつながっているなどKTはあくまでもキャッシュなので、いつ消えても全部作り直せることに気をつけている
バッチについて「バッチもpixivというアプリケーションの重要な一部」一般に:● 定期的に実行される (cron job)● 無限ループで常に動いている (daemon)がある
Question:cronの問題点は?
Question:cronの問題点は?● rootでないと更新できない● コマンドが失敗したかわかりにくい● コマンドのログが見れない● コマンドの実行履歴が見れない● とにかく面倒!!○ /etc/cron.d/ 以下のファイル名に制約があるとか○ パーミッションに制約があるとか
Jenkins元は継続的インテグレーションのためのツールだが、cronの代替としてとても優秀● 登録されているジョブが一覧できる● 現在走っているジョブが一覧できる● ジョブの実行中の標準出力が見られる● ジョブの過去の失敗履歴やログが見られる● ウェブ画面ですべて操作できる
pixivでのJenkinsCI用途でしか使ってなかったが、今年からcronの代替として全面導入daemon的な処理もJenkinsで1分おきに実行● 1分したらwhileループを抜ける● デーモンの管理にJenkinsほどの良いツールが無いのが理由(の1つ)
MySQLサイトの規模が大きくなると必ず行わなければいけないこと、それは「データベースの系統を分ける」ユーザーIDで分割したりデータの日付で分けたりすることもあるが、pixivではテーブルのアクセス頻度や機能ごとに分割している
データベース系統● ユーザー、イラストデータ● 小説● プレミアム関係● ブックマーク● グループ機能● プレミアム向けアクセス解析などなど、それぞれにMasterが1台とSlaveが複数ある
Question:サービスのデータベースが1系統のみであることが望ましい理由は?
Question:サービスのデータベースが1系統のみであることが望ましい理由は?● JOINが使える● トランザクションが使える● ウェブアプリケーションから複数のDBに接続しなくてよい
DBまわりで特に意識していること● 最近はJOINはあまりしない方針○ アプリケーションレベルのJOINを多用● ORMは使わない○ 流れるクエリを意識するためにSQLを手書き○ ガチガチにチューニングしたクエリがたくさん● MySQLにアクセスする層とアプリケーションロジックの層を分離
Aside: pixiv最大のデータベースブックマーク● 12億レコード○ uint32max = 42億● 1年で倍増弱ぐらい今後、市販のメモリで収まりきらなくなれば、期間で分割なども考える必要があり、更にカオスに…
Question:pixivではほぼすべてのユーザーデータはMySQLに入れているが、MySQLに入っていないデータは何?
Question:pixivではほぼすべてのユーザーデータはMySQLに入れているが、MySQLに入っていないデータは何?投稿された画像
画像ストレージリレーショナルデータベースに入らないファイルは、どのサービスもそれぞれの要件に合わせて頭をひねる部分pixivではWebDAVを採用している● HTTPのGETやPOSTでファイルシステムにアクセスするプロトコル● Apacheやnginxのプラグインとして使える
Question:画像をMySQLに保存しない理由は?
Question:画像をMySQLに保存しない理由は?● ファイルあたりのサイズが大きい● 総容量も多い(40TB)● 配信するときにApacheやnginxが直接読めるファイル単位としてある方が便利● 管理上もファイルとしてあるほうがSQLを書いて取り出すよりラク
pixivの画像の特徴● 1つ1つが手作りなので写真と違って増えるスピードは速くない● PC、スマホ、ガラケーなどがあり、生成するサムネイルの種類が多い● 漫画の枠や、正方形クロップ時の特殊な変換● 変換後も同じファイルフォーマット○ なんでそうしてしまったのか…● 数々の歴史的経緯…● 最近ではうごイラも
pixivの画像変換● 昔はすべてのサムネイルを投稿時に変換して保存● 非同期アップロード化(2009)○ pixivの画像アップロードシステム● mod_small_lightで配信時に動的変換○ ただしリクエストの多いサムネイルは静的サムネイルのまま○ YAPC::Asia 2012「pixivのサムネイル事情」● サムネイルマスター(2014)○ サムネイル生成元となる大きめのサムネイルをJPEGで用意● サムネイル変換クラスター (2014)○ https://github.com/pixiv/go-thumber○ 近日稼働予定!
画像配信pixivというウェブアプリケーションとpixivの画像ストレージ、配信はまあまあ疎結合→今後はもっと疎結合にしていきたい理想はAmazon S3のように、ファイルをPOSTするとURLが返ってくるぐらいのブラックボックスにしていきたい詳しくはインフラのところで話されるかも?
そろそろまとめ主にpixivのサーバーサイドアプリケーションを、ストレージとキャッシュに注目して見ていきました。pixivならではのパフォーマンス上の問題やアプリケーションの制約についていくつか紹介しました。
今日話さなかったこと● 個別機能にまつわる話● クライアントサイドの話● デプロイの話● テストの話● グロースチームのエンジニアとしての話その他いっぱい→興味があればあとで質問歓迎