いつ、どのようにHibernate 2次キャッシュを使用するのですか?


90

hibernateが2番目のレベルのキャッシュにヒットするタイミングと、キャッシュが無効になるタイミングを理解できません。

これは私が現在理解していることです:

  • 2次キャッシュはセッション間のエンティティを保存します。スコープはSessionFactoryです
  • キャッシュするエンティティを指定する必要があります。デフォルトでは、エンティティはキャッシュされません。
  • クエリキャッシュは、クエリの結果をキャッシュに保存します。

わからないのは

  • 休止状態はいつこのキャッシュにヒットしますか?
  • 2番目のレベルのキャッシュを設定したが、クエリのキャッシュは設定していないとしましょう。顧客をキャッシュしたいのですが、50000あります。どのようにしてキャッシュから顧客を取得できますか?
  • キャッシュからIDで取得できると思います。それは簡単ですが、キャッシュする価値もありません。しかし、もし私がすべての顧客と何らかの計算をしたいとしたらどうでしょう。顧客のリストを表示したい場合、どうすれば顧客にアクセスできますか?
  • クエリキャッシュが無効になっている場合、どのようにすればすべての顧客を獲得できますか?
  • 誰かが顧客の1人を更新するとどうなりますか?
    • その顧客はキャッシュで無効になりますか、それともすべての顧客が無効になりますか?

それともキャッシュが完全に間違っていると思いますか?その場合、2次キャッシュのより適切な使用法は何でしょうか?hibernateのドキュメントでは、キャッシュが実際にどのように機能するかはまったく明確ではありません。それをセットアップする方法についての指示だけがあります。

更新: したがって、2番目のレベルのキャッシュ(クエリキャッシュなし)がIDでデータをロードするのに適していることを理解するようになりました。たとえば、Webアプリケーションのすべてのリクエストでパーミッションをチェックしたいユーザーオブジェクトがあります。これは、2次キャッシュにユーザーをキャッシュすることでデータベースアクセスを削減する良い例でしょうか?セッションまたはどこにでもユーザーIDを格納するように、アクセス許可を確認する必要がある場合は、IDでユーザーを読み込み、アクセス許可を確認します。


回答:


100

まず、プロセスレベルキャッシュ(またはHibernateでそれを呼び出すときの2次レベルキャッシュ)について話しましょう。それを機能させるには、

  1. キャッシュプロバイダーの構成
  2. キャッシュするエンティティをhibernateに指示します(この種のマッピングを使用する場合はhbm.xmlファイルにあります)。

キャッシュプロバイダーに、オブジェクトをいくつ保存する必要があるか、いつ/なぜ無効にする必要があるかを伝えます。たとえば、BookエンティティとAuthorエンティティがあり、それらをDBから取得するたびに、キャッシュにないエンティティのみが実際のDBから選択されます。これにより、パフォーマンスが大幅に向上します。次の場合に役立ちます。

  • Hibernateを介してのみデータベースに書き込みます(キャッシュ内のエンティティをいつ変更または無効化するかを知る方法が必要なため)
  • オブジェクトをよく読む
  • 単一のノードがあり、レプリケーションはありません。それ以外の場合は、キャッシュ自体を複製する必要があります(JGroupsのような分散キャッシュを使用)。これにより、複雑さが増し、シェアーナッシングアプリほどスケールが良くありません。

では、キャッシュはいつ機能するのでしょうか?

  • あなたsession.get()またはsession.load()以前に選択され、キャッシュに存在するオブジェクト。キャッシュは、IDがキーでプロパティが値であるストレージです。したがって、IDで検索する可能性がある場合にのみ、DBへのアクセスを排除できます。
  • アソシエーションがレイジーロードされている(または結合ではなく選択でイージーロードされている)場合

ただし、次の場合は機能しません。

  • IDで選択しない場合。この場合も、2次キャッシュはエンティティのIDのマップを他のプロパティに格納します(実際にはオブジェクトを格納せず、データ自体を格納します)。したがって、ルックアップが次のようになっている場合は、from Authors where name = :nameキャッシュにヒットしません。
  • HQLを使用する場合(たとえを使用した場合でもwhere id = ?)。
  • マッピングでを設定した場合fetch="join"、これは、関連付けをロードするために、個別の選択ステートメントではなく、どこでも結合が使用されることを意味します。プロセスレベルのキャッシュfetch="select"は、が使用されている場合にのみ子オブジェクトで機能します。
  • あなたが持っている場合でも、fetch="select"その後HQLで使用する関連付けを選択するために参加する-それらはすぐに発行されます参加し、彼らはあなたがのhbm.xmlや注釈で指定されたものは何でも上書きされます。

次に、クエリキャッシュについて説明します。これは独立したキャッシュではなく、プロセスレベルのキャッシュへの追加であることに注意してください。国エンティティがあるとします。これは静的なので、と言うと毎回同じ結果セットが存在することがわかりますfrom Country。この、クエリキャッシュのための完璧な候補である、それはリスト格納するIDを自分自身にしてたとき、次回のすべての国を選択し、それは順番に、各IDのためのオブジェクトを返します、プロセス・レベルのキャッシュ、後者には、このリストを返します。これらのオブジェクトはすでに2次キャッシュに保存されているためです。エンティティに関連するものが変更されるたびに、クエリキャッシュは無効になります。それではfrom Authors、クエリキャッシュに配置するように構成したとします。著者は頻繁に変更するため、効果がありません。


