---
id: caching-redis
title: "Redis và Memcached"
shortTitle: "Redis"
track: caching
trackTitle: "Caching"
order: 1
level: core
status: published
estimatedMinutes: 40
prerequisites:
  - database-mongo
next: docker-concepts
reviewedAgainst: 2026-10-12
sources:
  - title: "Redis — key eviction"
    url: https://redis.io/docs/latest/develop/reference/eviction/
  - title: "Redis — persistence"
    url: https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/
  - title: "memcached(1)"
    url: https://linux.die.net/man/1/memcached
---

# Redis và Memcached

Lab chạy Redis bằng Docker, image `redis:7`. Không cần cài Memcached. Phần Memcached chỉ để biết khi nào không dùng Redis.

## Để làm gì

Đặt cache có TTL, chọn eviction policy khi RAM đầy, và không dùng Redis làm chỗ chứa dữ liệu duy nhất nếu bạn chưa bật persistence có chủ đích.

## Gồm những gì

- `SET` với `EX`, `GET`, `TTL`.
- `maxmemory` và `maxmemory-policy`. Mặc định là `noeviction`.
- RDB và AOF, một đoạn đủ để đọc config.
- Memcached: chỉ cache trong RAM, không persistence.

Không gồm Redis Cluster, Pub/Sub, hay Lua script.

## Dùng khi nào

Một query lặp lại, dữ liệu chịu được độ trễ vài giây đến vài phút. Session cần TTL. Hàng đợi nhẹ thì Redis cũng làm được, nhưng đó không phải bài này.

Memcached hợp cache thuần, nhiều node độc lập, không cần persistence hay cấu trúc dữ liệu phong phú. Hệ thống cũ còn Memcached thì đừng vội đổi sang Redis trong một lần deploy.

Đừng nhét dữ liệu không tái tạo được vào Redis rồi tắt persistence. Restart là mất.

## Kiến thức cốt lõi

`SET key value EX 60` ghi key và hết hạn sau 60 giây. `TTL key` trả số giây còn lại, `-2` khi key không còn, `-1` khi key không có hạn.

`maxmemory` là trần RAM. Khi đầy, `maxmemory-policy` quyết định. Docs eviction liệt kê:

| Policy | Khi RAM đầy |
| --- | --- |
| `noeviction` | Không xoá key. Lệnh ghi mới trả lỗi. Đây là mặc định |
| `allkeys-lru` | Xoá key ít được đọc gần đây, kể cả key không TTL |
| `volatile-ttl` | Chỉ xoá key có TTL, ưu tiên key sắp hết hạn |

Cache nên đặt `allkeys-lru` hoặc một policy `volatile-*` nếu mọi key cache đều có TTL. `noeviction` hợp Redis đang giữ dữ liệu không được phép rơi. Để mặc định rồi dùng làm cache: lúc RAM đầy, app nhận lỗi ghi thay vì cache cũ bị đẩy ra.

Persistence, theo docs Redis: RDB là snapshot theo chu kỳ. AOF ghi lại lệnh ghi, mất ít dữ liệu hơn khi crash, file lớn và replay lâu hơn. Bật cả hai được. Tắt cả hai thì Redis chỉ là RAM.

Memcached giữ object trong RAM, có LRU của nó, không có RDB/AOF. Restart process là cache trống. App phải chạy được khi cache trống.

## Lệnh và code mẫu

```bash
docker run -d --name lab-redis -p 6379:6379 redis:7
docker exec -it lab-redis redis-cli
```

Trong `redis-cli`:

```text
SET page:home "<html>ok</html>" EX 60
GET page:home
TTL page:home
CONFIG GET maxmemory-policy
```

`CONFIG GET` trên Redis 7 trả policy hiện tại. Thoát bằng `QUIT`.

Đặt trần rất nhỏ để thấy eviction, chỉ trên container lab:

```bash
docker exec lab-redis redis-cli CONFIG SET maxmemory 1mb
docker exec lab-redis redis-cli CONFIG SET maxmemory-policy allkeys-lru
```

## Thực hành

1. `SET` một key với `EX 15`. `GET` ngay thì còn. Đợi hơn 15 giây, `GET` trả `(nil)`, `TTL` trả `-2`.
2. `CONFIG GET maxmemory-policy` trước khi sửa. Ghi lại giá trị. Image `redis:7` mặc định `noeviction`.
3. Đặt `maxmemory` 1mb và `allkeys-lru`. Ghi một key mới vẫn được, không cần chờ đầy RAM để hiểu lệnh đã nhận.
4. `docker rm -f lab-redis`. Chạy lại container không volume. Key cũ mất. Đó là hệ quả của không persistence và không mount disk.

## Kết quả mong đợi

- Key biến mất sau TTL, không cần `DEL`.
- Policy lúc mới lên là `noeviction`.
- Container mới không còn key đã `SET`.

## Checklist

- [ ] Gắn TTL cho cache key, trừ khi bạn cố ý giữ key không hết hạn.
- [ ] Đổi `noeviction` nếu Redis này chỉ là cache.
- [ ] Nói được RDB khác AOF chỗ dữ liệu mất khi crash.
- [ ] App vẫn chạy khi `GET` trả nil.
- [ ] Không để port 6379 ra Internet không password.

## Lỗi thường gặp

**Redis cache đầy, app 500 hàng loạt.** Policy `noeviction`, lệnh `SET` trả lỗi. Đặt `allkeys-lru` hoặc tăng RAM. Log app sẽ có `OOM command not allowed`.

**Dùng Redis làm database duy nhất, persistence tắt.** Deploy lại container là hết session và hết dữ liệu. Bật AOF hoặc RDB, gắn volume, hoặc chỉ để những gì làm lại được.

**Key không TTL trong cache LRU.** `allkeys-lru` xoá cả key đó. Session dài và cache ngắn nên tách instance, đúng gợi ý trong docs eviction về `volatile-*`.

## Nguồn

1. [Key eviction](https://redis.io/docs/latest/develop/reference/eviction/) — Redis, `noeviction`, `allkeys-lru`, `volatile-ttl`.
2. [Persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/) — RDB và AOF.
3. [memcached](https://linux.die.net/man/1/memcached) — cache RAM, không có persistence của Redis.

## Tiếp theo

[Container và Docker](../docker/00-concepts.md)
