日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

HibernateNONSTRICT_READ_WRITE CacheConcurrencyStrategy如何工作

發(fā)布時(shí)間:2023/12/3 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HibernateNONSTRICT_READ_WRITE CacheConcurrencyStrategy如何工作 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

介紹

在我以前的文章中 ,我介紹了READ_ONLY CacheConcurrencyStrategy ,這是不可變實(shí)體圖的顯而易見的選擇。 當(dāng)高速緩存的數(shù)據(jù)可變時(shí),我們需要使用讀寫高速緩存策略,本文將介紹NONSTRICT_READ_WRITE二級(jí)高速緩存的工作方式。

內(nèi)部運(yùn)作

提交Hibernate事務(wù)后,將執(zhí)行以下操作序列:

首先,在刷新期間,在提交數(shù)據(jù)庫(kù)事務(wù)之前,緩存無效:

  • 當(dāng)前的Hibernate事務(wù) (例如JdbcTransaction , JtaTransaction )已刷新
  • DefaultFlushEventListener執(zhí)行當(dāng)前的ActionQueue
  • EntityUpdateAction調(diào)用EntityRegionAccessStrategy的更新方法
  • NonStrictReadWriteEhcacheCollectionRegionAccessStrategy從基礎(chǔ)EhcacheEntityRegion中刪除緩存條目
  • 提交數(shù)據(jù)庫(kù)事務(wù)后,將再次刪除緩存條目:

  • 完成回調(diào)后當(dāng)前的Hibernate Transaction被調(diào)用
  • 當(dāng)前會(huì)話將此事件傳播到其內(nèi)部ActionQueue
  • EntityUpdateAction在EntityRegionAccessStrategy上調(diào)用afterUpdate方法
  • NonStrictReadWriteEhcacheCollectionRegionAccessStrategy調(diào)用基礎(chǔ)EhcacheEntityRegion上的remove方法
  • 不一致警告

    NONSTRICT_READ_WRITE模式不是“ 直 寫式”緩存策略,因?yàn)榫彺鏃l目無效,而不是被更新。 緩存無效化與當(dāng)前數(shù)據(jù)庫(kù)事務(wù)不同步。 即使關(guān)聯(lián)的Cache區(qū)域條目?jī)纱螣o效(在事務(wù)完成之前和之后),當(dāng)緩存和數(shù)據(jù)庫(kù)可能分開時(shí),仍然存在一個(gè)很小的時(shí)間窗口。

    以下測(cè)試將演示此問題。 首先,我們將定義Alice事務(wù)邏輯:

    doInTransaction(session -> {LOGGER.info("Load and modify Repository");Repository repository = (Repository)session.get(Repository.class, 1L);assertTrue(getSessionFactory().getCache().containsEntity(Repository.class, 1L));repository.setName("High-Performance Hibernate");applyInterceptor.set(true); });endLatch.await();assertFalse(getSessionFactory().getCache().containsEntity(Repository.class, 1L));doInTransaction(session -> {applyInterceptor.set(false);Repository repository = (Repository)session.get(Repository.class, 1L);LOGGER.info("Cached Repository {}", repository); });

    愛麗絲加載一個(gè)存儲(chǔ)庫(kù)實(shí)體,并在她的第一個(gè)數(shù)據(jù)庫(kù)事務(wù)中對(duì)其進(jìn)行修改。
    為了在Alice準(zhǔn)備提交時(shí)產(chǎn)生另一個(gè)并發(fā)事務(wù),我們將使用以下Hibernate Interceptor :

    private AtomicBoolean applyInterceptor = new AtomicBoolean();private final CountDownLatch endLatch = new CountDownLatch(1);private class BobTransaction extends EmptyInterceptor {@Overridepublic void beforeTransactionCompletion(Transaction tx) {if(applyInterceptor.get()) {LOGGER.info("Fetch Repository");assertFalse(getSessionFactory().getCache().containsEntity(Repository.class, 1L));executeSync(() -> {Session _session = getSessionFactory().openSession();Repository repository = (Repository) _session.get(Repository.class, 1L);LOGGER.info("Cached Repository {}", repository);_session.close();endLatch.countDown();});assertTrue(getSessionFactory().getCache().containsEntity(Repository.class, 1L));}} }

    運(yùn)行此代碼將生成以下輸出:

    [Alice]: Load and modify Repository [Alice]: select nonstrictr0_.id as id1_0_0_, nonstrictr0_.name as name2_0_0_ from repository nonstrictr0_ where nonstrictr0_.id=1 [Alice]: update repository set name='High-Performance Hibernate' where id=1[Alice]: Fetch Repository from another transaction [Bob]: select nonstrictr0_.id as id1_0_0_, nonstrictr0_.name as name2_0_0_ from repository nonstrictr0_ where nonstrictr0_.id=1 [Bob]: Cached Repository from Bob's transaction Repository{id=1, name='Hibernate-Master-Class'}[Alice]: committed JDBC Connection[Alice]: select nonstrictr0_.id as id1_0_0_, nonstrictr0_.name as name2_0_0_ from repository nonstrictr0_ where nonstrictr0_.id=1 [Alice]: Cached Repository Repository{id=1, name='High-Performance Hibernate'}
  • Alice獲取存儲(chǔ)庫(kù)并更新其名稱
  • 調(diào)用定制的Hibernate Interceptor并啟動(dòng)Bob的事務(wù)
  • 由于存儲(chǔ)庫(kù)已從緩存中逐出,因此Bob會(huì)使用當(dāng)前數(shù)據(jù)庫(kù)快照加載第二級(jí)緩存
  • Alice事務(wù)提交,但是現(xiàn)在緩存包含Bob剛剛加載的先前數(shù)據(jù)庫(kù)快照
  • 如果第三位用戶現(xiàn)在將獲取存儲(chǔ)庫(kù)實(shí)體,則他還將看到與當(dāng)前數(shù)據(jù)庫(kù)快照不同的陳舊實(shí)體版本。
  • 提交Alice事務(wù)后,將再次逐出Cache條目,并且任何后續(xù)實(shí)體加載請(qǐng)求都將使用當(dāng)前數(shù)據(jù)庫(kù)快照填充Cache
  • 過時(shí)的數(shù)據(jù)與丟失的更新

    當(dāng)數(shù)據(jù)庫(kù)和二級(jí)緩存可能不同步時(shí), NONSTRICT_READ_WRITE并發(fā)策略會(huì)引入一個(gè)很小的不一致窗口。 盡管這聽起來可能很糟糕,但實(shí)際上,即使我們不使用二級(jí)緩存,也應(yīng)始終設(shè)計(jì)應(yīng)用程序來應(yīng)對(duì)這些情況。 Hibernate通過其事務(wù)性的后臺(tái)寫式第一級(jí)緩存提供應(yīng)用程序級(jí)可重復(fù)讀取,并且所有托管實(shí)體都將變得過時(shí)。 在實(shí)體加載到當(dāng)前的持久性上下文中之后 ,另一個(gè)并發(fā)事務(wù)可能會(huì)對(duì)其進(jìn)行更新,因此,我們需要防止陳舊數(shù)據(jù)升級(jí)為丟失更新 。

    樂觀并發(fā)控制是處理長(zhǎng)時(shí)間對(duì)話中丟失的更新的有效方法,該技術(shù)還可以緩解NONSTRICT_READ_WRITE不一致問題。

    結(jié)論

    NONSTRICT_READ_WRITE并發(fā)策略是大多數(shù)只讀應(yīng)用程序的理想選擇(如果由樂觀鎖定機(jī)制支持)。 對(duì)于寫密集型方案,緩存無效機(jī)制將增加緩存未命中率 ,因此使該技術(shù)效率低下。

    • 代碼可在GitHub上獲得 。

    翻譯自: https://www.javacodegeeks.com/2015/05/how-does-hibernate-nonstrict_read_write-cacheconcurrencystrategy-work.html

    總結(jié)

    以上是生活随笔為你收集整理的HibernateNONSTRICT_READ_WRITE CacheConcurrencyStrategy如何工作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。