勉強日記

チラ裏

PoEAA ch16 Coarse-Grained Lock

martinfowler.com


Coarse-Grained Lock

Locks a set of related objects with a single lock.

  • オブジェクトはグループとして編集される
    • 例: 顧客と住所
  • グループを構成する1要素を編集する際には、グループ全体をロックするのが理にかなっている
  • 各要素別々にロックを管理するのは多くの困難をともなう
    • 全要素検索してロックしなければならない
      • 「顧客と住所」くらいなら問題ないが、オブジェクトグラフが大きくなってくると困難
    • Optimistic Offline Lockの場合
      • ロックのために全要素読み込まないといけない
        • レコードにバージョンが紐付いているため
      • 読まなくてもよいレコードも読んでしまいい、パフォーマンスに悪影響
    • Pessimistic Offline Lockの場合
      • 管理が大変
      • ロックテーブルにアクセス集中し競合が発生する
  • Coarse-Grained Lockでは、単一のロックで多数のオブジェクトをロックする
    • ロック操作の簡略化
    • ロックのために全レコード読み込まなくて良い

How It Works

  • Optimistic Offline Lockの場合
    • shared lock
      • グループ内の全オブジェクトは同一のバージョンオブジェクトを参照するようにする
        • 同じ値ではなく、同一のバージョンを参照
      • 共通のバージョンをインクリメントすることで、グループ全体がロックされる
  • Pessimistic Offline Lockの場合
    • なにがしかのlockable tokenをグループ内の全オブジェクトで共有
    • Optimistic Offline Lockパターンの「共通のバージョン」はまさにlockable tokenとして利用できる
  • Evansの「Aggregate」
    • root
      • オブジェクトグラフのroot
    • boundary
      • Aggregateに含まれるオブジェクトと外との境界
      • boundary内部のオブジェクトには、root経由でのみアクセスできる
    • rootをロックすることで、Aggregateを構成する全オブジェクトをロックしたことにする
    • Aggregateを構成する各オブジェクトからrootへのアクセスはどうする
      • rootへの直接参照を保持する
      • 親をrootまでたどる
        • オブジェクトグラフが巨大な場合、パフォーマンスに悪影響
          • Lazy Loadの併用
            • 親オブジェクトを完全にロードしなくてもよいよう
            • 無限ループ回避
          • Lazy Loadの問題
            • Inconsistent Readのおそれ
    • 実装の選定
      • root lock
        • rootのみロックする
        • メリデメ
          • メリ
            • root以外、バージョンテーブルとのjoin不要
          • デメ
            • rootまで親オブジェクトをたどる際に読み込み負荷がある
              • Lazy Loadで回避できるが、Inconsistent Readがおきる
      • shared lock (Optimistic Offline Lock)
        • Aggregateを構成する任意のオブジェクトをロックすると、root含め全オブジェクトがロックされる
        • メリデメ
          • メリ
            • rootまで親をたどらなくてよい
          • デメ
            • ほぼすべてのSELECT文でバージョンテーブルとのjoinが必要
      • Pessimistic Offline Lock
        • ヘンな組み合わせ

When to Use It

  • 機能要件
    • ビジネス要件
      • 例: 「貸出」と「機材」
        • あるユーザが貸出を編集しているとき、別のユーザが同時に機材を編集できてはいけない
  • 非機能要件
    • パフォーマンス
      • ロックの獲得・解放が低コストになる
  • オブジェクト間に不自然な関連を追加してしまうことに留意する
    • 双方向参照
    • rootへの直接参照