---
# System prepended metadata

title: 旁路缓存：Redis是如何工作的？

---

## 1) 為何要系統性學習 Redis 快取
- 由於 Redis **作為快取的普遍性**與其在業務應用中的重要性，我們需要**系統地**掌握：
  - **工作原理**
  - **替換策略**
  - **異常處理**
  - **擴展機制**
- 需要解決的四個關鍵問題：
  1. **Redis 快取具體是怎麼工作的？**
  2. **Redis 快取如果滿了，該怎麼辦？**
  3. **為什麼會有快取一致性、快取穿透、快取雪崩、快取擊穿等異常，該如何應對？**
  4. **Redis 記憶體有限；若使用快速固態硬碟保存資料以增加快取量，Redis 快取可以使用 SSD 嗎？**

---

## 2) 快取的特徵（為何需要、為何適合）
- **不同層級的存取速度不同**，因此需要快取：把**需要頻繁訪問的資料**放在**更快**的一層，以加速存取。  
- 以**電腦系統的三層儲存**做比喻：
  - **最上層：處理器（含暫存器 / CPU 快取）** → 速度最快、容量最小
  - **中間：主記憶體（RAM）** → 速度中等、容量中等
  - **最下層：磁碟（SSD/HDD）** → 速度最慢、容量最大
- 由上而下：**速度遞減、容量遞增**。快取的核心思路：**用小而快的層緩衝大而慢的層**。

