--- title: Oracle Coherenceを使うときに特にアーキテクトの人が気をつけるべきこと tags: [] categories: ["Middleware", "DistributedSystem", "InMemoryDataGrid", "Coherence"] date: 2013-07-22T15:32:14Z updated: 2013-08-21T23:44:22Z --- 本記事の内容を発表しました。[発表資料][1]
---- Oracle Coherenceに関するメモ。整理するために書いた。Coherenceに限らず同様な分散データグリッド製品(InfinispanとかeXtreme ScaleとかGemfireとか)にも言えると思う。 アーキテクトとして開発の方針を決め、統制を効かせ、安定して開発を進めるためのノウハウメモ。 "安定"と書くといろいろな意味にとられかねないので、ここでは余計なトラブルを起こさずスムーズに進められることくらいの意味にとどめておく。 Coherenceに関して検討すべきことはアプリ面、インフラ面で両方あるがアプリ面について説明する。 途中で書き疲れたので散文失礼。 ## 用途の決定 Coherence設計ポイントは用途によって大きく異なる * DBのフロントのキャシュ用途なのか * パフォーマンスを上げるためにメモリサーバーだけの運用するのか * CEP的なやつなのか ここでは2つ目の用途について説明する。 1つめはJPAなどO/RマッパーのL2キャッシュとして使えばいいのでは。 Coherenceを使う目的をはっきり決めて方針を決めることが重要。ここが曖昧になると、安直に「とりあえずCoherenceにつっこめばいいんじゃね?」っていう流れになってしまう。これは食い止めねばならない。 ## 前提知識 ### Cache方式 * Distributed Cache * クラスタ上のどこか2つのノードにキャッシュを置く。 * 書き込みは2ホップ、読み込みは1ホップ。 * 十分速く、普通はこちらを使う。 * Replicated Cache * 全てのクラスタ上の全ノードにキャッシュを置く。 * 書き込みはNホップかかるので遅いが、読み込みは0ホップで超高速(同一JVM上のlocalキャッシュと同等)。 * データサイズはスケールしないので、頻繁に読み込む必要がある少量のデータ用途。後述の**read throughが使えない**点に注意。 * Near Cache * Distributed Cache + Local Cache。 * 書き込みはLocal Cache→Distributed Cacheに行う。読み込み時にLocal CacheになかったらDistributed Cacheを探す。 * 読み込み速度は2回目以降は超高速 * キャッシュ削除の伝播が非同期であることに注意。 ### DB連携方式 * read through * キャッシュ上になかったらDBから取り出しキャッシュに乗せる * write through * キャッシュに書き込んだ後、同期してDBに書き込む * write behind * キャッシュに書き込んだ後、**非同期で**DBに書き込む CacheStoreを登録することで実現する。 ## 設計編 ### キャッシュデータの種類 * メモリ上にのみ存在してDBにはないもの * メモリにもDBにも存在し同期が必要なもの 同期が必要な方が要注意 ### メモリとDBの同期 #### DB->メモリ 更新時にDBトランザクションとの整合性が重要 DBの一部がキャッシュ上にある場合 (例:Accountテーブルのうちのユーザー名とパスワードのみキャッシュ上にある場合) 1. DB更新(キャッシュ上のフィールド以外)+write through 2. DB更新(全フィールド)+キャッシュ書き込み 3. DB更新(全フィールド)+キャッシュ削除+read through 1.は実装が複雑なうえにDB更新トランザクションとwrite throughトランザクションは別なので片方DB更新が失敗したら整合性がとれない。 2.は実装は簡単になるが1.同様トランザクションが別。 3.はDBトランザクション中にキャッシュ削除。DB失敗すればキャッシュ更新しないし、キャッシュ削除に失敗したらDBロールバック。削除後キャッシュアクセスすれば最新のデータをDBから取ってこれる。 3が一番安全。 念のためトランザクションの外でもキャッシュ削除&キャッシュアクセスでリフレッシュする。 → 更新方式を3に統一。 この前提を置いたとき、更新が必要なデータにはReplicated Cacheは使わない。 NearとDistibutedを以下のように使い分ける。 * データ量が少なく、頻繁にアクセスするもの→Near Cache * それ以外→Distributed Cache TopLinkを使っていたらまた違ったのかな。 #### メモリ->DB write behindを利用して 更新が遅れるフィールドについてビジネス的に問題ないかお客さんに確認 またwrite behindでDBに書き込む前にマスターノードとレプリカノードが落ちたらデータ欠損。欠損しても良いデータかどうか。 ### データの検索 基本はKey-Value形式。キーアクセスでしか速くない。じゃあキー以外の項目で検索したいときどうするか?以下の2通りのやり方がある。 #### 転置インデックス * メリット ネットワークホップ数が1回増えるだけなので性能は良い。 * デメリット 転置インデックス作成、更新、削除の分、実装が複雑になる。 #### Filter 検索条件(where句みたいなもの)を与えて、各ノードに送り込みパラレル処理で検索する。自動indexing対応。 * メリット 実装が容易。 * デメリット パラレル処理=全てのキャッシュサーバーに負荷をかける。高トランザクション下では不向き。 ## コーディング編 ### 安全なキャッシュアクセス **Mapとして使ってはならない**。かならずTypeSafeにすること。仕様変更が入ると死ぬ。まじで死ぬ。 `AccountCacheRepository extends CacheRepository
[1]: https://www.slideshare.net/makingx/coherence-25447429