Concurrency
-
並列性はソフトウェア開発において最も骨の折れる側面のひとつ
- 複数のスレッドで同一のデータを操作すると直面する
-
困難性
-
起こりうるシナリオの列挙が困難
- すぐ漏れる
- テストしづらい
-
-
トランザクションを用いることで、骨の折れる部分はおおむね回避できる
- 極論、データ操作を全部トランザクションの中で行えば問題がひどくなることはない
-
が、並列性の問題は完全には無視できない
-
多くの(ビジネス)トランザクションは単一のDBトランザクションでは完結しない
- offline concurrencyのことを言っている
- 複数のDBトランザクションの間における並列性制御
-
-
アプリケーションサーバでも並列性の困難は顕在化する
- マルチスレッド
- 前述の問題よりは楽
-
一般的な並列性の概念についての理解が必要
-
CVSを例に挙げる
- CVSに慣れていないなら、悪いことは言わないから並列制御に手を出さないほうがいい
-
Concurrency Problems
-
Lost Updates
- Martinさんがコードをチェックアウト、編集
- Davidさんがコードをチェックアウト、編集
- Davidさんがコードをチェックイン
-
Martinさんがコードをチェックイン
- mergeしてない!
- Davidさんの編集が失われる
-
Inconsistent Read
- パッケージA,Bがある
- Aにはクラスが7個、Bにはクラスが5個あった
- MartinさんはパッケージAをチェックアウトし、クラスが7個あることを確認した
- パッケージBをチェックアウトしようとしたら電話がかかってきた
- DavidさんはパッケージAにクラスを2つ、パッケージBにクラスを3つ追加しチェックインした
- Martinさんは電話を終え、パッケージBをチェックアウトし、クラスが8個あることを確認した
-
「全部で7+8=15クラスある!」<- まちがい
-
David氏チェックイン前後のデータが混ざっている
- それぞれは正しいが、混ぜると正しくない
-
package A | package B | 合計 | |
---|---|---|---|
Davidチェックイン前 | 7 | 5 | 12 |
Davidチェックイン後 | 9 | 8 | 17 |
- いずれもcorrectness(or safety)が損なわれている例
-
correctnessだけが問題ならばそんなに深刻ではない
- 同時に一人だけがデータを改変できるようにすれば回避できる
-
liveness
- どれだけ並列できるか
- correctnessとlivenessとはトレードオフ
-
並列処理に伴う問題の解決策自体が困難をはらむ
- トランザクションとかロックとか
-
correctness/safetyが損なわれても問題ないなら、解決策を一切講じないという選択肢もある
- 許容されることは稀だが…
-
【補】部分的に捨てるのはよくある
- トランザクション分離レベルを下げてパフォーマンスを稼ぐなど
- ファントムリードを許容してSERIALIZABLEからREPEATABLE READに落とす、とか
Execution Contexts
-
主要な実行コンテキスト2つ
-
リクエスト
- サーバ外からサーバへの単一call
- レスポンスを返す
-
処理はほとんどサーバサイド
- クライアントは待ってるだけ
- キャンセルリクエストを送れる場合もあるが稀
-
セッション
- C-S間の長く続く相互作用
- 単一リクエストだけかもしれない
-
が、論理的にまとまった一連のリクエスト群からなること多し
- ログインして
- なんかして
- ログアウトする
-
-
リクエストとセッションの視点
- クライアントからサーバへのリクエスト
-
サーバから外部の別システム(のサーバ)へのリクエスト
- 複数のDBMSにつなぐ場合とか
-
プロセスとスレッド
-
プロセス
- 重量級
-
メモリ独立してる
- 【補】critical sectionとかでやりとりする
-
スレッド
- かるい
-
1つのプロセスの中で複数スレッド並列
- リソース面で有利
-
メモリ共有してる
- 並列性の問題おきる
-
メモリ共有しないヤツがいる環境もある
- isolated threads
-
-
実行コンテキストに関する困難…思い通りの順番に実行されないこと
- 理論的には各セッション独立している
-
現実的に近いやつ: 昔のPerlのWebシステム
- リクエストのたびに新しくプロセス立ち上げる
-
執筆時点では単一プロセス
- プロセスは一度に1つのリクエストしか処理しない
- 並列性の問題の多くを回避できる
-
DB操作が絡む、もうひとつの実行コンテキスト…トランザクション
-
複数リクエストを単一リクエストであるかのように扱う
- 【補】原子性: 全成功or全失敗
-
アプリケーションからDBへのリクエスト
- 【補】システムトランザクション
-
ユーザからアプリケーションへのリクエスト
- 【補】ビジネストランザクション
-
Isolation and Immutability
- 並列性の困難性はわかった
-
どう回避するの
- 同一のデータを変更するのが原因
-
解決策
- isolation
- immutability
-
isolation
- 同一のデータを変更するのが原因
- データ分ける
- 各ピースが1エージェントからのみアクセスされるよう
-
実装例
- メモリをプロセスに排他的に割り当てる
-
ファイルのロック
- 【補】悲観ロック
- isolatedな部分では並列性のことを意識しなくてよいのが強い
- なるべくisolatedな部分でプログラムを動かす
-
immutability
- 同一のデータを変更するのが原因
- 不変、もしくはほぼいつも不変ならば、並列性に関する心配事を緩和できる
-
データ読み出し専のアプリケーションを切り出すとか
- コピーされたデータを読むだけなら並列制御を完全回避できる
- 【補】CQRSアーキテクチャとかあるわね
Optimistic and Pessimistic Concurrency Control
-
並列制御
-
楽観ロック
-
ロックしてねえじゃねえかってやつ
- 言葉として便利だし、広まってしまったからしゃーない
-
-
悲観ロック
-
ロックには2種類
-
共有ロック
- R
- 他の誰にも専有ロックさせない
-
専有ロック
- R/W
- 他の誰にも共有/専有ロックさせない
-
-
-
Optimistic | Pessimistic | |
---|---|---|
liveness | o | x |
conflictを… | 検出 | 予防 |
-
コンフリクトがあまり起きず、起きたとしても重大にならないなら楽観ロックがよい
- liveness稼げる
- 実装らく
-
コンフリクトが起きたが最後、マージが困難なら悲観ロック
- ビジネスロジックのデータとか
-
いずれの解決策を選んでも、問題から真に開放されるわけではない
- 並列性の問題そのものと同じくらいの新たな問題
えいご
-
rear its ugly head
- 問題が顕在化する