勉強日記

チラ裏

PoEAA ch5 Concurrency 1/4

martinfowler.com


Concurrency

  • 並列性はソフトウェア開発において最も骨の折れる側面のひとつ
    • 複数のスレッドで同一のデータを操作すると直面する
  • 困難性
    • 起こりうるシナリオの列挙が困難
      • すぐ漏れる
    • テストしづらい
  • トランザクションを用いることで、骨の折れる部分はおおむね回避できる
  • が、並列性の問題は完全には無視できない
  • アプリケーションサーバでも並列性の困難は顕在化する
    • マルチスレッド
    • 前述の問題よりは楽
  • 一般的な並列性の概念についての理解が必要
    • CVSを例に挙げる
      • CVSに慣れていないなら、悪いことは言わないから並列制御に手を出さないほうがいい

Concurrency Problems

  • Lost Updates
    1. Martinさんがコードをチェックアウト、編集
    2. Davidさんがコードをチェックアウト、編集
    3. Davidさんがコードをチェックイン
    4. Martinさんがコードをチェックイン
      • mergeしてない!
    5. Davidさんの編集が失われる
  • Inconsistent Read
    1. パッケージA,Bがある
    2. Aにはクラスが7個、Bにはクラスが5個あった
    3. MartinさんはパッケージAをチェックアウトし、クラスが7個あることを確認した
    4. パッケージBをチェックアウトしようとしたら電話がかかってきた
    5. DavidさんはパッケージAにクラスを2つパッケージBにクラスを3つ追加しチェックインした
    6. Martinさんは電話を終え、パッケージBをチェックアウトし、クラスが8個あることを確認した
    7. 全部で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操作が絡む、もうひとつの実行コンテキスト...トランザクション

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
    • 問題が顕在化する