對於互聯網業務來說,傳統的直接訪問資料庫方式,主要通過數據分片、一主多從等方式來扛住讀寫流量,但隨著數據量的積累和流量的激增,僅依賴資料庫來承接所有流量,不僅成本高、效率低、而且還伴隨著穩定性降低的風險。
鑒於大部分業務通常是讀多寫少(讀取頻率遠遠高於更新頻率),甚至存在讀操作數量高出寫操作多個數量級的情況。因此, 在架構設計中,常採用增加緩存層來提高系統的響應能力 ,提升數據讀寫性能、減少資料庫訪問壓力,從而提升業務的穩定性和訪問體驗。
根據 CAP 原理,分布式系統在可用性、一致性和分區容錯性上無法兼得,通常由於分區容錯無法避免,所以一致性和可用性難以同時成立。對於緩存系統來說, 如何保證其數據一致性是一個在應用緩存的同時不得不解決的問題 。
需要明確的是,緩存系統的數據一致性通常包括持久化層和緩存層的一致性、以及多級緩存之間的一致性,這里我們僅討論前者。持久化層和緩存層的一致性問題也通常被稱為雙寫一致性問題,「雙寫」意為數據既在資料庫中保存一份,也在緩存中保存一份。
對於一致性來說,包含強一致性和弱一致性 ,強一致性保證寫入後立即可以讀取,弱一致性則不保證立即可以讀取寫入後的值,而是盡可能的保證在經過一定時間後可以讀取到,在弱一致性中應用最為廣泛的模型則是最終一致性模型,即保證在一定時間之後寫入和讀取達到一致的狀態。對於應用緩存的大部分場景來說,追求的則是最終一致性,少部分對數據一致性要求極高的場景則會追求強一致性。
為了達到最終一致性,針對不同的場景,業界逐步形成了下面這幾種應用緩存的策略。
— 1 —
Cache-Aside
Cache-Aside 意為旁路緩存模式,是應用最為廣泛的一種緩存策略。下面的圖示展示了它的讀寫流程,來看看它是如何保證最終一致性的。在讀請求中,首先請求緩存,若緩存命中(cache hit),則直接返回緩存中的數據;若緩存未命中(cache miss),則查詢資料庫並將查詢結果更新至緩存,然後返回查詢出的數據(demand-filled look-aside )。在寫請求中,先更新資料庫,再刪除緩存(write-invalidate)。
1、為什麼刪除緩存,而不是更新緩存?
在 Cache-Aside 中,對於讀請求的處理比較容易理解,但在寫請求中,可能會有讀者提出疑問,為什麼要刪除緩存,而不是更新緩存?站在符合直覺的角度來看,更新緩存是一個容易被理解的方案,但站在性能和安全的角度,更新緩存則可能會導致一些不好的後果。
首先是性能 ,當該緩存對應的結果需要消耗大量的計算過程才能得到時,比如需要訪問多張資料庫表並聯合計算,那麼在寫操作中更新緩存的動作將會是一筆不小的開銷。同時,當寫操作較多時,可能也會存在剛更新的緩存還沒有被讀取到,又再次被更新的情況(這常被稱為緩存擾動),顯然,這樣的更新是白白消耗機器性能的,會導致緩存利用率不高。
而等到讀請求未命中緩存時再去更新,也符合懶載入的思路,需要時再進行計算。刪除緩存的操作不僅是冪等的,可以在發生異常時重試,而且寫-刪除和讀-更新在語義上更加對稱。
其次是安全 ,在並發場景下,在寫請求中更新緩存可能會引發數據的不一致問題。參考下面的圖示,若存在兩個來自不同線程的寫請求,首先來自線程 1 的寫請求更新了資料庫(step 1),接著來自線程 2 的寫請求再次更新了資料庫(step 3),但由於網路延遲等原因,線程 1 可能會晚於線程 2 更新緩存(step 4 晚於 step 3),那麼這樣便會導致最終寫入資料庫的結果是來自線程 2 的新值,寫入緩存的結果是來自線程 1 的舊值,即緩存落後於資料庫,此時再有讀請求命中緩存(step 5),讀取到的便是舊值。
2、為什麼先更新資料庫,而不是先刪除緩存?
另外,有讀者也會對更新資料庫和刪除緩存的時序產生疑問,那麼為什麼不先刪除緩存,再更新資料庫呢?在單線程下,這種方案看似具有一定合理性,這種合理性體現在刪除緩存成功。
但更新資料庫失敗的場景下,盡管緩存被刪除了,下次讀操作時,仍能將正確的數據寫回緩存,相對於 Cache-Aside 中更新資料庫成功,刪除緩存失敗的場景來說,先刪除緩存的方案似乎更合理一些。那麼,先刪除緩存有什麼問題呢?
問題仍然出現在並發場景下,首先來自線程 1 的寫請求刪除了緩存(step 1),接著來自線程 2 的讀請求由於緩存的刪除導致緩存未命中,根據 Cache-Aside 模式,線程 2 繼而查詢資料庫(step 2),但由於寫請求通常慢於讀請求,線程 1 更新資料庫的操作可能會晚於線程 2 查詢資料庫後更新緩存的操作(step 4 晚於 step 3),那麼這樣便會導致最終寫入緩存的結果是來自線程 2 中查詢到的舊值,而寫入資料庫的結果是來自線程 1 的新值,即緩存落後於資料庫,此時再有讀請求命中緩存( step 5 ),讀取到的便是舊值。
另外,先刪除緩存,由於緩存中數據缺失,加劇資料庫的請求壓力,可能會增大緩存穿透出現的概率。
3、如果選擇先刪除緩存,再更新資料庫,那如何解決一致性問題呢?
為了避免「先刪除緩存,再更新資料庫」這一方案在讀寫並發時可能帶來的緩存臟數據,業界又提出了延時雙刪的策略,即在更新資料庫之後,延遲一段時間再次刪除緩存,為了保證第二次刪除緩存的時間點在讀請求更新緩存之後,這個延遲時間的經驗值通常應稍大於業務中讀請求的耗時。
延遲的實現可以在代碼中 sleep 或採用延遲隊列。顯而易見的是,無論這個值如何預估,都很難和讀請求的完成時間點准確銜接,這也是延時雙刪被詬病的主要原因。
4、那麼 Cache-Aside 存在數據不一致的可能嗎?
在 Cache-Aside 中,也存在數據不一致的可能性。在下面的讀寫並發場景下,首先來自線程 1 的讀請求在未命中緩存的情況下查詢資料庫(step 1),接著來自線程 2 的寫請求更新資料庫(step 2),但由於一些極端原因,線程 1 中讀請求的更新緩存操作晚於線程 2 中寫請求的刪除緩存的操作(step 4 晚於 step 3),那麼這樣便會導致最終寫入緩存中的是來自線程 1 的舊值,而寫入資料庫中的是來自線程 2 的新值,即緩存落後於資料庫,此時再有讀請求命中緩存(step 5),讀取到的便是舊值。
這種場景的出現,不僅需要緩存失效且讀寫並發執行,而且還需要讀請求查詢資料庫的執行早於寫請求更新資料庫,同時讀請求的執行完成晚於寫請求。足以見得,這種 不一致場景產生的條件非常嚴格,在實際的生產中出現的可能性較小 。
除此之外,在並發環境下,Cache-Aside 中也存在讀請求命中緩存的時間點在寫請求更新資料庫之後,刪除緩存之前,這樣也會導致讀請求查詢到的緩存落後於資料庫的情況。
雖然在下一次讀請求中,緩存會被更新,但如果業務層面對這種情況的容忍度較低,那麼可以採用加鎖在寫請求中保證「更新資料庫&刪除緩存」的串列執行為原子性操作(同理也可對讀請求中緩存的更新加鎖)。 加鎖勢必會導致吞吐量的下降,故採取加鎖的方案應該對性能的損耗有所預期。
— 2 —
補償機制
我們在上面提到了,在 Cache-Aside 中可能存在更新資料庫成功,但刪除緩存失敗的場景,如果發生這種情況,那麼便會導致緩存中的數據落後於資料庫,產生數據的不一致的問題。
其實,不僅 Cache-Aside 存在這樣的問題,在延時雙刪等策略中也存在這樣的問題。針對可能出現的刪除失敗問題,目前業界主要有以下幾種補償機制。
1、刪除重試機制
由於同步重試刪除在性能上會影響吞吐量,所以常通過引入消息隊列,將刪除失敗的緩存對應的 key 放入消息隊列中,在對應的消費者中獲取刪除失敗的 key ,非同步重試刪除。這種方法在實現上相對簡單,但由於刪除失敗後的邏輯需要基於業務代碼的 trigger 來觸發 ,對業務代碼具有一定入侵性。
鑒於上述方案對業務代碼具有一定入侵性,所以需要一種更加優雅的解決方案,讓緩存刪除失敗的補償機制運行在背後,盡量少的耦合於業務代碼。一個簡單的思路是通過後台任務使用更新時間戳或者版本作為對比獲取資料庫的增量數據更新至緩存中,這種方式在小規模數據的場景可以起到一定作用,但其擴展性、穩定性都有所欠缺。
一個相對成熟的方案是基於 MySQL 資料庫增量日誌進行解析和消費,這里較為流行的是阿里巴巴開源的作為 MySQL binlog 增量獲取和解析的組件 canal(類似的開源組件還有 Maxwell、Databus 等)。
canal sever 模擬 MySQL slave 的交互協議,偽裝為 MySQL slave,向 MySQL master 發送 mp 協議,MySQL master 收到 mp 請求,開始推送 binary log 給 slave (即 canal sever ),canal sever 解析 binary log 對象(原始為 byte 流),可由 canal client 拉取進行消費,同時 canal server 也默認支持將變更記錄投遞到 MQ 系統中,主動推送給其他系統進行消費。
在 ack 機制的加持下,不管是推送還是拉取,都可以有效的保證數據按照預期被消費。當前版本的 canal 支持的 MQ 有 Kafka 或者 RocketMQ。另外, canal 依賴 ZooKeeper 作為分布式協調組件來實現 HA ,canal 的 HA 分為兩個部分:
那麼,針對緩存的刪除操作便可以在 canal client 或 consumer 中編寫相關業務代碼來完成。這樣,結合資料庫日誌增量解析消費的方案以及 Cache-Aside 模型,在讀請求中未命中緩存時更新緩存(通常這里會涉及到復雜的業務邏輯),在寫請求更新資料庫後刪除緩存,並基於日誌增量解析來補償資料庫更新時可能的緩存刪除失敗問題,在絕大多數場景下,可以有效的保證緩存的最終一致性。
另外需要注意的是,還應該隔離事務與緩存,確保資料庫入庫後再進行緩存的刪除操作。 比如考慮到資料庫的主從架構,主從同步及讀從寫主的場景下,可能會造成讀取到從庫的舊數據後便更新了緩存,導致緩存落後於資料庫的問題,這就要求對緩存的刪除應該確保在資料庫操作完成之後。所以,基於 binlog 增量日誌進行數據同步的方案,可以通過選擇解析從節點的 binlog,來避免主從同步下刪除緩存過早的問題。
3、數據傳輸服務 DTS
— 3 —
Read-Through
Read-Through 意為讀穿透模式,它的流程和 Cache-Aside 類似,不同點在於 Read-Through 中多了一個訪問控制層,讀請求只和該訪問控制層進行交互,而背後緩存命中與否的邏輯則由訪問控制層與數據源進行交互,業務層的實現會更加簡潔,並且對於緩存層及持久化層交互的封裝程度更高,更易於移植。
— 4 —
Write-Through
Write-Through 意為直寫模式,對於 Write-Through 直寫模式來說,它也增加了訪問控制層來提供更高程度的封裝。不同於 Cache-Aside 的是,Write-Through 直寫模式在寫請求更新資料庫之後,並不會刪除緩存,而是更新緩存。
這種方式的 優勢在於讀請求過程簡單 ,不需要查詢資料庫更新緩存等操作。但其劣勢也非常明顯,除了上面我們提到的更新資料庫再更新緩存的弊端之外,這種方案還會造成更新效率低,並且兩個寫操作任何一次寫失敗都會造成數據不一致。
如果要使用這種方案, 最好可以將這兩個操作作為事務處理,可以同時失敗或者同時成功,支持回滾,並且防止並發環境下的不一致 。另外,為了防止緩存擾動的頻發,也可以給緩存增加 TTL 來緩解。
站在可行性的角度,不管是 Write-Through 模式還是 Cache-Aside 模式,理想狀況下都可以通過分布式事務保證緩存層數據與持久化層數據的一致性,但在實際項目中,大多都對一致性的要求存在一些寬容度,所以在方案上往往有所折衷。
Write-Through 直寫模式適合寫操作較多,並且對一致性要求較高的場景,在應用 Write-Through 模式時,也需要通過一定的補償機制來解決它的問題。首先,在並發環境下,我們前面提到了先更新資料庫,再更新緩存會導致緩存和資料庫的不一致,那麼先更新緩存,再更新資料庫呢?
這樣的操作時序仍然會導致下面這樣線程 1 先更新緩存,最後更新資料庫的情況,即由於線程 1 和 線程 2 的執行不確定性導致資料庫和緩存的不一致。這種由於線程競爭導致的緩存不一致,可以通過分布式鎖解決,保證對緩存和資料庫的操作僅能由同一個線程完成。對於沒有拿到鎖的線程,一是通過鎖的 timeout 時間進行控制,二是將請求暫存在消息隊列中順序消費。
在下面這種並發執行場景下,來自線程 1 的寫請求更新了資料庫,接著來自線程 2 的讀請求命中緩存,接著線程 1 才更新緩存,這樣便會導致線程 2 讀取到的緩存落後於資料庫。同理,先更新緩存後更新資料庫在寫請求和讀請求並發時,也會出現類似的問題。面對這種場景,我們也可以加鎖解決。
另在,在 Write-Through 模式下,不管是先更新緩存還是先更新資料庫,都存在更新緩存或者更新資料庫失敗的情況,上面提到的重試機制和補償機制在這里也是奏效的。
— 5 —
Write-Behind
Write behind 意為非同步回寫模式,它也具有類似 Read-Through/Write-Through 的訪問控制層,不同的是,Write behind 在處理寫請求時,只更新緩存而不更新資料庫,對於資料庫的更新,則是通過批量非同步更新的方式進行的,批量寫入的時間點可以選在資料庫負載較低的時間進行。
在 Write-Behind 模式下,寫請求延遲較低,減輕了資料庫的壓力,具有較好的吞吐性。但資料庫和緩存的一致性較弱,比如當更新的數據還未被寫入資料庫時,直接從資料庫中查詢數據是落後於緩存的。同時,緩存的負載較大,如果緩存宕機會導致數據丟失,所以需要做好緩存的高可用。顯然,Write behind 模式下適合大量寫操作的場景,常用於電商秒殺場景中庫存的扣減。
— 6 —
Write-Around
如果一些非核心業務,對一致性的要求較弱,可以選擇在 cache aside 讀模式下增加一個緩存過期時間,在寫請求中僅僅更新資料庫,不做任何刪除或更新緩存的操作,這樣,緩存僅能通過過期時間失效。這種方案實現簡單,但緩存中的數據和資料庫數據一致性較差,往往會造成用戶的體驗較差,應慎重選擇。
— 7 —
總結
在解決緩存一致性的過程中,有多種途徑可以保證緩存的最終一致性,應該根據場景來設計合適的方案,讀多寫少的場景下,可以選擇採用「Cache-Aside 結合消費資料庫日誌做補償」的方案,寫多的場景下,可以選擇採用「Write-Through 結合分布式鎖」的方案 ,寫多的極端場景下,可以選擇採用「Write-Behind」的方案。
❷ SpringCache優化、緩存一致性、多級緩存
先記錄一些綱要
1、SpringCache是寫庫之後更新的策略,對緩存一致性的不太友好
2、繼承RedisCacheManager重寫createRedisCache,繼承RedisCache重寫put
3、緩存一致性有兩個方案,一個是先寫庫再刪除緩存、第二個是先刪除緩存再寫庫。
先寫庫再刪除緩存配合超時時間一般沒啥問題,極端的情況遇到緩存失效,線程讀庫和加緩存之間,完成了一次寫庫和刪緩存的操作,導致加的緩存是舊的。總結就是讀中加入了一次寫。A讀庫 B寫庫 B刪緩存 A加緩存。
先刪緩存再寫庫的話,是寫中加入了一次讀。A刪緩存 B讀庫 B加緩存 A寫庫A。這個概率比上面的大。
這兩種方案的問題的解決方式是一樣的,就是延時雙刪策略。即:
刪緩存 寫庫 延時再次刪除緩存(需超過一次讀庫的時間,可以新啟線程完成)
或者 寫庫 刪緩存 延時再次刪除緩存(需超過一次讀庫的時間,可以新啟線程完成)
如果有主從讀寫分離,需要將延時再加上主從同步的時間。
還有個第二次刪除失敗的問題,這個問題可以通過消息中間件,反復嘗試進行。或者通過訂閱binlog,反復進行。
多級緩存可以參考阿里開源的JetCache的實現
後面會給出demo和源碼解析。
❸ 瀏覽器緩存機制簡單概括和分析
對於訪問的頁面和請求,為了縮短網頁請求資源的距離,減少延遲,並且由於緩存文件可以重復利用,還可以減少帶寬,降低網路負荷,瀏覽器和伺服器都有可能會對請求資源進行緩存,接下來的文章就簡單介紹和分析瀏覽器的緩存機制。
深入理解瀏覽器的緩存機制: https://www.jianshu.com/p/54cc04190252
這篇文章已經有詳細的講解,這里就概括一下:
以首頁的請求為例:
1、強制緩存策略(Expires和Cache-Control) :當瀏覽器發起http請求的時候,如果配置了緩存策略且緩存在有效期內,會直接使用瀏覽器緩存。 不使用強制緩存 ( Cache-Control=no-chache, 或者 max-age=0 )
(1)、圖中請求伺服器:是 max-age=0 的情況,瀏覽器直接請求伺服器資源,而不是用本地緩存
(2)、圖中磁碟緩存和內存緩存:就是瀏覽器使用了本地緩存而不再請求伺服器資源
2、協商緩存策略(Last-Modified和If-Modified-Since, ETag和If-None-Match): 當瀏覽器發起http請求的時候,如果 強制緩存策略 失效,或者者禁用了強制緩存,這時候會根據 If-Modified-Since 中的值與伺服器中這個資源的最後修改時間對比,如果沒有變化,返回304和空的響應體,直接從緩存讀取,如果If-Modified-Since的時間小於伺服器中這個資源的最後修改時間,說明文件有更新,於是返回新的資源文件和200。
不使用協商緩存 ( Cache-Control=no-store ),這個參數同時也會 禁用強制緩存。
(1)、伺服器資源返回無更新,瀏覽器使用上次請求的資源
(2)、伺服器資源有更新,返回200並返回最新的資源
3、不使用緩存策略(Cache-Control=no-store): 所有內容都不會被緩存,即不使用強制緩存,也不使用協商緩存。當response head 設置了no-store,瀏覽器不會對返回的資源做緩存,每次請求都是直接請求伺服器。這可以保證瀏覽器每次都能拿最新的資源,即使資源對比上次請求沒有任何更新,但同時也降低了頁面的響應速度,和增加了網路的IO與伺服器的壓力。
可以明顯的看到請求時間,請求伺服器資源時間 >> 請求磁碟緩存 > 請求內存緩存,所以合適的緩存策略,可以在不影響業務的情況下,極大地提升客戶體驗和後台伺服器壓力。
❹ 蘋果手機緩存慢
手機永久了,大量的垃圾文件導致手機越來越卡,iPhone也會有這種情況。那麼蘋果手機卡頓反應慢怎麼辦?如果手機非常卡頓的話不妨試試下面9招會讓iPhone運行速度提升不少
蘋果手機卡頓反應慢怎麼辦?
1、清空Safari緩存
經常使用 Safari 瀏覽網頁時間久了會產生大量緩存數據,需要清空Safari的緩存來保持它的運行流暢。想要執行這個操作,需要進入【設置】-【Safari】,然後點擊「清除歷史記錄」和「清除Cookies和數據」。
iPhone手機變卡變慢
2、關閉自動更新自動下載
如果iPhone在使用時出現卡頓,那可能是因為它正在後台嘗試應用升級,而這完全可以通過手動的方式執行。想要更改自動升級應用的設置,你需要進入【設置】-【iTunes Store和App Store】自動下載的項目,然後全部關閉。
運行飛速起來的方法
3、刪除舊的無用照片和視頻
刪除不必要的文件是加速手機運行速度的主要方式之一。如果iPhone當中存儲了幾百上千張照片以及很多的視頻,可以將它們備份到電腦或是iCloud,然後在手機當中刪除。畢竟手機內存空間有限,對於收藏照片來說,手機真不是一個好的地方。
刪除舊的無用照片和視頻
4、刪除佔用大量空間的應用
iPhone越是臃腫,運行速度也就越慢。可以在設置-通用-用量當中查看到每款應用的空間佔用,然後將那些佔用空間大但並不是必要的應用刪除。大量「僵屍」應用存在於手機上,只會拖累手機的運行速度,與其讓它放著佔用大量空間還不如刪了。
刪除佔用大量空間的應用
5、刪除舊的簡訊會話
大量的簡訊也是拖垮手機速度的原因之一,有時簡訊多了,打開信息應用時要卡一下等待一會才能進入。如果搞不清楚手機為什麼變卡,可以嘗試刪除手機當中那些無意義的垃圾簡訊。
刪除舊的簡訊會話
6、關閉後台不必要運行的應用
頻繁的關閉「後台」只會加快iPhone的耗電速度,但是對於一些平時不怎麼用的應用,完全可以雙擊home鍵關閉它,只保留常用的即可。像定位導航和音樂類應用是常駐內存的,沒用時最好關了。
關閉後台不必要運行的應用
7、能手動執行的操作就不要開啟自動模式
iPhone會經常詢問是否要加入附近的Wi-Fi網路嗎?如果是,或許應該關掉這個功能。因為當iPhone在進行任何自動操作時,比如搜索附近Wi-Fi或升級應用,都會降低運行速度。想要關閉該功能,需要進入【設置】-【無線區域網】-【詢問是否加入網路】,然後將其關閉。
能手動執行的操作就不要開啟自動模式
8、定期重啟手機
在使用iPhone時,大多數用戶都會一直保持著開機狀態,但定期重啟手機其實是很有必要的。關閉手機可以幫助iPhone擺脫那些一直在佔用系統資源的東西。
9、升級恢復系統
終極解決辦法:刷機恢復系統,讓系統恢復到剛出廠的狀態。如果越獄也不知道幹嘛還有就是不是非常必要建議還是別越獄了,越獄後安裝些插件手機會卡很多。
以上就是讓手機恢復神速的幾個小妙招啦,希望能對大家有幫助!
❺ 先刪後寫為何不能用延遲雙刪
先刪後寫會出現一致性的問題
在這里,我們討論三種更新策略:
先更新緩存,再更新資料庫
先更新資料庫,再更新緩存
先刪除緩存,再更新資料庫
先更新資料庫,再刪除緩存
- public void write(String key,Object data){
- redis.delKey(key);
- db.updateData(data);
- Thread.sleep(1000);
- redis.delKey(key);
- }
先刪緩存,將更新資料庫的操作放進有序隊列中
從緩存查不到的查詢操作,都進入有序隊列
讀請求積壓,大量超時,導致資料庫的壓力:限流、熔斷
如何避免大量請求積壓:將隊列水平拆分,提高並行度。
保證相同請求路由正確。
第一種,先更新緩存,再更新資料庫
問題:更新緩存成功,更新資料庫失敗,導致數據不一致。
第二種,先更新資料庫,再更新緩存
問題:
1、A更新資料庫
2、B更新資料庫
3、B寫入緩存
4、A寫入緩存
出現數據不一致。
考慮另一種情況, 有如下兩點:
(1)如果你是一個寫資料庫場景比較多,而讀數據場景比較少的業務需求,採用這種方案就會導致,數據壓根還沒讀到,緩存就被頻繁的更新,浪費性能。
(2)如果你寫入資料庫的值,並不是直接寫入緩存的,而是要經過一系列復雜的計算再寫入緩存。那麼,每次寫入資料庫後,都再次計算寫入緩存的值,無疑是浪費性能的。顯然,刪除緩存更為適合。
第三種,先刪除緩存,再更新資料庫。
問題:
1、A刪除緩存
2、B查詢資料庫獲取舊值
3、B更新了緩存
4、A更新資料庫
出現數據不一致的問題
延時雙刪
問題一:延時雙刪,演變成了:先更新資料庫,再刪除緩存。。。。
比如:
1、A刪除緩存
2、B查詢資料庫獲取舊值
3、B更新了緩存
4、A更新資料庫
5、A延時刪緩存
1~3步執行後,資料庫和緩存是一致的,相當於沒刪除。
4~5步:先更新資料庫,再刪緩存。
所以延時雙刪演變成了:先更新資料庫,再刪除緩存。問題還是沒解決。。。
為什麼?假設,此時,在第4步執行之前,又來了個查詢C,C查詢到舊值。第6步:C將舊值插入緩存。此時出現緩存和資料庫不一致。
延時並不能解決:C插入緩存的操作在第5步後面執行,比如C遇到網路問題、GC問題等。當然這是小概率,但並不代表不存在。
當然,延時越長,這個問題越能規避。如果業務需求不是非常嚴格,是可以忽略的。
問題二:吞吐量
問題三:資料庫更新後,無法保證下一次查詢,從緩存獲取的值和資料庫是一致的。
第四種,先更新資料庫,再刪除緩存
問題:上面C的查詢,已經說明問題了。
出現數據不一致的概率,比較小。採取這個方案,取決於業務需求。
終極方案
請求串列化
真正靠譜的方案:將訪問操作串列化
需要解決的問題:
❻ JAVA幾種緩存技術介紹說明
1、TreeCache / JBossCache
JBossCache是一個復制的事務處理緩存,它允許你緩存企業級應用數據來更好的改善性能。緩存數據被自動復制,讓你輕松進行JBoss伺服器之間 的集群工作。JBossCache能夠通過JBoss應用服務或其他J2EE容器來運行一個MBean服務,當然,它也能獨立運行。
2、WhirlyCache
Whirlycache是一個快速的、可配置的、存在於內存中的對象的緩存。它能夠通過緩存對象來加快網站或應用程序的速度,否則就必須通過查詢資料庫或其他代價較高的處理程序來建立。
3、SwarmCache
SwarmCache是一個簡單且有效的分布式緩存,它使用IP multicast與同一個區域網的其他主機進行通訊,是特別為集群和數據驅動web應用程序而設計的。SwarmCache能夠讓典型的讀操作大大超過寫操作的這類應用提供更好的性能支持。
4、JCache
JCache是個開源程序,正在努力成為JSR-107開源規范,JSR-107規范已經很多年沒改變了。這個版本仍然是構建在最初的功能定義上。
5、ShiftOne
ShiftOne Java Object Cache是一個執行一系列嚴格的對象緩存策略的Java lib,就像一個輕量級的配置緩存工作狀態的框架。