Hibernate二级缓存
因為項目中經常出現,由于使用了hibernate生成的方法,會從二級緩存中拿取數據,導致數據不一致的問題,甚至導致出現臟數據的問題,所以總結以下hibernate的緩存機制。
什么是二級緩存
我們知道一級緩存,并且一級緩存的作用范圍就在session中,每個session都有一個自己的一級緩存,而二級緩存也就是比一級緩存的作用范圍更廣,存儲的內容更多,我們知道session是由sesssionFactory創建出來的,一個sessionFactory能夠創建很多個session,每個session有自己的緩存,稱為一級緩存,而sessionFactory也有自己的緩存,存放的內容供所有session共享,也就是二級緩存。?
一級緩存:保存session中,事務范圍的緩存(通俗點講,就是session關閉后,該緩存就沒了,其緩存只能在session的事務開啟和結束之間使用)
二級緩存:保存在SessionFactory,進程范圍內的緩存(進程包括了多個線程,也就是我們上面說的意思,A線程可能拿到一個session進行操作,B線程也可能拿到一個session進行操作,但是A和B讀能訪問到SessionFactory中的緩存,也就是二級緩存,這里只是拿A,B說事,可能有一個線程剛創建出來session,也能拿到二級緩存中的數據)
hql做的查詢能夠存入一級緩存和二級緩存,但是不能夠從二級緩存中拿數據
get\load能夠將其查詢數據插入一級緩存和二級緩存,也能夠從一級二級緩存中拿數據。
例如:
我們有一個Order對象,是一個實體對象,對應數據庫中order表中的一條記錄,經過查詢已有n個Order對象被放入二級緩存中。現在我們要修改order表中任意任x條記錄,執行以下HQL:
template.bulkUpdate("update Order set owner = ? where id in (?,?,?)");
?這時Hibernate會直接將二級緩存中的n個Order對象清除掉。 天啊,居然不是你想像的修改誰就同步更新二級緩存中的誰,而是清除了二級緩存中全部的Order類型的對象。為什么?這一切是為了保證“數據一致性”。你執行了HQL修改了order表中的x條記錄,這x條是哪幾條?如果sql是子查詢:update Order set owner =? where id in(select id from *** ),誰知道你修改了order表中的哪幾條記錄,你自己都不知道,Hibernate更不知道了。所以為了保證二級緩存中的數據與order表中的數據一致,只能清除了二級緩存中全部的Order類型的對象。二級緩存頻繁的載入與清除,這樣緩存命中率就會下降。
二級緩存的更新機制
存放了對于查詢結果相關的表進行插入,更新,刪除操作的時間戳,Hibernate通過時間戳緩存區域來判斷被緩存的查詢結果是否過期,如果過期了則從數據庫中拿數據,沒過期則直接從緩存中拿數據。通俗點講,就三步
1、查詢結果放到二級緩存中,此時記錄一個時間為T1
2、當有操作直接更改了數據庫的數據時,比如使用hql語句,就會直接對數據庫進行修改,而不會改變緩存中的數據。此時記錄時間為T2
3、當下次在查詢記錄時,會先將T1和T2進行比較,如果T2>T1,則說明緩存中的數據不是最新的,那么就從數據庫中拿出正確的數據,如果T2<T1,就說明沒有對數據庫進行過什么修改操作,那么就可以直接從緩存中獲取數據。
解惑:如果沒有T1和T2的比較,那么會出現我們查詢到的數據不是準確的,因為就像上面第二步所說的,數據庫的數據會和緩存中的數據不一樣,什么都不做就從緩存中拿數據,就會出現錯誤。
這里需要注意:如果你用了update語句,那么二級緩存無法更新。因為系統無法判斷二級緩存的對象哪些失效了。如果你是update(對象)的方式更新,則系統可以通過ID確認哪個二級緩存對象需要更新,系統能夠維護二級緩存。
項目中出現的緩存問題分析
由于項目的beta和prod環境是有多臺server集群的,所以如果在某些對數據一致性要求較高的地方使用了二級緩存(也就是從緩存中取數據,不是直接從db中查取數據),就會出現數據一致性問題。
原因:由于server的elb機制是粘性session,那么就可能出現用戶A和admin連上了兩臺不同的server,并且所有的db操作都是在不同的server上進行的,這時候如果admin更新的用戶A的狀態信息,只會刷新admin所連接server的二級緩存,并不會刷新其他server的緩存,而用戶A并不能及時獲取到db的更新,如果所有的地方都是從二級緩存中取數據就還好,只會出現延時的問題,這種可能性比較小。但如果不是全部都從二級緩存中取數據,那用戶A就會出現數據不一致問題,甚至導致頁面掛掉。
上面這種情況當清楚的db的catch之后就可以恢復正常,但還有一種更嚴重的情況,如果用戶A從緩存中獲取的和db不一致的數據,并做的相應的更新操作,那么就會直接導致數據庫出現臟數據,直接導致這個用戶出現問題。
所以hibernate需要慎用,在更新較為頻繁或者對數據一致性較高的地方不要使用二級緩存,否則會得不償失。
?
?
?
總結
以上是生活随笔為你收集整理的Hibernate二级缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 评价——秩和比综合评价
- 下一篇: 辽宁省计算机考研排名,2014辽宁省大学