Hibernateのキャッシュについて考える

Hibernateは、キャッシュ周りのインタフェースを定義し、実装を交換可能にしています。ということで、CacheProvider インタフェースと Cache インタフェースを見てみました。

インタフェース org.hibernate.cache.CacheProvider

Cache buildCache(String regionName, Properties properties) throws CacheException;
long nextTimestamp();
void start(Properties properties) throws CacheException;
void stop();
boolean isMinimalPutsEnabledByDefault();
Cache buildCache(String regionName, Properties properties) throws CacheException;
  • 指定されたリージョン名のキャッシュ実装を返します。
  • HashMapCacheProvider も、EhCacheProvider も、OSCacheProvider も、properties は使用していません。
long nextTimestamp();
  • SessionImpl のコンストラクタに渡されるために使用されている。
  • HashMapCacheProvider も、EhCacheProvider も、OSCacheProvider も、return Timestamper.next(); してるだけ。
void start(Properties properties) throws CacheException;
  • キャッシュ実装に応じた初期化処理を行うように、SessionFactory 作成時に呼ばれます。
  • OSCacheでは、このタイミングで、キャッシュとして GeneralCacheAdministrator を作成しています。
  • EhCacheでは、このタイミングで、CacheManagerを作成しています。
  • OSCacheでもEhCacheでも、properties から設定ファイルのパスを導き出し、読み出しています。
void stop();
  • EntityManagerFactoryがcloseする際に呼ばれます。
  • 実装は、CacheProvider全体の停止処理を行います。
  • OSCacheでは、GeneralCacheAdministrator#destroy() を呼び出しています。
  • EhCacheでは、CacheManager#shutdown() を呼び出しています。
boolean isMinimalPutsEnabledByDefault();
  • isMinimalPutsEnabledByDefault のデフォルト値を返します。
  • HashMapCacheProvider も、EhCacheProvider も、OSCacheProvider も、return false; してるだけ。

インタフェース org.hibernate.cache.Cache

Object read(Object key) throws CacheException;
Object get(Object key) throws CacheException;
void put(Object key, Object value) throws CacheException;
void update(Object key, Object value) throws CacheException;
void remove(Object key) throws CacheException;
void clear() throws CacheException;
void destroy() throws CacheException;
void lock(Object key) throws CacheException;
void unlock(Object key) throws CacheException;
long nextTimestamp();
int getTimeout();
String getRegionName();
long getSizeInMemory();
long getElementCountInMemory();
long getElementCountOnDisk();
Map toMap();
Object read(Object key) throws CacheException;
  • トランザクショナルに、キャッシュからデータを取得します。
  • transactional の場合に使用されます。
  • HashMapCache も、EhCache も、OSCache も、get() してるだけ。
Object get(Object key) throws CacheException;
  • 非トランザクショナルに、キャッシュからデータを取得します。
  • read-only, read-write, nonstrict-read-write の場合に使用されます。
  • EhCacheは、キーからElementを取得し、値を取得して返している。
  • OSCacheは、キーから独自ルール(obj.toString()+'.'+regionName)でキー文字列を作成し、キャッシュからデータを取得しています。その際に、refreshPeriod(時間) と cron(cron表記) を渡して、期限切れ処理をしています。ということは、OSCacheの場合、toString()で同一性をあらわせないキーは扱えないということになります。
void put(Object key, Object value) throws CacheException;
  • エンティティを格納します。
  • read-writeの場合は、キーでロックされた後にこのメソッドが呼び出されます。
void update(Object key, Object value) throws CacheException;
  • HashMapCache も、EhCache も、OSCache も、put(Object key, Object value) に処理を委譲しています。
void remove(Object key) throws CacheException;
  • 削除、退避、キーのリリース等、さまざまな用途で呼ばれます。
void clear() throws CacheException;
  • クラスやコレクションやエンティティ全体の退避時などに呼ばれます。
void destroy() throws CacheException;
  • EntityManagerFactoryがcloseする際に呼ばれます。
  • 実装は、キャッシュの廃棄処理をします。
void lock(Object key) throws CacheException;
  • read-write の場合のみ使用されます。
  • 分散キャッシュの場合は、指定されたキーに関して、分散キャッシュ全体にロックをかけます。
  • HashMapCache も、EhCache も、OSCache も、何もしてません。
void unlock(Object key) throws CacheException;
  • read-write の場合のみ使用されます。
  • 分散キャッシュの場合は、指定されたキーに関して、分散キャッシュ全体にロックをかけます。
  • HashMapCache も、EhCache も、OSCache も、何もしてません。
long nextTimestamp();
  • HashMapCache も、EhCache も、OSCache も、return Timestamper.next(); してるだけ。
int getTimeout();
  • read-write の場合のみ使用されます。
  • ロックのタイムアウト時間を返します。
  • UpdateTimestampCacheの場合にも使用されます。
  • HashMapCache も、EhCache も、OSCache も、return Timestamper.ONE_MS * 60000; してるだけ。
String getRegionName();
  • リージョン名を返します。
long getSizeInMemory();
  • SecondLevelCacheStatistics から呼び出されます。
  • EhCacheの場合、シリアライズしたサイズを返す処理が行われ、非常に重い処理になる。1MB/秒程度。
  • OSCacheの場合、-1を返す。
long getElementCountInMemory();
  • SecondLevelCacheStatistics#getElementCountInMemory() から呼び出されます。
long getElementCountOnDisk();
  • SecondLevelCacheStatistics#getElementCountOnDisk() から呼び出されます。
Map toMap();
  • SecondLevelCacheStatistics#getEntries() から呼び出されます。

バックログ

  • lock(), unlock() がらみについては、Hibernate側の動作シーケンスを含めてもちょっと理解を深めよう。
  • TimeStamp と Session や Transaction の関係についてもちょっと理解を深めよう。