1

高スループットの読み取り専用の spring/jpa/hibernate アプリ (Web API) があり、Hibernate の第 2 レベルのキャッシュに依存する場合のパフォーマンスが許容できないことがわかりました。セッションの各読み取りトランザクション内でエンティティの再水和に費やされる CPU 時間が多すぎます。 。得る()。

したがって、次の理由から、(VM 内の) エンティティをオブジェクト (脱水されていない) としてキャッシュする道を進んでいます。

  • データモデル全体を VM ヒープ内に収めることができます
  • 古さは気にしません (アプリの存続期間中、キャッシュは最新の状態を表していると想定できます)

最初は、サービス レイヤーと DAO レイヤーの間に位置するライトスルー キャッシュ レイヤーを実装することを考えていました。

ただし、上記の仮定を考えると、別のアプローチの方が簡単なようです。

  • 会話型 EntityManager を宣言します (アプリの開始時に初期化、アプリの停止時に手動で閉じる):

    @PersistenceContext(type = PersistenceContextType.EXTENDED, properties = {@PersistenceProperty(name = AvailableSettings.FLUSH_MODE, value = "MANUAL")}) プライベート HibernateEntityManager conversationalEM;

  • 上記のプロキシをすべての DAO impl に挿入します

  • (オプション) アプリの起動時に別のトランザクションですべてのエンティティを EM にプリロードします (複数のスレッドが同じセッションに後で書き込もうとする可能性を回避するため)。
  • したがって、dao.loadEntity(id) などのすべての操作は、共有された Hibernate セッションに「ヒット」し、DB クエリや再ハイドレーションなしでエンティティ インスタンスを返します。

後者のアプローチの落とし穴はありますか?

たとえば、EM は多数の (常に読み取り専用) トランザクションにまたがり、同時実行 (複数のクライアントが同時に API をヒット) を含むため、これらのトランザクションは引き続きコミットする必要があります。Hibernate EM impl は tx オブジェクトを参照するため、複数のスレッドが同じ TX オブジェクトで commit() を試行している状況に陥る可能性があるようです...

4

0 に答える 0