Hibernateのキャッシュについて考えてみる(その3)

前回は、キャッシュ関連の分類と、キャッシュプロバイダ実装側の対応について考えてみました。分類にもいろいろあり、実装にもいろいろあって、一気にすべて理解するのは難しそうです。ということで、今回は Cache Concurrency Strategy の概要を確認してみたいと思います。

マニュアル曰く

read only

If your application needs to read but never modify instances of a persistent class, a read-only cache may be used. This is the simplest and best performing strategy. It's even perfectly safe for use in a cluster.

http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache-readonly

おいら的意訳:
アプリケーションが、永続化クラスのインスタンスの読み込みを行う必要があるが変更を行う必要がない場合、read-only キャッシュが使用可能です。これは、最もシンプルで最高のパフォーマンスを実現する戦略です。クラスタ環境においても安全に使用可能です。

read/write

If the application needs to update data, a read-write cache might be appropriate. This cache strategy should never be used if serializable transaction isolation level is required. If the cache is used in a JTA environment, you must specify the property hibernate.transaction.manager_lookup_class, naming a strategy for obtaining the JTA TransactionManager. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called. If you wish to use this strategy in a cluster, you should ensure that the underlying cache implementation supports locking. The built-in cache providers do not.

http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache-readwrite

おいら的意訳:
アプリケーションがデータを更新する必要がある場合、read-write キャッシュが適切かもしれません。このキャッシュ戦略は、トランザクションアイソレーションレベルが serializable の場合は使用してはいけません。キャッシュが JTA 環境で使用される場合は、hibernate.transaction.manager_lookup_class プロパティで JTA TransactionManager を取得するための戦略を指定する必要があります。その他の環境では、Session.close() もしくは Session.disconnect() が呼び出された際に、トランザクションが完了していることを保証する必要があります。この戦略をクラスタ内で使用する場合は、キャッシュ実装がロッキングをサポートすることを保証する必要があります。ビルトインの各キャッシュプロバイダはロッキングをサポートしていません。
※ロッキングは、Cache.lock(Object key) および Cache.unlock(java.lang.Object) のことだと思われ。

nonstrict read/write

If the application only occasionally needs to update data (ie. if it is extremely unlikely that two transactions would try to update the same item simultaneously) and strict transaction isolation is not required, a nonstrict-read-write cache might be appropriate. If the cache is used in a JTA environment, you must specify hibernate.transaction.manager_lookup_class. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called.

http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache-nonstrict

おいら的意訳:
もし、アプリケーションがたまにしかデータを更新しない場合(例:2つのトランザクションが同時に同一対象を変更することがほとんど考えられない場合)や厳密なトランザクション分離が必要ない場合には、nonstrict-read-write キャッシュが適切かもしれません。キャッシュが JTA 環境で使用される場合は、hibernate.transaction.manager_lookup_class プロパティで JTA TransactionManager を取得するための名前戦略を指定する必要があります。その他の環境では、Session.close() もしくは Session.disconnect() が呼び出された際に、トランザクションが完了していることを保証する必要があります。

transactional

The transactional cache strategy provides support for fully transactional cache providers such as JBoss TreeCache. Such a cache may only be used in a JTA environment and you must specify hibernate.transaction.manager_lookup_class.

http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache-transactional

おいら的意訳:
transactional キャッシュは、JBoss TreeCache のようなフル・トランザクショナルなキャッシュプロバイダをサポートします。そのようなキャッシュは JTA 環境のみで使用可能で、hibernate.transaction.manager_lookup_class を指定しなくてはなりません。)

すべての Cache Concurrency Strategy をサポートするキャッシュプロバイダは存在しない。

None of the cache providers support all of the cache concurrency strategies. The following table shows which providers are compatible with which concurrency strategies.

http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#d0e14541

もう少し踏み込んで考えてみる

マニュアルでは、read only の設定が読み込み専用として適切であるようなことが書かれています。しかし、データを insert をしてしまった場合についての記述はありません。また、nonstrict read/write において、どのような場合にどのような形で DB とキャッシュの不整合が起こるのかは書かれていません。ほかにも、read/write は絶対に DB とキャッシュの不整合が起きないことが保証されているのかとか、transactional って実際にどのような動作をするのかとか、いろいろ気になります。


おそらく、もう少し具体的なレベルで理解しておかなければ、Hiberanteのキャッシュを使いこなすことは難しいのではないかと思います。Hibernate側だけでも正確に理解することが難しいのですから、各キャッシュプロバイダ実装の独自機能と組み合わせるのはさらに大変だと思います。

Cache Concurrency Strategy の実装

Cache Concurrency Strategy は、org.hibernate.cache.CacheConcurrencyStrategy インタフェースとして定義されています。このインタフェースを implements しているクラスを以下に示します。

そのまんまですね。

まとめ

今回は Cache Concurrency Strategy の概要を確認してみました。次回CacheConcurrencyStrategy インタフェースにフォーカスしてみようと思います。