# Hot key và cold key

> “Redis mà vẫn nghẽn à?”  
> “Redis mà vẫn timeout à?”  
> “Tưởng cache là nhanh mà?”  
> → Có thể một lượng truy cập quá nhiều vào **hot key**!

## 1\. Hot Key , Cold Key là gì?

* **Hot key** là key bị **truy cập cực kỳ nhiều lần** trong thời gian ngắn
    
* **Cold key** là mấy key ít người đụng tới
    

## 2\. Tình huống thực tế

Redis không phải siêu nhân, vẫn toang vì hot key như thường.

**Bối cảnh:**

* App có 10 triệu người dùng
    
* Trên homepage có 1 phần gọi API `GET /hot-news` – ai vào cũng gọi
    
* Kết quả được cache với key: `hot-news` trong Redis
    

Chúng ta tưởng ngon lành vì đã cache, nhưng…

**Redis CPU đột ngột tăng vọt**

Tất cả 10 triệu request đều hỏi 1 key: `hot-news`.

Dù Redis siêu nhanh, nhưng:

* Truy cập quá nhiều vào 1 key = 1 CPU core bị nghẽn
    
* Redis là single-threaded → performance tụt dần đều
    
* Tệ hơn: nếu dùng redis cluster → hot key nằm 1 shard → shard đó toang, còn shard khác thì… rảnh
    

## 3\. Dấu hiệu hệ thống đang dính hot key

* Redis CPU tăng vọt dù tổng số key không nhiều
    
* Redis response chậm, dù data nhỏ
    
* Request latency tăng tại một số thời điểm, không phải ngẫu nhiên
    
* Redis cluster: 1 shard bị cao tải hơn phần còn lại
    

## 4\. Cách kiểm tra hot key

Sử dụng lệnh:

```plaintext
redis-cli --hotkeys
```

Hiển thị top key được truy cập nhiều nhất trong thời gian ngắn.

Hoặc dùng:

```plaintext
MONITOR
```

Xem toàn bộ request đang đánh vào Redis, lọc ra key bị spam nhiều nhất.

## 5\. Các giải pháp xử lý Hot Key

### 5.1. Phân tán key (Key Sharding)

Thay vì 1 key `hot-news`, chia ra nhiều key ngẫu nhiên:

```plaintext
hot-news:1  
hot-news:2  
hot-news:3  
...
```

Client khi đọc:

* Random chọn 1 key để giảm tải
    
* Hoặc dùng consistent hashing
    

Khi ghi (cache): Ghi đè tất cả bản sao.

### 5.2. Đặt layer cache phía trước Redis

Nếu dùng Redis cluster, có thể đặt **local cache layer** (như Caffeine, Guava) ngay trong ứng dụng.

* App A gọi `hot-news` → cache trong RAM app → không hit Redis
    
* TTL ngắn, sync theo thời gian
    

### 5.3. Sử dụng CDN hoặc Reverse Proxy cache (nếu là content tĩnh)

Ví dụ:

* `GET /banner`
    
* `GET /hot-news`
    

Đưa lên Cloudflare, Nginx cache để **tránh xuống Redis và app layer**

### 5.4. Đặt TTL ngắn và làm warm-up chủ động

* Đặt TTL tầm 30–60s
    
* Có scheduler chủ động refresh key định kỳ thay vì đợi request đầu tiên tới
    

### 5.5. Nếu bất khả kháng: scale Redis Cluster + đặt key ở nhiều shard

Dùng Redis cluster sau đó cấu hình sao cho:

* Key `hot-news` ghi nhiều bản sao tương đương ở shard khác nhau
    
* Mỗi shard gánh một phần request
    

## 6\. Nếu vừa hot key, vừa dính cache stampede?

Khi hot key hết hạn → hàng ngàn request cùng gọi lại → backend chết theo.

**Có thể xem xét phương án kết hợp xử lý như sau:**

* Phân tán key + lock (`SETNX`) để chỉ 1 request gọi backend
    
* TTL ngắn nhưng random
    
* Nếu cần, dùng **cache-aside + mutex lock**
    

## Tóm lại vài ý chính

* Tưởng cache là xong thực ra Redis vẫn toang vì quá tải 1 key
    
* Không đo tần suất truy cập từng key, bỏ sót hot key tiềm ẩn. Redis vẫn có thể nghẽn hoặc timeout nếu dính hot key
    
* Không scale theo pattern truy cập, gây nghẽn cổ chai ở Redis hoặc shard cụ thể. Cần phân tán key, dùng local cache trước Redis, TTL ngắn + warm-up là cách chống cháy
