休眠NONSTRICT_READ_WRITE CacheConcurrencyStrategy如何工作
介紹
在我以前的文章中 ,我介紹了READ_ONLY CacheConcurrencyStrategy ,這是不可變實體圖的顯而易見的選擇。 當(dāng)緩存的數(shù)據(jù)可變時,我們需要使用讀寫緩存策略,本文將介紹NONSTRICT_READ_WRITE二級緩存的工作方式。
內(nèi)部運作
提交Hibernate事務(wù)后,將執(zhí)行以下操作序列:
首先,在刷新期間,在提交數(shù)據(jù)庫事務(wù)之前,緩存無效:
提交數(shù)據(jù)庫事務(wù)后,將再次刪除緩存條目:
不一致警告
NONSTRICT_READ_WRITE模式不是“ 直 寫式”緩存策略,因為緩存條目無效,而不是被更新。 緩存無效化與當(dāng)前數(shù)據(jù)庫事務(wù)不同步。 即使關(guān)聯(lián)的Cache區(qū)域條目兩次無效(在事務(wù)完成之前和之后),當(dāng)緩存和數(shù)據(jù)庫可能分開時,仍然還有一個很小的時間窗口。
以下測試將演示此問題。 首先,我們將定義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); }); 愛麗絲加載存儲庫實體,并在她的第一個數(shù)據(jù)庫事務(wù)中對其進(jìn)行修改。
為了在Alice準(zhǔn)備提交時產(chǎn)生另一個并發(fā)事務(wù),我們將使用以下Hibernate Interceptor :
運行此代碼將生成以下輸出:
[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'}過時的數(shù)據(jù)與丟失的更新
當(dāng)數(shù)據(jù)庫和二級緩存可能不同步時, NONSTRICT_READ_WRITE并發(fā)策略會引入一個很小的不一致窗口。 盡管這聽起來可能很糟糕,但實際上,即使我們不使用二級緩存,也應(yīng)始終設(shè)計應(yīng)用程序來應(yīng)對這些情況。 Hibernate通過其事務(wù)性的后寫式第一級緩存提供應(yīng)用程序級可重復(fù)讀取,并且所有托管實體都將變得過時。 在將實體加載到當(dāng)前的持久性上下文中之后 ,另一個并發(fā)事務(wù)可能會對其進(jìn)行更新,因此,我們需要防止陳舊的數(shù)據(jù)升級為丟失的更新 。
樂觀并發(fā)控制是處理長時間對話中丟失的更新的有效方法,并且該技術(shù)還可以緩解NONSTRICT_READ_WRITE不一致問題。
結(jié)論
NONSTRICT_READ_WRITE并發(fā)策略是大多數(shù)只讀應(yīng)用程序的不錯選擇(如果由樂觀鎖定機(jī)制支持)。 對于寫密集型方案,緩存無效機(jī)制將增加緩存未命中率 ,因此使該技術(shù)效率低下。
- 代碼可在GitHub上獲得 。
翻譯自: https://www.javacodegeeks.com/2015/05/how-does-hibernate-nonstrict_read_write-cacheconcurrencystrategy-work.html
總結(jié)
以上是生活随笔為你收集整理的休眠NONSTRICT_READ_WRITE CacheConcurrencyStrategy如何工作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 揭秘5位爬藤“牛娃” 他们吸引藤校的到底
- 下一篇: 通俗理解DDPM:生成扩散模型