「著者からのフェッチa.booksのフェッチ」というクエリでは、キャッシュから著者をフェッチするためにクエリキャッシュが必要ですか?
palto

1
いいえ、クエリキャッシュは静的データ専用であり、IDのみを保存します。著者は2次キャッシュから取得されます。
Stanislav Bashkyrtsev 2011

@ctapobep:あなたの言うことは正しくない!"Authorからfetch join a.books"は、エンティティAuthorのフィールドブックに注釈が付けられている場合は正常に機能します(フェッチEAGER)...手遅れだと思います
Bilal BBB

そのような素晴らしい答え!ずっと覚えています!:d
Mohammadreza Khatami

「クエリキャッシュ」を有効にした後、ID以外のプロパティで選択した場合、キャッシュからデータをフェッチしますか?
アルンRaaj

41
  • 2次キャッシュはキーと値のストアです。IDでエンティティを取得する場合にのみ機能します
  • エンティティが休止状態を介して更新/削除されると、2次キャッシュはエンティティごとに無効化/更新されます。データベースが別の方法で更新されても、無効にはなりません。
  • クエリ(顧客リストなど)の場合は、クエリキャッシュを使用します。

実際には、Key-Value分散キャッシュがあると便利です。これがmemcachedと同じであり、facebook、twitterなどの機能を強化します。ただし、IDによるルックアップがない場合は、あまり役に立ちません。


12

パーティーに遅れたが、多くの開発者が尋ねるこれらの質問に体系的に答えたいと思った。

ここであなたの質問を一つずつ取り上げることが私の答えです。

Q.休止状態はいつこのキャッシュにヒットしますか?

A. 一次キャッシュセッションオブジェクトに関連付けられていますセカンドレベルキャッシュが関連付けられているセッションファクトリオブジェクト。最初のオブジェクトが見つからない場合は、2番目のレベルがチェックされます。

Q. 2次キャッシュを設定したが、クエリキャッシュは設定しなかったとしましょう。顧客をキャッシュしたいのですが、50000あります。どのようにしてキャッシュから顧客を取得できますか?

A.アップデートでその答えを得ました。また、クエリキャッシュはオブジェクトのIDのリストのみを格納し、それらのオブジェクトのIDが同じ 2次レベルキャッシュに格納されます。したがって、クエリキャッシュを有効にすると、同じリソースが利用されます。きちんとね?

Q.キャッシュからIDで取得できると思います。それは簡単ですが、キャッシュする価値もありません。しかし、もし私がすべての顧客と何らかの計算をしたいとしたらどうでしょう。顧客のリストを表示したい場合、どうすれば顧客にアクセスできますか?

A.上記の回答。

Q.クエリキャッシュが無効になっている場合、どのようにしてすべての顧客を獲得できますか?

A.上記の回答。

Q.誰かが顧客の1人を更新するとどうなりますか?その顧客はキャッシュで無効になりますか、それともすべての顧客が無効になりますか?

A. Hibernateにはアイデアがありませんが、他のサードパーティのIMDG /分散キャッシュを使用して、Hibernateの2次レベルキャッシュとして実装し、無効にすることができます。たとえば、TayzGridはそのような製品の1つであり、他にもあります。


0

Hibernateの2次キャッシュは、理解して実装するのが少し難しいです。質問に基づいて以下のことが言えます。

Hibernateはいつこのキャッシュにヒットしますか?

ご提案のとおり、Hibernate L2キャッシュ(有効になっている場合、デフォルトではオンになっていません)は、L1キャッシュの後でのみ照会されます。これは、データが複数のセッションにわたって保持されるKey-Valueキャッシュです。

2番目のレベルのキャッシュを設定したが、クエリのキャッシュは設定していないとしましょう。顧客をキャッシュしたいのですが、50000あります。どのようにしてキャッシュから顧客を取得できますか?

顧客データは静的であり、リレーショナルデータベースから取得されるため、クエリキャッシングはこの使用例に最適です。

誰かが顧客の1人を更新するとどうなりますか?その顧客はキャッシュで無効になりますか、それともすべての顧客が無効になりますか?

これは、使用している特定のHibernateキャッシュ戦略に依存します。Hibernateには実際には4つの異なるキャッシュ戦略があります。

READ_ONLY:オブジェクトはキャッシュ内で一度変更されません。

NONSTRICT_READ_WRITE:対応するデータベースエントリが更新された後、オブジェクトは(最終的に)変更されます。これにより、結果の一貫性が保証されます。

READ_WRITE:対応するデータベースエントリが更新された後、オブジェクトは(すぐに)変更されます。これにより、「ソフト」ロックを使用して強力な一貫性が保証されます。

TRANSACTIONAL:分散XAトランザクションを使用してオブジェクトが変更され、データの整合性が確保されます。これにより、完全な成功またはすべての変更のロールバックが保証されます。ただし、これら4つのケースすべてで、単一のデータベースエントリを更新しても、キャッシュ内の顧客のリスト全体が無効になることはありません。Hibernateはそれより少し賢いです:)

HibernateでのL2キャッシングの仕組みの詳細については、記事「Hibernate L2キャッシュとは」、または詳細な記事「Redisを使用したHibernateでのキャッシング」をチェックしてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.