Your SlideShare is downloading. ×
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜

2,332

Published on

GREE Tech Talk #05での発表資料です。 …

GREE Tech Talk #05での発表資料です。
http://techtalk5.labs.gree.jp/

Published in: Engineering
0 Comments
15 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,332
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
11
Comments
0
Likes
15
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • ・まず、弊社で並行・並列処理がどのようなところで発生しているか、紹介したいと思います。〜
  • ・サーバサイドでは
  • 〜・(Redisのコードの話でもする?)・マルチプロセッサ環境でスケールさせるためには、プロセッサの数だけプロセスを立ち上げる必要があります。・いずれの方法をとるにせよ、プログラミングは簡単ではありません。
  • ・我々は過去数年間マルチスレッドサーバを運用してきましたが、ちゃんと動かすのは簡単ではありません。・まず、競合している状態を再現させるのが難しい、という問題があります。〜・次に、修正が正しいかの検証が難しいという問題があります。〜・人間が考えてもどうしても確証がもてない場合、SPINなどのツールを使って全状態をチェックすることになりますが、・ツールに入力するモデル(プログラムを単純化しなもの)はやはり人間がつくるので、モデルが間違っていれば検証も間違っている可能性があります。〜・結局、バグを踏んで、解析して、修正するということを繰り返した結果、安定したソフトウェアができあがる、というのが現状です。
  • ・たとえば、数年前にMemcachedの不具合が話題になったことがありました。・詳細は、mixiさんのエンジニアブログに書いてありますので、興味のある方は呼んでみてください。・このような事例をみますと、マルチスレッドのプログラミングは難しいという感想しかもてないですね。
  • Why Threads Are A Bad Idea (for most purposes) by John Ousterhout・マルチスレッドプログラミングが難しい、というのは昔からわかっていたことです。〜
  • ・結局のところ、なにがいけなかったのでしょうか。・〜
  • ・ここで思い返していただきたいのですが、Webアプリケーションは複数のユーザが並行に要求を行うにもかかわらず、・並行プログラミングにまつわる問題が一切生じていない、という事実です。・状態の保持を専用の機構に委譲して、トランザクションと呼ばれるブロックでアトミックに実行したい操作をDBにわたしていました。・じゃあ、変数を使うのをやめて、DBを使うようにすればいいのではないか、という素朴なアイデアが浮かびます。・ただそうしてしまうと、共有メモリは諦めないといけないですし、使えるデータ構造も限定されてしまいます。
  • (ここは他の人の発表で触れているはずなのでとばす)
  • ・さきほどのSTMの発表をおききになっていない方のために
  • ・Frontend
  • ■ 時間がなければ飛ばす
  • TODO: グラフをちゃんとしたものに置き換える。
  • TODO: グラフをちゃんとしたものに置き換える。
  • TODO: グラフをちゃんとしたものに置き換える。
  • Transcript

    • 1. Copyright © GREE, Inc. All Rights Reserved. サーバサイドの並行プログラミング 〜 かんたんマルチスレッドプログラミング 〜 2014/5/20 Infrastructure Department Kiyoshi Ikehara
    • 2. Copyright © GREE, Inc. All Rights Reserved.
    • 3. Copyright © GREE, Inc. All Rights Reserved. Webアプリケーション • 3層アーキテクチャ + CDN • フロントエンド(Nginx、Varnish など) • アプリケーションサーバ(Apache+PHP など) • データベース(MySQL など) • アプリケーションサーバは状態をもたない • HTTPのリクエストが終了したら終わり • 共有される情報はすべてDBに格納されている 問題の単純化:状態を分離 • どうやって整合性を保つか → 同じデータを同時に扱わない → データベースが競合を解決してくれる GREEにおける並行・並列 大規模Webサイトにおける並行処理
    • 4. Copyright © GREE, Inc. All Rights Reserved. リレーショナルDBの場合 • トランザクション分離レベルさえ気にすれば良い • SERIALIZABLE • REPEATABLE READ • READ COMMITTED • READ UNCOMMITTED KVSの場合 • 条件付き書き込み命令を使用する • Ex.) CAS命令 (Memcached / Flare) • 複数命令をまとめて処理する機能を使用する • Ex.) Multi … Exec命令 (Redis) GREEにおける並行・並列 大規模Webサイトにおける並行処理 (cont.)
    • 5. Copyright © GREE, Inc. All Rights Reserved. マルチプレイヤー型オンラインゲーム • クライアントは常にサーバに接続される • 複数のクライアント間で状態を共有 • DB上の状態もあれば、メモリ上にのみ存在する状態もある 問題の単純化:プロセスに分割 • ワールドなどの単位でプロセスを分割 • 各クライアントの処理をちょっとずつ進める(イベント駆動) パフォーマンスが求められる場合 • マルチプロセッサを活かすためにマルチスレッド化 • 並行プログラミング! GREEにおける並行・並列 マルチプレイヤー型オンラインゲーム
    • 6. Copyright © GREE, Inc. All Rights Reserved. マルチスレッドを使ったサーバミドルウェア OSSになっているもの • Flare (2008) • 分散KVS • https://github.com/gree/flare • PrimDNS (2011) • 高性能DNSサーバ • https://github.com/ebisawa/primdns 要件 • 多数のクライアントからの要求を処理できる • 数百〜数千台のWebサーバから接続が来る • マルチプロセッササーバでスケールする • 1サーバに10~20程度の論理コア GREEにおける並行・並列 自社開発ミドルウェア
    • 7. Copyright © GREE, Inc. All Rights Reserved. 各種KPIの算出 • 大量の情報の中から、欲しい時に素早く情報を提供する • 並列分散処理ミドルウェアを活用 • Hadoop, Hive, Presto … GREEにおける並行・並列 大量データの処理
    • 8. Copyright © GREE, Inc. All Rights Reserved. サーバサイドで並行プログラミングをする理由 • 多数のクライアントから同時に要求される処理をこなす • クライアント間で共有すべき状態が存在する よくある実現方法 • 各クライアント毎にスレッドを実行する • ロックと条件変数を使って整合性を担保する • 1つのスレッドで各クライアントの処理を少しずつ進める • イベントとコールバックを駆使する (ex. Redis, node.js) 並行プログラミングの方法 マルチスレッドとイベント駆動
    • 9. Copyright © GREE, Inc. All Rights Reserved. 各クライアント毎にスレッドを実行する • 利点:処理を順次書いていけばよい • 欠点:スレッド間の競合を意識する必要がある 1つのスレッドで各クライアントの処理を少しずつ進める • 利点:メモリアクセスの排他制御の必要がない • 欠点:処理を細切れに書くため、見通しが悪い マルチプロセッサを活用できない いずれの方法をとるにせよ、プログラミングは難しい 参考: 「マルチコア時代の サーバプログラミング と Haskell」(山本和彦さん) • http://www.iij.ad.jp/company/development/tech/techweek/pdf/tw2011_04_haskell.pdf 並行プログラミングの方法 利点と欠点
    • 10. Copyright © GREE, Inc. All Rights Reserved. 過去数年間マルチスレッドサーバを運用してきましたが・・ • 再現させるのが難しい • 「ある特定の行と行の間でスレッドが切り替わると起こるかもしれない」 • 「42億回クライアントが接続した後に起こるかもしれない」 • 「複数のサーバーが同時に故障すると起こるかもしれない」 • 修正が正しいかの検証が難しい • 複数スレッドの進行状況をすべて考慮する必要がある。 考慮したところで、人間の考えることは信用ならない。 • 不安なら全状態をツールでチェックすればよいが、状態のモデル化が大変。 モデルは人間が作るのでまちがってる可能性もある。 • 解決方法=枯れるのを待つ • もぐらたたきの結果、安定したソフトウェアができあがる マルチスレッドプログラミングは難しい サーバ運用の観点からみた難しさ
    • 11. Copyright © GREE, Inc. All Rights Reserved. 実例 • Memcached 1.4.6 のバグ • 複数のMemcachedが同時に落ちる • mixi.jp でアクセス障害(2010/8) • http://mixi.co.jp/press/2010/0812/3477/ • 詳細はmixiさんのエンジニアブログに書いてあります • http://alpha.mixi.co.jp/2011/10745/ 教訓(個人的感想) • 先人は偉大である • マルチスレッドプログラミングはやはり難しい マルチスレッドプログラミングは難しい サーバ運用の観点からみた難しさ(cont.)
    • 12. Copyright © GREE, Inc. All Rights Reserved. “Why Threads Are A Bad Idea (for most purposes)” by John Ousterhout (1995) マルチスレッドプログラミングは難しい 20年前から言われ続けている・・
    • 13. Copyright © GREE, Inc. All Rights Reserved. 30年の研究を経て、 共有メモリを用いたタスクレベルの並行処理で、 最も利用されている協調の仕組みは.... マルチスレッドプログラミングは難しい 結局なにがいけないのか mutex_lock() / cond_wait() (;´Д`) こ、こんな古い物を・・・ * http://research.microsoft.com/en-us/um/people/simonpj/papers/stm/STMTokyoApr10-Japanese.pdf • 並行プログラミングを容易にするいろいろな手法が過去発明されてき たにもかかわらず、それを利用することができていない。 ロックと条件変数(30年前の発明) * by Simon Peyton Jones
    • 14. Copyright © GREE, Inc. All Rights Reserved. Webアプリケーションはいかにして複雑さを回避していたか? • 状態の保持を専用の機構(=データベース)に委譲 • データベースの提供するトランザクションを利用 マルチスレッドプログラミングは難しい 結局なにがいけないのか(cont.) ( ゚д゚)ハッ! | \ __ / _ (m) _ピコーン |ミ| / .`´ \ ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ (・∀・∩< DBつかえばいいんじゃね (つ 丿 \_________ ⊂_ ノ (_)
    • 15. Copyright © GREE, Inc. All Rights Reserved. 我々はソフトウェアトランザクショナルメモリ(STM)を使っています STM • アトミックブロック内の一貫性保持 • プロック内では、あたかも自分のスレッドだけが動いているようにふるまう (SERIALIZABLEと同じ) • ロールバック • 処理の途中で変数への書き込みをなかったことにできる かんたんマルチスレッドプログラミング 並行プログラミングの容易化
    • 16. Copyright © GREE, Inc. All Rights Reserved. 実装の歴史 • GHC 6.4 (Haskell) − 2005年 • https://hackage.haskell.org/package/stm • Scala STM – 2010年 • http://nbronson.github.io/scala-stm/ • GCC 4.7 (C/C++) − 2012年 • http://gcc.gnu.org/wiki/TransactionalMemory (experimental) ほとんどの主要言語になんらかの実装があるようです • http://en.wikipedia.org/wiki/Software_transactional_memory#Implementations かんたんマルチスレッドプログラミング 実は普及しているSTM
    • 17. Copyright © GREE, Inc. All Rights Reserved. “Transactional Variable(TVar)”で状態を表現 • Intを保持したいなら TVar Int という型を使う • アトミックブロック内でのみ操作できる 動作 • とりあえず実行してみる • 自分がTVarを参照している最中に他の人がそれを 書き換えたら、処理をやり直す 特徴 • デッドロックの問題は回避できるが、 平等性(fairness)の問題がある • 処理を合成でき、合成してもSTMの性質を保つ • 現在の実装ではロックを使用しているっぽい HaskellのSTM 本発表から聴講された方向け 10章あたりにかいてあります
    • 18. Copyright © GREE, Inc. All Rights Reserved. • atomically − STMの実行を開始する • readTVar − TVarから値を読む • writeTVar − TVarに値を書き込む • retry − TVarが更新されるまで待って、処理をやり直す HaskellのSTM STMの使い方 main = do tvar <- newTVarIO "ガッ" forkIO $ forever $ atomically $ do x <- readTVar tvar if x == "ガッ" then writeTVar tvar "ぬるぽ" else retry forever $ atomically $ do x <- readTVar tvar if x == "ぬるぽ" then writeTVar tvar "ガッ" else retry
    • 19. Copyright © GREE, Inc. All Rights Reserved. • STMは合成可能 • STMの中では、任意のSTM関数 を呼び出して良い • TVarをプリミティブとして、 より複雑なデータ構造を構築 • Ex. TQueue • 例外でロールバックされる • 途中の状態は他から見えない • 「スレッドが例外で終了して状態 がおかしくなる」問題がない • ex. キューからアイテムを取り出 して別のキューにいれる HaskellのSTM STMはなにがすごいか Control.Concurrent.STM.TQueueの実装
    • 20. Copyright © GREE, Inc. All Rights Reserved. MVar • 1つものをいれられる箱 • putMVar関数 - もうすでに入ってたら、空くまで実行が停止する • takeMVar関数 – まだ入ってなければ、入るまで実行が停止する • 特徴 • スレッド間の制御に使える • 誤って使うとデッドロックする可能性がある IORef • アトミックに書き換え可能 • atomicModifyIORef関数 • 扱う変数が1個ならこちらを使ったほうが速い HaskellのSTM 他にもあるHaskellの状態保持機構
    • 21. Copyright © GREE, Inc. All Rights Reserved. • システム構成 • ZooKeeper • Frontend サーバ • Control サーバ • Flare Indexサーバ • Flare ノード STMの使用例 KVS自動運用システム Zookeeper Zookeeper Control Control Control Control Zookeeper Frontend Frontend Frontend Frontend Flare IndexFlare IndexFlare Index Web Servers Web Servers Web Servers Flare Flare Flare ノードの監視・制御 構築・管理 KVS自動運用システム アプリケーション 構築・管理 get/set get/set
    • 22. Copyright © GREE, Inc. All Rights Reserved. ゲートウェイサーバ (Frontend)ゲートウェイサーバ (Frontend)ゲートウェイサーバ (Frontend) • リクエスト処理スレッドと転送処理スレッドに分割 • それぞれのスレッドがキュー(TQueue)を介して通信 • スレッド+プロセス多重 • 性能と安全性を考慮してプロセス多重も併用 STMの使用例 ゲートウェイサーバの実装 リクエスト スレッド 転送処理 スレッド 転送処理 スレッド 転送処理 スレッド リクエスト スレッド リクエスト スレッド リクエスト スレッド リクエスト 受付キュー 応答受取 キュー Response Request Flare サーバ Flare サーバ Flare サーバ 転送処理 スレッド 転送 スレッド 転送処理 スレッド 転送 スレッド 転送処理 スレッド 転送 スレッド クライ アント クライ アント クライ アント クライ アント
    • 23. Copyright © GREE, Inc. All Rights Reserved. 転送性能を評価 • C++で書かれたサーバ • Flareのプロキシモード(マルチスレッド) • Haskellで書かれたサーバ • GHC7.8向けに修正したFrontend 1) レイテンシの計測 単一スレッドでリクエストを実行し、リクエスト毎の応答時間を計測 2) スループットの計測 複数スレッドでリクエストを実行し、処理したリクエストの数を計測 ゲートウェイサーバの性能評価 測定対象および項目 KVSサーバ (Flare) プロキシ(C++) プロキシ(Haskell) ベンチマーク プログラム 構成
    • 24. Copyright © GREE, Inc. All Rights Reserved. 構成 Intel(R) Xeon(R) CPU E5-1650 @ 3.20GHz(HTと省電力機能を無効化) 1台のPCで測定 測定結果 ほぼ互角 ゲートウェイサーバの性能評価 レイテンシ
    • 25. Copyright © GREE, Inc. All Rights Reserved. 構成 • Intel(R) Xeon(R) CPU E5-1650 @ 3.20GHz(HTと省電力機能を無効化) • 1台のPCで測定 測定結果 • C++で書いたサーバの80%程度 • 要チューニング? ゲートウェイサーバの性能評価 スループット(マルチスレッド) 0 5000 10000 15000 20000 25000 30000 35000 40000 C++/mt Haskell/mt set(qps) set(qps) 0 5000 10000 15000 20000 25000 30000 35000 40000 45000 C++/mt Haskell/mt get(qps) get(qps)
    • 26. Copyright © GREE, Inc. All Rights Reserved. 構成 • マルチプロセスで起動(現在使っている方式) • 独立したサーバ(16コア)でgetコマンドの性能を測定 • 64, 128, 256並列 測定結果 • CPUバウンドではないのであまり性能差はない ゲートウェイサーバの性能評価 [参考] スループット(マルチプロセス) 0 10000 20000 30000 40000 50000 60000 C++/mt Haskell/prefork 64 128 256
    • 27. Copyright © GREE, Inc. All Rights Reserved. • イベントログを threadscope で可視化 • GHCのランタイムがスレッド関連のイベントを出力してくれる プログラムの最適化 threadscope
    • 28. Copyright © GREE, Inc. All Rights Reserved. • マルチスレッドプログラミングは難しい。 • ロックと条件変数のせいかもしれません。 まとめ 本日の結論 • STMを使うと、簡単にマルチスレッドのサーバが作れます。 • 性能はそこそこ良いです。 • STMを使うなら、Haskellがお勧めです。 • プロダクションで使われています。 • Haskellを使って、サーバを書きましょう! • 生産性があがります。

    ×