Coherenceを利用する
ときに気をつけること
2013/08/21
槙 俊明 twitter:@making
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
今日の話のスコープ
• Coherenceのアプリケーション開発に関するノウ
ハウについての説明
• インフラの話ではない(ネットワーク構成などは
話せない)
• Coherenceに限らず、他の分散インメモリデータ
グリッド製品を利用する場合にも適用できる
• Inifinispan(RedHat)
• eXtremeScale(IBM)
• Gemfire(Pivotal ← VMware)
• Coherence 3.7.1の話であり、Coherence 12c以降
改善されている可能性あり
用途の決定
• Coherence設計ポイントは用途によって大きく異なる
• DBのフロントのキャシュ用途なのか
• パフォーマンスを上げるためにメモリサーバーだけの運
用するのか
• CEP的なやつなのか
用途の決定
• Coherence設計ポイントは用途によって大きく異なる
• DBのフロントのキャシュ用途なのか
• パフォーマンスを上げるためにメモリサーバーだけの運
用するのか
• CEP的なやつなのか
• ここでは2つ目の用途について説明する。
• 1つ目はJPAなどO/RマッパーのL2キャッシュを使用すれ
ば良い
用途の決定
• Coherenceを使う目的をはっきり決め
て方針を決めることが重要。
• ここが曖昧になると、なんでもかんで
も安直に「とりあえずCoherenceにい
れよう!」っていう流れになってしま
う。これは食い止めねばならない。
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
前提知識のおさらい
• Cache方式
• DB連携方式
前提知識のおさらい
• Cache方式
• DB連携方式
Cache方式
• Partitioned Cache
• Replicated Cache
• Near Cache
Cache方式
• Partitioned Cache
• Replicated Cache
• Near Cache
Partitioned Cache
• クラスタ上のどこか2つのノード
(primary, backup)にキャッシュを置く。
• 書き込みは2ホップ、読み込みは1ホッ
プ。
• 十分速く、普通はこちらを使う。
Partitioned Cacheの読み込み
キャッシュノード1
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
P
B
A
B
CD
A
B
C D
読み取りは1hopの
ネットワークアクセス
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheの書き込み
キャッシュノード1
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
P
B
P…プライマリデータ、B…バックアップデータ
A
B
CD
A
B
C D
書き込みは2hopの
ネットワークアクセス
Partitioned Cacheのリカバリ
キャッシュノード1
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
P
B
A
B
CD
A
B
C D
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのリカバリ
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
B
C
A
B
D
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのリカバリ
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
B
C
A
B
D
A D
バックアップが
プライマリに昇格
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのリカバリ
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
B
CBA D
バックアップが
プライマリに昇格
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのリカバリ
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
B
C
D
B
A
A D
C
プライマリから
バックアップを作成
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのリカバリ
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
B
C
D
B
A
A D
C
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのノード追加
キャッシュノード1
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
P
B
A
B
CD
A
B
C D
キャッシュノード4
P
B
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのノード追加
キャッシュノード1
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
P
B
A
B
CD
A
B
C D
キャッシュノード4
P
B
D
B
再パーティショニング
P…プライマリデータ、B…バックアップデータ
Partitioned Cacheのノード追加
キャッシュノード1
アプリケーション アプリケーション
キャッシュノード2 キャッシュノード3
P
B
P
B
P
B
A C
A
B
C D
キャッシュノード4
P
B
D
B
キャッシュ容量を
追加できる
P…プライマリデータ、B…バックアップデータ
Cache方式
• Partitioned Cache
• Replicated Cache
• Near Cache
Replicated Cache
• 全てのクラスタ上の全ノードにキャッシュを置く。
• 書き込みはN(=ノード数)-1ホップかかるので遅いが、
読み込みは0ホップで超高速(同一JVM上のlocalキャ
ッシュと同等)。
• データサイズはスケールしないので、頻繁に読み込
む必要がある少量のデータ用途。
• 後述のread throughが使えない点に注意。
Replicated Cacheの読み込み
キャッシュノード1
アプリケーション
A B
C D
キャッシュノード2
アプリケーション
A B
C D
キャッシュノード3
アプリケーション
A B
C D
読み取りは同一プロセス内で完結
Replicated Cacheの書き込み
キャッシュノード1
アプリケーション
A B
C D
キャッシュノード2
アプリケーション
A B
C D
キャッシュノード3
アプリケーション
A B
C D
書き込みは他のノードへ複製
Cache方式
• Partitioned Cache
• Replicated Cache
• Near Cache
Near Cache
• Partitioned Cache + Local Cache。
• 書き込みはLocal Cache→Partitioned Cacheの順
に行う。読み込み時にLocal Cacheになかったら
Partitioned Cacheを探す。
• 読み込み速度は2回目以降は超高速
• キャッシュ削除の伝播が非同期であることに注
意。
AP Server
Near Cache
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
AP Server
Near Cacheからデータ取得
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
Get A
AP Server
アプリケーション
A
Partitioned Cache
存在する
LocalC
ache
Get A A
存在しない
Near Cacheからデータ取得
AP Server
アプリケーション
A
Partitioned Cache
LocalC
ache
Get A
裏のPartitionedキャ
ッシュからコピー
A
Near Cacheからデータ取得
AP Server
アプリケーション
A
Partitioned Cache
LocalC
ache
Get A A
Near Cacheからデータ取得
2回目以降はLocalキャッシ
ュから取得するため超高速
AP Server
Near Cacheへデータ書込
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
Write A
AP Server
Near Cacheへデータ書込
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
Write A A
まずLocalキャッ
シュに書込
AP Server
Near Cacheへデータ書込
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
Write A A A
Localから分散へ
コピー
A
AP Server
Near Cacheのデータ更新伝播
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
Write A A A
A
AP Server
アプリケーション
LocalC
ache
A
更新or削除
AP Server
Near Cacheのデータ更新伝播
アプリケーション
Partitioned Cache
LocalC
ache
Near Cache
Write A A A
A
AP Server
アプリケーション
LocalC
ache
A
別ノードの同じデー
タを非同期で削除
Cache方式の比較
方式 書き込み 読み込み データサイズ 耐障害性 一貫性
Partitio
ned
1+n hop
n=バック
アップ数
通常n=1
1 hop ノードの追加
によって容量
を拡張可能
バックアップから
プライマリへ昇格
し、新たなバック
アップを別ノード
に作成
一貫
Replicat
ed
m-1 hop
m=ノード
数
(同期/非
同期でレ
イテンシ
が変わる)
0 hop 1プロセスに
割り当て可能
な最大量(2
~4GB)
高い(落ちたノード
を無視するのみ)
一貫
Near 1+n(+m-
1)
()内は非
0 hop
(初回を除
く)
Partitionedと
同じ
(local cache
が容量オーバ
? 要検討
前提知識のおさらい
• Cache方式
• DB連携方式
DB連携方式
• read through
• キャッシュ上になかったらDBから取り出し
キャッシュに乗せる
• write through
• キャッシュに書き込んだ後、同期してDBに
書き込む
• write behind
• キャッシュに書き込んだ後、非同期でDBに
書き込む
Read Through
DBアプリケーション
AGet A
Cache Cluster
存在する
Read Through
DBアプリケーション
AGet A
Cache Cluster
存在する
A
Read Through
DBアプリケーション
AGet A
Cache Cluster
存在しない
CacheStore
Read Through
DBアプリケーション
Get A
Cache Cluster
CacheStoreを介して
DBから取得
A
select … from ..
where id = A
Read Through
DBアプリケーション
Get A
Cache Cluster
A
CacheStore
A
二回目以降は
直接キャッシュか
ら取得可能
Write Through
DBアプリケーション
Write A
Cache Cluster
A
CacheStore
Write Through
DBアプリケーション
Write A
Cache Cluster
CacheStoreを介して
DBへ書き込み
A
insert or update
where id = A
A
CacheStore
Write Through
DBアプリケーション
Write A
Cache Cluster
CacheStoreを介して
DBへ書き込み
A
insert or update
where id = A
A
DBへ書き込みが同
期
=一貫性が保たれる
Write Behind
DBアプリケーション
Write A
Cache Cluster
A
CacheStore
Write Behind
DBアプリケーション
Write A
Cache Cluster
CacheStoreを介して
DBへ書き込み
A
insert or update
where id = A
A
CacheStore
Write Behind
DBアプリケーション
Write A
Cache Cluster
CacheStoreを介して
DBへ書き込み
A
insert or update
where id = A
A
DBへ書き込みが非同期
=一貫性は保たれないが
高スループット
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
キャッシュデータの種類
• メモリ上にのみ存在してDBには存在し
ないもの
• メモリ上にもDBにも存在して同期が必
要な物
• [メモリ上に一時的に存在してDBに同期
したら削除するもの]
キャッシュデータの種類
• メモリ上にのみ存在してDBには存在し
ないもの(非永続データ)
• メモリ上にもDBにも存在して同期が必
要な物(永続データ)
• [メモリ上に一時的に存在してDBに同期
したら削除するもの(揮発データ)]
キャッシュデータの種類
• メモリ上にのみ存在してDBには存在し
ないもの(非永続データ)
• メモリ上にもDBにも存在して同期が必
要な物(永続データ)
• [メモリ上に一時的に存在してDBに同期
したら削除するもの(揮発データ)]
同期方法要注意
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
メモリとDBの同期
• DBへの更新をどうメモリに反映させる
か
• メモリへの更新をどうDBに反映させる
か
• 一貫性は?
• 性能は?
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
DB→メモリ
• DBデータ更新時にDBトランザクショ
ンとメモリの整合性に要注意
システム構成例
System1
System2
Coherence
DB
システム構成例
System1
System2
Coherence
DB
高スループット・低レスポンス
タイムが求められる。
基本キャッシュアクセスのみ
DBのCRUDが主処理
キャッシュアクセスはデータの同期用途
のみ
システム構成例
System1
System2
Coherence
DB
高スループット・低レスポンス
タイムが求められる。
基本キャッシュアクセスのみ
DBが落ちても
System1は運用する必
要がある
DBのCRUDが主処理
キャッシュアクセスはデータの同期用途
のみ
システム構成例
System1
System2
Coherence
DB
高スループット・低レスポンス
タイムが求められる。
基本キャッシュアクセスのみ
DB更新結果をどうキャッ
シュに反映させるか
次の例を考える
Coherence
DB
account
• user_id
• first_name
• last_name
• email
• password
Account <value>
• userId <key>
• email
• password
次の例を考える
Coherence
DB
Account <value>
• userId <key>
• email
• password
account
• user_id
• first_name
• last_name
• email
• password
Cacheのフィール
ド∈ DBのフィール
ド
DB更新結果をどうキ
ャッシュに反映させる
か
• 案1: DB更新(キャッシュ上のフィールド
以外) + Write Through
• 案2: DB更新(全フィールド) + キャッシ
ュ書き込み
• 案3: DB更新(全フィールド) + キャッシ
ュ削除 + Read Through
案1: DB更新(キャッシュ上のフィ
ールド以外) + Write Through
System2
Coherence
DB
Account更新処理
案1: DB更新(キャッシュ上のフィ
ールド以外) + Write Through
System2
Coherence
DB1. update
first_name,
last_name
Account更新処理
案1: DB更新(キャッシュ上のフィ
ールド以外) + Write Through
System2
Coherence
DB
2. put Account
1. update
first_name,
last_name
Account更新処理
案1: DB更新(キャッシュ上のフィ
ールド以外) + Write Through
System2
Coherence
DB
2. put Account
3. update
user_id,
email,
password
1. update
first_name,
last_name
Account更新処理
write through
案1: DB更新(キャッシュ上のフィ
ールド以外) + Write Through
System2
Coherence
DB
2. put Account
3. update
user_id,
email,
password
1. update
first_name,
last_name
Account更新処理
write through
DB Transaction
案1: DB更新(キャッシュ上のフィ
ールド以外) + Write Through
• Account更新処理の実装が複雑
• キャッシュ更新とDB更新の両方を意識する必要がある
• JPAを使っており、accountテーブルの全フィールド更
新に比べて、一部フィールドのみ更新する実装コスト
が高い
• DB更新トランザクションとWrite Throughのトランザクシ
ョンが別になり、片方DBでエラーが生じすると整合性が
とれなくなる
• キャッシュへputしたあとDBコミットするまでに整合性が
とれていない期間がある
• トランザクション(AOP)がロールバックされてもキャッ
シュに残り続ける
案2: DB更新(全フィールド) + キ
ャッシュ書き込み
System2
Coherence
DB
Account更新処理
案2: DB更新(全フィールド) + キ
ャッシュ書き込み
System2
Coherence
DB1. update
user_id. email,
password,first_
name,
last_name
Account更新処理
案2: DB更新(全フィールド) + キ
ャッシュ書き込み
System2
Coherence
DB
2. put Account
1. update
user_id. email,
password,first_
name,
last_name
Account更新処理
案2: DB更新(全フィールド) + キ
ャッシュ書き込み
System2
Coherence
DB
2. put Account
1. update
user_id. email,
password,first_
name,
last_name
Account更新処理
DB Transaction
案2: DB更新(全フィールド) + キ
ャッシュ書き込み
• 実装は案1より低い
• 案1同様キャッシュへputしたあとDBコ
ミットするまでに整合性がとれていな
い期間がある
• トランザクション(AOP)がロールバッ
クされてもキャッシュに残り続ける
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System2
Coherence
DB
Account更新処理
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System2
Coherence
DB1. update
user_id. email,
password,first_
name,
last_name
Account更新処理
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System2
Coherence
DB1. update
user_id. email,
password,first_
name,
last_name
Account更新処理
2. remove
Account
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System2
Coherence
DB1. update
user_id. email,
password,first_
name,
last_name
Account更新処理
2. remove
Account
DB Transaction
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System1
Coherence
DB
Account参照処理
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System1
Coherence
DB
Account参照処理
1. get Account
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System1
Coherence
DB
Account参照処理
1. get Account
remove済み
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System1
Coherence
DB
Account参照処理
1. get Account
2. select
user_id,
email,
password
read through
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
System1
Coherence
DB
Account参照処理
1. get Account
2. select
user_id,
email,
password
read through
最新の情報を
取得できる
案3: DB更新(全フィールド) + キ
ャッシュ削除 + Read Through
• 実装コストが低い
• キャッシュモデル作成不要
• 対象のキーを使って削除するだけ
• データ整合性が高い
• データ不整合が起こる可能性が低い
• 念のためDBコミット後もう一回削除で整合性
を高められる
• キャッシュに初回読み込み時は連ポンスタイム
が遅くなる
• DB更新後にpreloadで対応
•どの案が適切はシステム
特性や業務内容次第
参考
• Coherence 12cからHotCache機能が追加
• http://builder.japan.zdnet.com/sp_oracle/w
eblogic_2013/35036005/2/
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
メモリ→DB
• 高スループットが求められる箇所
→Write Behind
• DBが落ちてもSystemをメモリだけで運
用する必要がある→Write Behind
• そこまで性能を求められず、一貫性が
重要な箇所→Write Through
メモリ→DB
• 高スループットが求められる箇所
→Write Behind
• DBが落ちてもSystemをメモリだけで運
用する必要がある→Write Behind
• そこまで性能を求められず、一貫性が
重要な箇所→Write Through
非同期でも問題ない
か?
非同期の問題点
System1
System2
Coherence
DB
非同期の問題点
System1
System2
Coherence
DB
1. put Account
非同期の問題点
System1
System2
Coherence
DB
2. get Account
非同期の問題点
System1
System2
Coherence
DB
2. get Account
WriteBehindの処理の前に、
データが参照されうる!
非同期の問題点
System1
System2
Coherence
DB
3. update
Account
非同期の問題点
System1
System2
Coherence
DB
3. update
Account
2. で取得した情報は最
新の状態ではない!
非同期であることのトレード
オフ
•メモリ→DBを非同期にするこ
とで、情報の不整合が必ず発
生しうる
対処方法
•非同期で更新する項目に対し
てSystem2からアクセスする
パターンを全て洗い出し、ビ
ジネス的なインパクトがない
かを一つ一つお客様に確認す
る
設計編
• キャッシュデータの種類
• メモリとDBの同期
• DB→メモリ
• メモリ→DB
• データの検索
データの検索
• 基本はキーの検索
• 要件によってキー以外のフィールドで
アクセスする必要がある
• 例:Accountキャッシュに対してuserId(キ
ー)だけでなく、emailでもアクセスしたい
Account <value>
• userId <key>
• email
キー以外のフィールドによる検索
• 転置インデックス
• 対象のフィールドの値がkeyで、対象のキャ
ッシュのkeyがvalueなキャッシュを作る
• RDBでないデータストアの検索手法として
一般的
• Filter
• Coherence独自の検索機能
• 分散インメモリデータグリッド製品には大
体実装されている
転置インデックス
Account <value>
• userId <key>
• email
AccountIndex
• email <key>
• userId <value>
転置インデックス
key value
A Account(userId=A,
email=a@example.com)
B Account(userId=B,
email=b@example.com)
key value
a@example.com A
b@example.com B
転置インデックス
Account <value>
• userId <key>
• email
AccountIndex
• email <key>
• userId <value>
転置インデックス
key value
A Account(userId=A,
email=a@example.com)
B Account(userId=B,
email=b@example.com)
key value
a@example.com A
b@example.com B
転置
転置インデックスを使っ
たキャッシュアクセス
アプリケーション
AccountIndex
Account
転置インデックスを使っ
たキャッシュアクセス
アプリケーション
AccountIndex
get a@example.com
A
Account
転置インデックスを使っ
たキャッシュアクセス
アプリケーション
AccountIndex
get a@example.com
A
get A
Account(userId=A,
email=a@example.com)
Account
転置インデックスの
作成• 手動で作成。CacheStoreに実装する。
• 主キャッシュのCRUD処理で転置インデック
スを意識する必要がある
• 主キャッシュ作成時に転置インデックスも
作成
• 主キャッシュロード時に転置インデックス
もロード
• 主キャッシュ更新時に転置インデックスも
更新
• 主キャッシュ削除時に転置インデックスも
削除
Filter
• Coherence独自の検索処理
• SQLのLIKE文のように条件を指定でき
る
• 全キャッシュノードでパラレル処理
Filterの処理
アプリケーション
search a@example.com
Cache Cluster
Filter
Filter
FilterFilter
Filter
比較
メリット デメリット
転置インデ
ックス
• 2hopで対象のキャッシュにア
クセスできて高速
• 通常のキャッシュアクセス
(put/get)の範疇で考えられる
• CRUDそれぞれで転置イ
ンデックス用のコーディ
ングを意識する必要があ
る
• 一対多の場合複雑(排他処
理の検討、
EntryProcessor)
Filter
• 自動でインデックスを作成で
きるのでコーディングがシン
プル
• Native APIの学習
• 全キャッシュノードに対
するパラレル処理になり、
負荷が大きい
• 高スループットな処理に
向かない
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
コーディング編
• キャッシュアクセスのコーディング
• モックの利用
コーディング編
• キャッシュアクセスのコーディング
• モックの利用
キャッシュアクセスのコー
ディング
• java.util.Mapを継承したkey/value
インタフェースでアクセスできる
と謳われている
キャッシュアクセスのコー
ディング
• java.util.Mapを継承したkey/value
インタフェースでアクセスできる
と謳われている
キャッシュアクセスのコー
ディング
• java.util.Mapを継承したkey/value
インタフェースでアクセスできる
と謳われている
業務アプリで直接Map
インタフェースを使
うべきでない
型不安全なキャッシュ
アクセス
• Mapインタフェースでキャッシュアクセス
するとTypeUnsafeなコードになり、仕様
変更に弱い
• キーの仕様変更は意外と起こる
• キーがStringとは限らない
• 該当のキャッシュを使用している箇所をト
レースしにくい
• 仕様変更すると実行時に
ClassCastException連発…
型安全なキャッシュ
アクセスへ
型安全なキャッシュ
アクセスへ
実際にはここをSpringの
CacheAbstract
ion機構でさらに抽
型安全なキャッシュ
アクセスへ
透過的キャッシュアクセス
• だれでも好き勝手にキャッシュアクセ
スすべきでない
• 開発者全員がCoherenceを学ぶわけで
はない
• 明示的なキャッシュアクセスは性能要
件が厳しいところに絞り、その他は透
過的にキャッシュアクセスすべし
• AOPなどを活用
透過的キャッシュアク
セスの利用例
System1
System2
Coherence
DB
System2
Coherence
DB1. update
user_id. email,
password,first_
name,
last_name
Account更新処理(案3)
2. remove
Account
DB Transaction
透過的キャッシュアク
セスの利用例
System2
Coherence
DB1. update
user_id. email,
password,first_
name,
last_name
2. remove
Account
DB Transaction
透過的キャッシュアク
セスの利用例
ここを開発者に意識
させたくない
Account更新処理(案3)
System2
Coherence
DB
1. update
user_id. email,
password,first_
name,
last_name
2. remove
Account
DB Transaction
透過的キャッシュアク
セスの利用例
Account更新処理(案3)
System2
Coherence
DB
1. update
user_id. email,
password,first_
name,
last_name
2. remove
Account
DB Transaction
透過的キャッシュアク
セスの利用例
キャッシュ削除
はAOPで実装
Account更新処理(案3)
System2
Coherence
DB
1. update
user_id. email,
password,first_
name,
last_name
2. remove
Account
DB Transaction
透過的キャッシュアク
セスの利用例
System2の開発者
はここだけ意識
Account更新処理(案3)
コーディング編
• キャッシュアクセスのコーディング
• モックの利用
モックの利用
• Coherenceは使い方が簡単でも必ずは
まる(起動の仕方、ネットワーク、キャ
ッシュモデルの最新化し忘れ等・・)
• -Dtangosol.coherence.distributed.localstorage=false
• 開発が安定していない状態で全開発者
がCoherenceを起動すると混乱に陥る
開発段階
System1
System2
Coherence
DB
開発段階
System1
System2
Coherence
DB
System2の開発中は
Coherenceを意識させたくな
い
開発段階
System1
System2
Mock
DB
Cacheのモック化
開発段階
System1
System2
Mock
DB
CacheRepository再活躍!
開発の鉄則
• Step by Stepでビルドアップしましょう
• いきなり全部作ろうとしてはダメ
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
Coherenceのチューニング
• Keyアクセスは基本的に速い
• 1 hop = 1 msec と見積もって良い
Coherenceのチューニング
• Coherenceのチューニング = いかにし
てhop数を減らすか
• 複数に渡るキャッシュアクセスをでき
るだけまとめる
チューニング編
• データアフィニティ
• EntryProcessor
チューニング編
• データアフィニティ
• EntryProcessor
データアフィニティ
• 関連するキャッシュデータを物理的に
同じノードに配置させる
データアフィニティ
がない場合
アプリケーション
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
データアフィニティ
がない場合
アプリケーション
1. get a@example.com
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
A
データアフィニティ
がない場合
アプリケーション
1. get a@example.com
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
2. get A
A
Account(key=A)
データアフィニティ
がない場合
アプリケーション
1. get a@example.com
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
2. get A
A
Account(key=A)
2 hop必要
データアフィニティ
がある場合
アプリケーション
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
データアフィニティ
がある場合
アプリケーション
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
同じノードに
配置される
データアフィニティ
がある場合
アプリケーション
1. get a@example.com
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)A
データアフィニティ
がある場合
アプリケーション
1. get a@example.com
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
2. get A
A
Account(key=A)
データアフィニティ
がある場合
アプリケーション
1. get a@example.com
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
2. get A
A
Account(key=A)
結局2 hop必要・・・
チューニング編
• データアフィニティ
• EntryProcessor
EntryProcessor
• Cacheサーバー側に処理を置く
• DBにおけるStoredProcedureに相当
• 複数のキャッシュモデルをAtomicに操
作
EntryProcessor
アプリケーション
Cache Cluster
Entry
Processor
EntryProcessor
アプリケーション
process
Cache Cluster
Entry
Processor
データアフィニティ+
EntryProcessor
アプリケーション
process
Cache Cluster
AccountIndex
(key=a@example.co
m)
Account
(key=A)
Entry
Processor
データアフィニティ+
EntryProcessor
process
Entry
Processor AccountIndex
(key=a@example.co
m)
Account
(key=A)
データアフィニティ+
EntryProcessor
process
Entry
Processor AccountIndex
(key=a@example.co
m)
Account
(key=A)
1. get a@example.com
2. get A
A
Account(key=A)
Account(key=A)
データアフィニティ+
EntryProcessor
process
Entry
Processor AccountIndex
(key=a@example.co
m)
Account
(key=A)
1. get a@example.com
2. get A
A
Account(key=A)
Account(key=A)
EntryProcessor内では、
処理実行中の物理ノー
ドにアクセスできる
データアフィニティ+
EntryProcessor
process
Entry
Processor AccountIndex
(key=a@example.co
m)
Account
(key=A)
1. get a@example.com
2. get A
A
Account(key=A)
Account(key=A)
1 hopで処理完了
EntryProcessorの注意
点
• コーディングが普通のキャッシュアク
セスより煩雑になる
• Coherenceと密結合になり、テスタビ
リティが下がる
• キャッシュサーバーにデプロイする必
要があるので開発効率が下がる
EntryProcessorの注意
点
• 速いからといって何でもかんでも
EntryProcessorで実装すればよいという
ものではない
• 性能テストで性能要件が満たせない場
合に検討
• あとでEntryProcessorに以降できるよう
な設計を予め行っておく
チューニングの鉄則
• 必要になるまでチューニングすべきで
ない
• 性能テストで測定してから最適化
• 予め実施すべきはスケーラビリティの
確保のみ
「早すぎる最適化は諸悪の根源であ
る」
by ドナルド・クヌース
チューニングの鉄則
• 必要になるまでチューニングすべきで
ない
• 性能テストで測定してから最適化
• 予め実施すべきはスケーラビリティの
確保のみ
Coherenceを採用すること自体
「早すぎる最適化は諸悪の根源であ
る」
by ドナルド・クヌース
Agenda
• 今日の話のスコープ
• 前提知識のおさらい
• 設計編
• コーディング編
• チューニング編
• Advanced Topic
初期ローダ
• DBに格納されている数億件のデータを
初回にプレロードしたい
初期ローダ
• DBに格納されている数億件のデータを
初回にプレロードしたい
• 数時間以内で
普通の考え
DBアプリケーション
put
Cache Cluster
select
普通の考え
DBアプリケーション
put
Cache Cluster
select
完了するのに
数日かかる
普通の考え+
DBアプリケーション
put
Cache Cluster
select where mod(id, n) = m
アプリケーション
アプリケーション
…
普通の考え+
DBアプリケーション
put
select where mod(id, n) = m
アプリケーション
アプリケーション
…
多少スケールするがアプリケーシ
ョンサーバー数と管理がネック
InvocationService
• キャッシュサーバーにタスクを依頼
• 非同期処理でタスク実行状況をobserve
できる
InvocationService
• キャッシュサーバーにタスクを依頼
• 非同期処理でタスク実行状況をobserve
できる
EntryProcessorは同期のみ対応
InvocationService
• キャッシュサーバーにタスクを依頼
• 非同期処理でタスク実行状況をobserve
できる
たくさんいるキャッシュサーバーのリソース
を使ってデータのロードを行う
InvocationService
による分散処理
DBアプリケーション
Cache Cluster
InvocationServi
ce
put
各キャッシュノード
にTaskをputする
InvocationService
による分散処理
DBアプリケーション
Cache Cluster
Task
Task
InvocationServi
ce
put
Task Task
Task
各キャッシュノード
にTaskをputする
InvocationService
による分散処理
DBアプリケーション
Cache Cluster
select where mod(id, n) = m
Task
Task
InvocationServi
ce
put
Task Task
Task
Task内でDBからロ
ードしキャッシュへ
putする
InvocationService
による分散処理
DBアプリケーション
Cache Cluster
select where mod(id, n) = m
Task
Task
InvocationServi
ce
put
Task Task
Task
あとはSQLチューニ
ング
まとめ
• 前提知識のおさらい
• Cache方式
• DB連携方式
• 設計編
• キャッシュデータの種類
• メモリとDBの同期
• データの検索
• コーディング編
• キャッシュアクセスのコーディング
• モックの利用
• チューニング編
• データアフィニティ
• EntryProcessor
• Advanced Topic
• InvocationServiceによる初期ロード
おわりに
• Coherenceは上手に使うとハイパフォーマンスを
実現してくれる良い製品
• 本発表のパターンがオンリー1なわけではない
• 要件によってベストなパターンは変わりうる
• カタログスペックを信用しすぎず、コンサルタン
トとよく相談して方式を定めるべき
• コンサルタントなしで利用すべきでない・・
• 細かいオプション多すぎ・・・(非推奨なものも
多数)

Coherenceを利用するときに気をつけること #OracleCoherence