> 圖示（文字示意）：  
> 處理器（快・小） → 記憶體（中） → 磁碟（慢・大）
![截圖 2025-08-13 晚上9.08.45](https://hackmd.io/_uploads/HJYwR-5_ee.png)

---

## 3) 系統中的兩種預設快取
- **CPU 末級快取（LLC）**：快取「記憶體中的資料」，避免每次都從記憶體讀寫。
- **記憶體中的頁面快取（page cache）**：快取「磁碟中的資料」，避免每次都從磁碟讀寫。

---
## 4) 速度關係
- 與記憶體相比：**LLC 更快**。
- 與磁碟相比：**記憶體更快**。
---
## 5) 快取的第一個特徵
在**層次化系統**中，**快取一定是較快的子系統**。當資料存在快取中時，能避免每次都從**較慢的子系統**讀寫。

---


# Redis 快取處理請求的兩種情況
![截圖 2025-08-14 上午10.02.56](https://hackmd.io/_uploads/H1hA7a5dlg.png)

## 1) 部署與讀取順序
- 將 Redis 作為快取時，會**部署在資料庫的前端**。
- 業務應用在讀取資料時，會**先查詢 Redis** 是否已有對應資料。

## 2) 兩種情況
- **快取命中**：Redis 中**有相應資料**，直接讀取 Redis，**效能非常快**。
- **快取缺失**：Redis 中**沒有相應資料**，需要從**後端資料庫**讀取，**效能較慢**。

## 3) 缺失後的快取更新
- 一旦發生快取缺失，為了讓**後續請求**能直接從快取讀取，需要將**缺失的資料寫入 Redis**，此過程稱為**快取更新**。
- 快取更新會牽涉到**快取與資料庫之間的一致性**問題（將在第 25 講中介紹）。
![截圖 2025-08-13 晚上9.17.09](https://hackmd.io/_uploads/rJbDlz9Oel.png)

## 4) 三個基本操作
使用 Redis 作為快取時，基本包含三件事：
1. 應用在讀取資料時，**需要先讀取 Redis**。
2. 發生快取缺失時，**需要從資料庫讀取資料**。
3. 發生快取缺失時，**還需要更新快取**（將缺失的資料寫入 Redis 以供後續讀取）。

# Redis 作為旁路快取的使用操作

## 1) 為何稱為「旁路快取」
- **Redis 與業務應用是兩個獨立軟體**；部署 Redis 後，它**被動等待**客戶端請求再處理。  
- 若應用要使用 Redis 快取，必須在程式中**新增快取操作的程式碼**。  
- 因此，「讀取快取、讀取資料庫、更新快取」**都在應用程式內完成**，這與硬體層面的快取不同。

## 2) 與 LLC / page cache 的差異
- 平時開發程式時，**不會顯式建立 LLC 或 page cache 的實例**，也**不會顯式呼叫它們的 GET 介面**。  
- 這是因為在硬體系統建構時，**LLC 與 page cache 已置於資料存取路徑上**，應用程式**直接就能用到**。  
- **Redis 則不同**：要用就必須**在應用程式中顯式呼叫其 API**。

## 3) 需要新增的三類程式碼
1. 當應用需讀取資料時：**顯式呼叫 Redis 的 GET** 查詢。  
2. 若發生快取缺失：**再與資料庫連線**，自資料庫讀取資料。  
3. 當快取中的資料需要更新時：**顯式呼叫 SET**，把更新後的資料寫入快取。

## 4) 適用性與限制
- 因為需要新增程式碼來使用快取，**不適用於無法取得原始碼的應用**：  
  - 很早之前開發、已不再維護的程式；  
  - 第三方供應商開發且未提供原始碼的應用。  
- 使用旁路快取會**增加額外工作量**，但也因 Redis 是獨立系統，**可單獨對其擴容或做效能優化**。  
- 只要**操作介面不變**，**應用中新增的程式碼就無需再修改**。

## 5) 快取型別的引入
- 除了從 Redis 查詢/讀取，**應用也可能修改資料**：可在快取中修改，或在後端資料庫中修改。  
- 這引出兩種快取型別：  
  - **只讀快取**：能加速讀取請求；  
  - **讀寫快取**：可同時加速讀與寫。  
- 且**讀寫快取**有**兩種資料寫回策略**，可根據業務需求在**效能**與**資料可靠性**間做選擇。

# 快取的類型：只讀快取與讀寫快取

## 1) 類型劃分
- 依據 Redis 快取是否接受**寫請求**，可分為：**只讀快取**與**讀寫快取**。

## 2) 只讀快取
- **讀取**：應用程式先呼叫 **Redis 的 GET** 介面查詢是否存在；命中則直接從快取讀取。  
- **寫入 / 刪改**：所有**寫請求**直接發往**後端資料庫**（在資料庫中增刪改）。  
- **與快取的配合**：對於已被 Redis 快取的資料，當在資料庫中刪改後，應用需**刪除 Redis 中對應的快取**；
  再次讀取該資料時會發生**快取缺失**，應用自資料庫讀出並**寫回 Redis**，以便後續可直接從快取讀取。
- **例子（資料 A）**：
  1. 業務要修改 **A**，且 **A** 在 Redis 中已被快取；  
  2. 應用先在**資料庫**修改 **A**，並**刪除 Redis 中的 A**；  
  3. 之後讀取 **A** 時發生**快取缺失**，應用自資料庫讀取 **A** 並**寫入 Redis**；  
  4. 後續請求可**直接從快取**讀取 **A**。  
- **特點**：最新資料都在**資料庫**，由資料庫提供**可靠性保障**，資料**不會有丟失風險**。  
- **適用舉例**：當需要快取**圖片、短影片**等**使用者只讀**的資料時，可使用**只讀快取**。

![截圖 2025-08-13 晚上9.28.50](https://hackmd.io/_uploads/SyRzXM9Oee.png)

## 3) 讀寫快取
- **讀**：請求會送至快取查詢資料是否存在。  
- **寫**：**寫請求也會送至快取**，在快取中直接進行**增刪改**。  
- **效能表現**：得益於 Redis 的高效存取，增刪改可在快取中**快速完成**並**迅速回應**應用。  
- **風險**：最新資料位於**Redis（記憶體資料庫）**；一旦掉電或宕機，**記憶體資料可能丟失**，
  因而**最新資料可能遺失**，對業務產生風險。

## 4) 讀寫快取-兩種資料寫回策略
- 依據對**資料可靠性**與**快取性能**的不同要求，讀寫快取可採：  
  - **同步直寫**：優先**保障資料可靠性**；  
  - **異步寫回**：優先提供**快速回應**。  
- 學習理解上述兩種策略，有助於**依業務需求做出正確設計選擇**。


# 讀寫快取的兩種策略：同步直寫與異步寫回

## a) 同步直寫
- **定義**：寫請求同時發給**快取**與**後端資料庫**處理，等待二者**都寫完**才回覆客戶端。  
- **效果**：即使快取宕機或故障，**最新資料仍保存在資料庫**，提供**資料可靠性**保障。  
- **代價**：快取處理寫入很快，但需**等待資料庫**完成所有寫請求，**增加回應延遲**、**降低快取訪問效能**。

## b) 異步寫回
- **定義**：優先考慮**回應延遲**；所有寫請求**先在快取中處理**。當這些增改的資料**被淘汰**時(???????)，才**寫回資料庫**。  
- **效果**：操作在快取中完成，**速度快**、能迅速回覆應用。  
- **風險**：若發生**掉電**且尚未寫回資料庫，**最新資料可能丟失**。

## 1) 只讀快取 vs 讀寫快取
- **是否需要加速寫請求**是選型關鍵：  
  - 需要加速寫 → 選讀寫快取（指 write-back）：前台寫只碰 Redis，寫延遲≈Redis 操作＋排隊，DB I/O 被移到背景批次，吞吐提升。代價是最終一致與更高的系統複雜度。
  - 寫很少或只想加速讀 → 選只讀快取：把熱查詢結果放 Redis，寫入路徑仍以 DB 為權威；寫時只需「刪鍵或重建」，簡單、安全、成本低。

## 2) 場景舉例
- **商品大促**：庫存資訊**頻繁修改**；若每次都到資料庫，會拖慢應用 → **讀寫快取**較合適。  
- **短影片 App**：影片屬性多但**確定後不常改**；在資料庫修改對快取影響不大 → **只讀快取**較合適。
![截圖 2025-08-13 晚上9.29.56](https://hackmd.io/_uploads/S1gPmM9deg.png)

# 小結

## 1) 快取的兩個特徵
- 在**分層系統**中，將資料暫存在**快速子系統**有助於**加速存取**。
- **快取容量有限**；當快取**寫滿**時，資料**需要被淘汰**。

## 2) 為何 Redis 適合作為快取
- Redis **具備高效能存取**與**資料淘汰機制**，符合以上兩個特徵的要求，**非常適合**用作快取。

## 3) 旁路快取的特性與限制
- Redis 作為**旁路快取**，代表需要在**應用程式中新增快取邏輯**的程式碼。
- 若是**無法修改原始碼**的應用情境，**就不能**使用 Redis 做快取。

## 4) 快取模式
- **只讀快取**與**讀寫快取**兩種。
- 其中**讀寫快取**提供：
  - **同步直寫**：**側重資料可靠性**；
  - **異步寫回**：**側重低延遲**。
- 應依**實際業務需求**進行選擇。