SlideShare una empresa de Scribd logo
1 de 28
Copyright © GREE, Inc. All Rights Reserved.
サーバサイドの並行プログラミング
〜 かんたんマルチスレッドプログラミング 〜
2014/5/20
Infrastructure Department
Kiyoshi Ikehara
Copyright © GREE, Inc. All Rights Reserved.
Copyright © GREE, Inc. All Rights Reserved.
Webアプリケーション
• 3層アーキテクチャ + CDN
• フロントエンド(Nginx、Varnish など)
• アプリケーションサーバ(Apache+PHP など)
• データベース(MySQL など)
• アプリケーションサーバは状態をもたない
• HTTPのリクエストが終了したら終わり
• 共有される情報はすべてDBに格納されている
問題の単純化:状態を分離
• どうやって整合性を保つか
→ 同じデータを同時に扱わない
→ データベースが競合を解決してくれる
GREEにおける並行・並列
大規模Webサイトにおける並行処理
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.)
Copyright © GREE, Inc. All Rights Reserved.
マルチプレイヤー型オンラインゲーム
• クライアントは常にサーバに接続される
• 複数のクライアント間で状態を共有
• DB上の状態もあれば、メモリ上にのみ存在する状態もある
問題の単純化:プロセスに分割
• ワールドなどの単位でプロセスを分割
• 各クライアントの処理をちょっとずつ進める(イベント駆動)
パフォーマンスが求められる場合
• マルチプロセッサを活かすためにマルチスレッド化
• 並行プログラミング!
GREEにおける並行・並列
マルチプレイヤー型オンラインゲーム
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における並行・並列
自社開発ミドルウェア
Copyright © GREE, Inc. All Rights Reserved.
各種KPIの算出
• 大量の情報の中から、欲しい時に素早く情報を提供する
• 並列分散処理ミドルウェアを活用
• Hadoop, Hive, Presto …
GREEにおける並行・並列
大量データの処理
Copyright © GREE, Inc. All Rights Reserved.
サーバサイドで並行プログラミングをする理由
• 多数のクライアントから同時に要求される処理をこなす
• クライアント間で共有すべき状態が存在する
よくある実現方法
• 各クライアント毎にスレッドを実行する
• ロックと条件変数を使って整合性を担保する
• 1つのスレッドで各クライアントの処理を少しずつ進める
• イベントとコールバックを駆使する (ex. Redis, node.js)
並行プログラミングの方法
マルチスレッドとイベント駆動
Copyright © GREE, Inc. All Rights Reserved.
各クライアント毎にスレッドを実行する
• 利点:処理を順次書いていけばよい
• 欠点:スレッド間の競合を意識する必要がある
1つのスレッドで各クライアントの処理を少しずつ進める
• 利点:メモリアクセスの排他制御の必要がない
• 欠点:処理を細切れに書くため、見通しが悪い
マルチプロセッサを活用できない
いずれの方法をとるにせよ、プログラミングは難しい
参考: 「マルチコア時代の サーバプログラミング と Haskell」(山本和彦さん)
• http://www.iij.ad.jp/company/development/tech/techweek/pdf/tw2011_04_haskell.pdf
並行プログラミングの方法
利点と欠点
Copyright © GREE, Inc. All Rights Reserved.
過去数年間マルチスレッドサーバを運用してきましたが・・
• 再現させるのが難しい
• 「ある特定の行と行の間でスレッドが切り替わると起こるかもしれない」
• 「42億回クライアントが接続した後に起こるかもしれない」
• 「複数のサーバーが同時に故障すると起こるかもしれない」
• 修正が正しいかの検証が難しい
• 複数スレッドの進行状況をすべて考慮する必要がある。
考慮したところで、人間の考えることは信用ならない。
• 不安なら全状態をツールでチェックすればよいが、状態のモデル化が大変。
モデルは人間が作るのでまちがってる可能性もある。
• 解決方法=枯れるのを待つ
• もぐらたたきの結果、安定したソフトウェアができあがる
マルチスレッドプログラミングは難しい
サーバ運用の観点からみた難しさ
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.)
Copyright © GREE, Inc. All Rights Reserved.
“Why Threads Are A Bad Idea (for most purposes)”
by John Ousterhout (1995)
マルチスレッドプログラミングは難しい
20年前から言われ続けている・・
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
Copyright © GREE, Inc. All Rights Reserved.
Webアプリケーションはいかにして複雑さを回避していたか?
• 状態の保持を専用の機構(=データベース)に委譲
• データベースの提供するトランザクションを利用
マルチスレッドプログラミングは難しい
結局なにがいけないのか(cont.)
( ゚д゚)ハッ!
|
\ __ /
_ (m) _ピコーン
|ミ|
/ .`´ \
∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
(・∀・∩< DBつかえばいいんじゃね
(つ 丿 \_________
⊂_ ノ
(_)
Copyright © GREE, Inc. All Rights Reserved.
我々はソフトウェアトランザクショナルメモリ(STM)を使っています
STM
• アトミックブロック内の一貫性保持
• プロック内では、あたかも自分のスレッドだけが動いているようにふるまう
(SERIALIZABLEと同じ)
• ロールバック
• 処理の途中で変数への書き込みをなかったことにできる
かんたんマルチスレッドプログラミング
並行プログラミングの容易化
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
Copyright © GREE, Inc. All Rights Reserved.
“Transactional Variable(TVar)”で状態を表現
• Intを保持したいなら TVar Int という型を使う
• アトミックブロック内でのみ操作できる
動作
• とりあえず実行してみる
• 自分がTVarを参照している最中に他の人がそれを
書き換えたら、処理をやり直す
特徴
• デッドロックの問題は回避できるが、
平等性(fairness)の問題がある
• 処理を合成でき、合成してもSTMの性質を保つ
• 現在の実装ではロックを使用しているっぽい
HaskellのSTM
本発表から聴講された方向け
10章あたりにかいてあります
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
Copyright © GREE, Inc. All Rights Reserved.
• STMは合成可能
• STMの中では、任意のSTM関数
を呼び出して良い
• TVarをプリミティブとして、
より複雑なデータ構造を構築
• Ex. TQueue
• 例外でロールバックされる
• 途中の状態は他から見えない
• 「スレッドが例外で終了して状態
がおかしくなる」問題がない
• ex. キューからアイテムを取り出
して別のキューにいれる
HaskellのSTM
STMはなにがすごいか
Control.Concurrent.STM.TQueueの実装
Copyright © GREE, Inc. All Rights Reserved.
MVar
• 1つものをいれられる箱
• putMVar関数 - もうすでに入ってたら、空くまで実行が停止する
• takeMVar関数 – まだ入ってなければ、入るまで実行が停止する
• 特徴
• スレッド間の制御に使える
• 誤って使うとデッドロックする可能性がある
IORef
• アトミックに書き換え可能
• atomicModifyIORef関数
• 扱う変数が1個ならこちらを使ったほうが速い
HaskellのSTM
他にもあるHaskellの状態保持機構
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
Copyright © GREE, Inc. All Rights Reserved.
ゲートウェイサーバ (Frontend)ゲートウェイサーバ (Frontend)ゲートウェイサーバ (Frontend)
• リクエスト処理スレッドと転送処理スレッドに分割
• それぞれのスレッドがキュー(TQueue)を介して通信
• スレッド+プロセス多重
• 性能と安全性を考慮してプロセス多重も併用
STMの使用例
ゲートウェイサーバの実装
リクエスト
スレッド
転送処理
スレッド
転送処理
スレッド
転送処理
スレッド
リクエスト
スレッド
リクエスト
スレッド
リクエスト
スレッド リクエスト
受付キュー
応答受取
キュー
Response
Request
Flare
サーバ
Flare
サーバ
Flare
サーバ
転送処理
スレッド
転送
スレッド
転送処理
スレッド
転送
スレッド
転送処理
スレッド
転送
スレッド
クライ
アント
クライ
アント
クライ
アント
クライ
アント
Copyright © GREE, Inc. All Rights Reserved.
転送性能を評価
• C++で書かれたサーバ
• Flareのプロキシモード(マルチスレッド)
• Haskellで書かれたサーバ
• GHC7.8向けに修正したFrontend
1) レイテンシの計測
単一スレッドでリクエストを実行し、リクエスト毎の応答時間を計測
2) スループットの計測
複数スレッドでリクエストを実行し、処理したリクエストの数を計測
ゲートウェイサーバの性能評価
測定対象および項目
KVSサーバ
(Flare)
プロキシ(C++)
プロキシ(Haskell)
ベンチマーク
プログラム
構成
Copyright © GREE, Inc. All Rights Reserved.
構成
Intel(R) Xeon(R) CPU E5-1650 @ 3.20GHz(HTと省電力機能を無効化)
1台のPCで測定
測定結果
ほぼ互角
ゲートウェイサーバの性能評価
レイテンシ
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)
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
Copyright © GREE, Inc. All Rights Reserved.
• イベントログを threadscope で可視化
• GHCのランタイムがスレッド関連のイベントを出力してくれる
プログラムの最適化
threadscope
Copyright © GREE, Inc. All Rights Reserved.
• マルチスレッドプログラミングは難しい。
• ロックと条件変数のせいかもしれません。
まとめ
本日の結論
• STMを使うと、簡単にマルチスレッドのサーバが作れます。
• 性能はそこそこ良いです。
• STMを使うなら、Haskellがお勧めです。
• プロダクションで使われています。
• Haskellを使って、サーバを書きましょう!
• 生産性があがります。

Más contenido relacionado

La actualidad más candente

プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
Takuya Akiba
 

La actualidad más candente (20)

Hiveを高速化するLLAP
Hiveを高速化するLLAPHiveを高速化するLLAP
Hiveを高速化するLLAP
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
 
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
 
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
 
データサイエンティスト向け性能問題対応の基礎
データサイエンティスト向け性能問題対応の基礎データサイエンティスト向け性能問題対応の基礎
データサイエンティスト向け性能問題対応の基礎
 
Java8でRDBMS作ったよ
Java8でRDBMS作ったよJava8でRDBMS作ったよ
Java8でRDBMS作ったよ
 
Java仮想マシンの実装技術
Java仮想マシンの実装技術Java仮想マシンの実装技術
Java仮想マシンの実装技術
 
分散システムについて語らせてくれ
分散システムについて語らせてくれ分散システムについて語らせてくれ
分散システムについて語らせてくれ
 
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうPython 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそう
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」
 
ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計
 
全力解説!Transformer
全力解説!Transformer全力解説!Transformer
全力解説!Transformer
 
大規模データ処理の定番OSS Hadoop / Spark 最新動向 - 2021秋 -(db tech showcase 2021 / ONLINE 発...
大規模データ処理の定番OSS Hadoop / Spark 最新動向 - 2021秋 -(db tech showcase 2021 / ONLINE 発...大規模データ処理の定番OSS Hadoop / Spark 最新動向 - 2021秋 -(db tech showcase 2021 / ONLINE 発...
大規模データ処理の定番OSS Hadoop / Spark 最新動向 - 2021秋 -(db tech showcase 2021 / ONLINE 発...
 
Scapyで作る・解析するパケット
Scapyで作る・解析するパケットScapyで作る・解析するパケット
Scapyで作る・解析するパケット
 
大量のデータ処理や分析に使えるOSS Apache Spark入門(Open Source Conference 2021 Online/Kyoto 発表資料)
大量のデータ処理や分析に使えるOSS Apache Spark入門(Open Source Conference 2021 Online/Kyoto 発表資料)大量のデータ処理や分析に使えるOSS Apache Spark入門(Open Source Conference 2021 Online/Kyoto 発表資料)
大量のデータ処理や分析に使えるOSS Apache Spark入門(Open Source Conference 2021 Online/Kyoto 発表資料)
 
pg_bigmで全文検索するときに気を付けたい5つのポイント(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
pg_bigmで全文検索するときに気を付けたい5つのポイント(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)pg_bigmで全文検索するときに気を付けたい5つのポイント(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
pg_bigmで全文検索するときに気を付けたい5つのポイント(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
グラフネットワーク〜フロー&カット〜
グラフネットワーク〜フロー&カット〜グラフネットワーク〜フロー&カット〜
グラフネットワーク〜フロー&カット〜
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
 

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

Google Compute EngineとPipe API
Google Compute EngineとPipe APIGoogle Compute EngineとPipe API
Google Compute EngineとPipe API
maruyama097
 
Google Compute EngineとGAE Pipeline API
Google Compute EngineとGAE Pipeline APIGoogle Compute EngineとGAE Pipeline API
Google Compute EngineとGAE Pipeline API
maruyama097
 
Firefoxの開発プロセス
Firefoxの開発プロセスFirefoxの開発プロセス
Firefoxの開発プロセス
Makoto Kato
 

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

Zynga
ZyngaZynga
Zynga
 
Aws privte20110406 arai
Aws privte20110406 araiAws privte20110406 arai
Aws privte20110406 arai
 
スマートフォン×Cassandraによるハイパフォーマンス基盤の構築事例
スマートフォン×Cassandraによるハイパフォーマンス基盤の構築事例スマートフォン×Cassandraによるハイパフォーマンス基盤の構築事例
スマートフォン×Cassandraによるハイパフォーマンス基盤の構築事例
 
PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門
 
Gmo media.inc 第9回西日本ossの普及を考える会
Gmo media.inc 第9回西日本ossの普及を考える会Gmo media.inc 第9回西日本ossの普及を考える会
Gmo media.inc 第9回西日本ossの普及を考える会
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
とあるメーカーのRedmine活用事例
とあるメーカーのRedmine活用事例とあるメーカーのRedmine活用事例
とあるメーカーのRedmine活用事例
 
既存システムへの新技術活用法 ~fluntd/MongoDB~
既存システムへの新技術活用法 ~fluntd/MongoDB~既存システムへの新技術活用法 ~fluntd/MongoDB~
既存システムへの新技術活用法 ~fluntd/MongoDB~
 
地方企業がソーシャルゲーム開発を成功させるための10のポイント
地方企業がソーシャルゲーム開発を成功させるための10のポイント地方企業がソーシャルゲーム開発を成功させるための10のポイント
地方企業がソーシャルゲーム開発を成功させるための10のポイント
 
AWS Black Belt Techシリーズ Amazon ElastiCache
AWS Black Belt Techシリーズ Amazon ElastiCacheAWS Black Belt Techシリーズ Amazon ElastiCache
AWS Black Belt Techシリーズ Amazon ElastiCache
 
クラウドデザイン パターンに見る クラウドファーストな アプリケーション設計 Data Management編
クラウドデザイン パターンに見るクラウドファーストなアプリケーション設計 Data Management編クラウドデザイン パターンに見るクラウドファーストなアプリケーション設計 Data Management編
クラウドデザイン パターンに見る クラウドファーストな アプリケーション設計 Data Management編
 
Google Compute EngineとPipe API
Google Compute EngineとPipe APIGoogle Compute EngineとPipe API
Google Compute EngineとPipe API
 
Google Compute EngineとGAE Pipeline API
Google Compute EngineとGAE Pipeline APIGoogle Compute EngineとGAE Pipeline API
Google Compute EngineとGAE Pipeline API
 
Cld018 コンテナ go_~あなた
Cld018 コンテナ go_~あなたCld018 コンテナ go_~あなた
Cld018 コンテナ go_~あなた
 
Cld018 コンテナ go_~あなた
Cld018 コンテナ go_~あなたCld018 コンテナ go_~あなた
Cld018 コンテナ go_~あなた
 
Firefoxの開発プロセス
Firefoxの開発プロセスFirefoxの開発プロセス
Firefoxの開発プロセス
 
Okuyama説明資料 20120119 ss
Okuyama説明資料 20120119 ssOkuyama説明資料 20120119 ss
Okuyama説明資料 20120119 ss
 
[SAPPORO CEDEC] サービスの効果を高めるグリー内製ツールの技術と紹介
[SAPPORO CEDEC] サービスの効果を高めるグリー内製ツールの技術と紹介[SAPPORO CEDEC] サービスの効果を高めるグリー内製ツールの技術と紹介
[SAPPORO CEDEC] サービスの効果を高めるグリー内製ツールの技術と紹介
 
地に足がついたクラウドのお話
地に足がついたクラウドのお話地に足がついたクラウドのお話
地に足がついたクラウドのお話
 

Más de gree_tech

Más de gree_tech (20)

アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜
アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜
アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜
 
GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介
GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介
GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介
 
REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表
REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表
REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表
 
アプリ起動時間高速化 ~推測するな、計測せよ~
アプリ起動時間高速化 ~推測するな、計測せよ~アプリ起動時間高速化 ~推測するな、計測せよ~
アプリ起動時間高速化 ~推測するな、計測せよ~
 
長寿なゲーム事業におけるアプリビルドの効率化
長寿なゲーム事業におけるアプリビルドの効率化長寿なゲーム事業におけるアプリビルドの効率化
長寿なゲーム事業におけるアプリビルドの効率化
 
Cloud Spanner をより便利にする運用支援ツールの紹介
Cloud Spanner をより便利にする運用支援ツールの紹介Cloud Spanner をより便利にする運用支援ツールの紹介
Cloud Spanner をより便利にする運用支援ツールの紹介
 
WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介
WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介
WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介
 
SINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現について
SINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現についてSINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現について
SINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現について
 
海外展開と負荷試験
海外展開と負荷試験海外展開と負荷試験
海外展開と負荷試験
 
翻訳QAでのテスト自動化の取り組み
翻訳QAでのテスト自動化の取り組み翻訳QAでのテスト自動化の取り組み
翻訳QAでのテスト自動化の取り組み
 
組み込み開発のテストとゲーム開発のテストの違い
組み込み開発のテストとゲーム開発のテストの違い組み込み開発のテストとゲーム開発のテストの違い
組み込み開発のテストとゲーム開発のテストの違い
 
サーバーフレームワークに潜んでる脆弱性検知ツール紹介
サーバーフレームワークに潜んでる脆弱性検知ツール紹介サーバーフレームワークに潜んでる脆弱性検知ツール紹介
サーバーフレームワークに潜んでる脆弱性検知ツール紹介
 
データエンジニアとアナリストチーム兼務になった件について
データエンジニアとアナリストチーム兼務になった件についてデータエンジニアとアナリストチーム兼務になった件について
データエンジニアとアナリストチーム兼務になった件について
 
シェアドサービスとしてのデータテクノロジー
シェアドサービスとしてのデータテクノロジーシェアドサービスとしてのデータテクノロジー
シェアドサービスとしてのデータテクノロジー
 
「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-
「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-
「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-
 
「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話
「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話
「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話
 
比較サイトの検索改善(SPA から SSR に変換)
比較サイトの検索改善(SPA から SSR に変換)比較サイトの検索改善(SPA から SSR に変換)
比較サイトの検索改善(SPA から SSR に変換)
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
 
「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜
「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜
「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜
 
法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)
法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)
法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)
 

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

  • 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を使って、サーバを書きましょう! • 生産性があがります。

Notas del editor

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