首頁 Java java教程 高並發場景下,到底先更新快取還是先更新資料庫?

高並發場景下,到底先更新快取還是先更新資料庫?

Jul 26, 2023 pm 02:53 PM
高並發場景

高並發場景下,到底先更新快取還是先更新資料庫?


#在大型系統中,為了減少資料庫壓力通常會引入快取機制,一旦引入快取又很容易造成快取和資料庫資料不一致,導致使用者看到的是舊資料。

為了減少資料不一致的情況,更新快取和資料庫的機制顯得特別重要,接下來帶領大家踩到坑。

高並發場景下,到底先更新快取還是先更新資料庫?

Cache aside

#Cache aside也就是旁路快取,是比較常用的快取策略。

(1)讀取請求常見流程

高並發場景下,到底先更新快取還是先更新資料庫?
Cache aside 讀取請求

應用程式首先會判斷快取是否有該數據,快取命中直接返回數據,快取未命中即快取穿透到資料庫,從資料庫查詢資料然後回寫到快取中,最後返回資料給客戶端。

(2)寫入請求常見流程

高並發場景下,到底先更新快取還是先更新資料庫?
#Cache aside 寫入請求

Cache aside 寫入請求

首先更新資料庫,然後從快取中刪除該資料。

看了寫請求的圖表之後,有些同學可能要問了:為什麼要刪除緩存,直接更新不就行了?這裡涉及到幾個坑,我們一步一步地踩下去。

Cache aside踩坑

Cache aside策略如果用錯就會遇到深坑,下面我們來逐一踩。
高並發場景下,到底先更新快取還是先更新資料庫?
踩坑一:先更新資料庫,再更新快取

如果同時有兩個

寫入請求

需要更新數據,每個寫入請求都先更新資料庫再更新緩存,在並發場景可能會出現資料不一致的情況。

先更新資料庫,再更新快取

如上圖的執行過程:######(1)###寫入請求1# ##更新資料庫,將age 欄位更新為18;######(2)###寫入請求2###更新資料庫,將age 欄位更新為20;###

(3)寫入請求2更新緩存,快取age 設定為20;

#(4)寫入請求1更新緩存,快取age 設定為18 ;

執行完預期結果是資料庫age 為20,快取age 為20,結果快取age為18,這就造成了快取資料不是最新的,出現了髒資料。

踩坑二:先刪緩存,再更新資料庫

如果寫入請求的處理流程是先刪快取再更新資料庫,在一個讀取請求和一個寫入請求並發場景下可能會出現資料不一致情況。

高並發場景下,到底先更新快取還是先更新資料庫?
先刪緩存,再更新資料庫

如上圖的執行過程:

(1)寫入請求刪除快取資料;

(2)讀取請求查詢快取未擊中(Hit Miss),緊接著查詢資料庫,將傳回的資料回寫到快取中;

(3)寫入請求更新資料庫。

整個流程下來發現資料庫中age為20,快取中age為18,快取和資料庫資料不一致,快取出現了髒資料。

踩坑三:先更新資料庫,再刪除快取

在實際的系統中針對寫入請求還是推薦先更新資料庫再刪除快取,但是在理論上還是有問題,以下面這個範例說明。

高並發場景下,到底先更新快取還是先更新資料庫?
先更新資料庫,再刪除快取

如上圖的執行過程:

(1)讀取請求先查詢緩存,快取未擊中,查詢資料庫返回資料;

(2)寫入請求更新資料庫,刪除快取;

(3)讀取請求回寫快取;

整個流程操作下來發現資料庫age為20快取age為18,即資料庫與快取不一致,導致應用程式從快取中讀到的資料都是舊資料。

但我們仔細想一下,上述問題發生的機率其實非常低,因為通常資料庫更新操作比記憶體操作耗時多出幾個數量級,上圖中最後一步回寫快取(set age 18)速度非常快,通常會在更新資料庫之前完成。

如果這種極端場景出現了怎麼辦?我們得想一個兜底的辦法:快取資料設定過期時間。通常在系統中是可以允許少量的資料短時間不一致的場景出現。

Read through

在 Cache Aside 更新模式中,應用程式碼需要維護兩個資料來源:一個是緩存,一個是資料庫。而在 Read-Through 政策下,應用程式無需管理快取和資料庫,只需要將資料庫的同步委託給快取提供者 Cache Provider 即可。所有資料互動都是透過抽象的快取層完成。

高並發場景下,到底先更新快取還是先更新資料庫?
Read-Through流程

如上圖,應用程式只需要與Cache Provider交互,不用關心是從緩存取還是資料庫.

在進行大量讀取時,Read-Through 可以減少資料來源上的負載,也對快取服務的故障具備一定的彈性。如果快取服務掛了,則快取提供者仍然可以透過直接轉到資料來源來進行操作。

Read-Through 適用於多次要求相同資料的場景,這與 Cache-Aside 策略非常相似,但是二者還是存在一些差別,這裡再次強調一下:

  • 在 Cache-Aside 中,應用程式負責從資料來源取得資料並更新到快取。
  • 在 Read-Through 中,此邏輯通常由獨立的快取提供者(Cache Provider)支援。

Write through

Write-Through 策略下,當發生資料更新(Write)時,快取提供程序Cache Provider 負責更新底層資料來源和快取。

快取與資料來源保持一致,並且寫入時始終透過抽象快取層到達資料來源。

Cache Provider類似一個代理人的作用。

高並發場景下,到底先更新快取還是先更新資料庫?
Write-Through流程

#Write behind

Write behind在某些地方也被成為Write back, 簡單理解就是:應用程式更新資料時只更新緩存, Cache Provider每隔一段時間將資料刷新到資料庫中。說穿了就是延遲寫入

高並發場景下,到底先更新快取還是先更新資料庫?
Write behind流程

如上圖,應用程式更新兩個數據,Cache Provider 會立即寫入快取中,但是隔一段時間才會批次寫入資料庫中。

這種方式有優點也有缺點:

  • #優點是資料寫入速度非常快,適用於頻繁寫的場景。

  • 缺點是快取和資料庫不是強一致性,對一致性要求高的系統慎用。

總結一下

學了這麼多,相信大家對快取更新的策略都已經有了清晰的認識。最後稍稍總結一下。

快取更新的策略主要分為三種:

  • Cache aside
  • Read/Write through
  • Write behind

Cache aside 通常會先更新資料庫,然後刪除緩存,為了兜底通常也會將資料設定快取時間。

Read/Write through 一般是由一個 Cache Provider 對外提供讀寫操作,應用程式不用感知操作的是快取還是資料庫。

Write behind簡單理解就是延遲寫入,Cache Provider 每隔一段時間就會批次輸入資料庫,優點是應用程式寫入速度非常快。

好了,今天先到這裡了,大家學會了嗎?

#############

以上是高並發場景下,到底先更新快取還是先更新資料庫?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? 使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...

See all articles