Replication, Sentinel và Cluster: Redis "partition" thế nào

4 câu hỏi~30 phútTừ khóa: master–replica, async replication, Sentinel, failover, Redis Cluster, 16384 hash slots, CRC16, hash tag, MOVED, CROSSSLOT, Lettuce topology refresh

Ok, vậy Redis có gì giống partition bên Kafka không?

Có. Khái niệm gần nhất là sharding trong Redis Cluster: Redis chia key space thành 16384 hash slots. Nhưng không nên coi Kafka partition = Redis hash slot hoàn toàn. Giống ở ý tưởng chia dữ liệu ra nhiều phần, khác ở mục đích. Để hiểu đủ, đi từ một node lên ba tầng: replication → Sentinel → Cluster.

1. Bài toán

shop-app ──> Redis (1 node, 8 GB)
             cache product, session, rate limit, lock

Hai rủi ro: node chết thì mọi người bị logout và DB nhận toàn bộ tải (avalanche, bài 7.2); dữ liệu tăng vượt RAM một máy.

2. Vấn đề

3. Giải pháp: ba tầng

TầngGiải quyếtKhông giải quyết
Replication (master + replica)Copy dữ liệu, scale đọcTự failover
SentinelTheo dõi master, tự promote replica, báo client master mớiDữ liệu lớn hơn một máy
ClusterSharding qua nhiều master + failover tích hợpLệnh multi-key khác slot

Replication là async: master trả OK cho client trước, rồi mới gửi sang replica. Master chết trước khi gửi thì write đó mất. WAIT numreplicas timeout giúp chờ replica nhận, nhưng vẫn không biến Redis thành strongly consistent.

Cluster chia key:

slot = CRC16(key) mod 16384

Master A: slot 0     – 5460    ── Replica A'
Master B: slot 5461  – 10922   ── Replica B'
Master C: slot 10923 – 16383   ── Replica C'

product:100 → CRC16 → slot 8000 → Master B

Hash tag: chỉ phần trong {...} được hash. cart:{42} và session:{42} cùng slot, nên dùng chung trong Lua script hay MULTI được.

4. Code từng bước

Bước 1: Sentinel (dữ liệu vừa một máy, cần HA):

spring:
  data:
    redis:
      password: ${REDIS_PASSWORD}
      sentinel:
        master: shop-master
        nodes: sentinel-1:26379,sentinel-2:26379,sentinel-3:26379

Bước 2: Cluster (cần sharding):

spring:
  data:
    redis:
      password: ${REDIS_PASSWORD}
      cluster:
        nodes: redis-1:6379,redis-2:6379,redis-3:6379
        max-redirects: 3
      lettuce:
        cluster:
          refresh:
            adaptive: true      # cập nhật topology khi gặp MOVED / failover
            period: 30s

Bước 3: Java: key cần đi chung thì dùng hash tag; đọc từ replica nếu chấp nhận stale:

@Bean
LettuceClientConfigurationBuilderCustomizer readFromReplica() {
    return b -> b.readFrom(ReadFrom.REPLICA_PREFERRED);   // cache đọc nhiều
}

// Hai key cùng user nằm cùng slot nhờ {userId}
String cartKey = "cart:{" + userId + "}";
String lastSeenKey = "recent:{" + userId + "}";

Bước 4: Test

redis-cli -c -h redis-1 CLUSTER KEYSLOT product:100     # 8000 (ví dụ)
redis-cli -h redis-1 GET product:100                     # (error) MOVED 8000 redis-2:6379
redis-cli -c -h redis-1 GET product:100                  # -c tự theo MOVED
redis-cli -c MGET product:1 product:2                    # CROSSSLOT nếu khác slot

5. Cách hoạt động: failover

Sentinel 1  Sentinel 2  Sentinel 3
     \          |          /
      ping master mỗi giây
master không trả lời > down-after-milliseconds
  → SDOWN (một sentinel thấy)
  → ODOWN (đủ quorum đồng ý)
  → bầu leader sentinel → promote replica tốt nhất
  → replica khác chuyển sang master mới
  → client hỏi sentinel, kết nối master mới

Cluster làm tương tự nhưng không cần Sentinel: các master gossip với nhau, đa số master đánh dấu một master là FAIL thì replica của nó được promote.

6. So sánh với Kafka

ConceptKafkaRedis Cluster
Chia dữ liệuPartitionHash slot
Đơn vị dữ liệuRecord/messageKey
Chọn phầnhash(message key) mod số partitionCRC16(key) mod 16384
ServerBrokerRedis node
Bản saoReplica (ISR)Replica (async)
Consumer parallelism, orderingCó: partition → consumer trong groupKhông có khái niệm này

7. Khi nào nên dùng / không nên dùng

Vậy chung quy lại:

  • Redis có sharding và single thread để thực thi command;
  • Kafka có partition, topic, consumer group;
  • RabbitMQ thì exchange và queue.

Mình hiểu vậy đúng không?

Đúng, ở mức interview bạn có thể đóng khung như vậy. Chỉnh một chút cho chính xác:

Công nghệConcept nên nhớ
RedisKey-value, TTL, data types, hash slot/sharding, replica, thực thi command chủ yếu trên một thread
KafkaProducer, topic → partition, offset, consumer group, broker, replica
RabbitMQProducer → exchange → queue → consumer → ACK, routing key
Redis:    Key → Hash slot → Node → main thread thực thi
Kafka:    Producer → Topic → Partition (offset) → Consumer group
RabbitMQ: Producer → Exchange → (routing) → Queue → Consumer → ACK

Lưu ý: single thread là cách Redis thực thi command trên mỗi node. Cluster 3 master là 3 main thread độc lập; atomic chỉ được đảm bảo trong một node, đó là lý do multi-key phải cùng slot.

Khi master chết và replica được promote, lock hay cache đang nằm trên master cũ có bị ảnh hưởng không?

Có, vì replication async. Những write master đã trả OK nhưng chưa kịp sang replica sẽ mất:

t1  Job instance A: SET lock:report token-A NX PX 30000 → OK (master)
t2  master chết trước khi replicate
t3  replica promote, không có lock:report
t4  Job instance B: SET lock:report token-B NX PX 30000 → OK
    → A và B cùng chạy job

Thêm nữa: trong lúc failover (thường vài giây đến chục giây) write bị lỗi. App cần timeout ngắn, retry có giới hạn, và fallback (cache lỗi thì đọc DB, có circuit breaker).

Phỏng vấn hỏi Redis HA, Sentinel và Cluster khác nhau thế nào thì trả lời sao?

Q1. Sentinel và Cluster khác nhau thế nào?

🇻🇳 Tiếng Việt:

Sentinel dùng cho mô hình một master nhiều replica: nó theo dõi master, khi master chết thì promote replica và báo client địa chỉ mới. Toàn bộ dữ liệu vẫn nằm trên một master. Cluster thì sharding: chia key vào 16384 hash slot trên nhiều master, mỗi master có replica, failover tích hợp sẵn. Dữ liệu vừa một máy thì Sentinel; vượt một máy thì Cluster.

🇬🇧 English:

Sentinel is for a single master with replicas: it monitors the master, promotes a replica on failure and tells clients the new address. All data still lives on one master. Cluster shards data: keys are mapped to 16384 hash slots spread across several masters, each with replicas, and failover is built in. If the data fits on one machine I use Sentinel; if not, Cluster.

Q2. Redis Cluster chia key thế nào? Giống Kafka partition không?

🇻🇳 Tiếng Việt:

Slot bằng CRC16 của key mod 16384, mỗi master giữ một dải slot. Giống Kafka ở ý tưởng chia dữ liệu theo hash ra nhiều node, nhưng Kafka partition còn là đơn vị ordering và chia việc cho consumer group, Redis slot thì chỉ phân phối key. Lệnh nhiều key phải cùng slot, nên em dùng hash tag như cart:{42}.

🇬🇧 English:

The slot is CRC16 of the key modulo 16384, and each master owns a range of slots. It is similar to Kafka in hashing data across nodes, but a Kafka partition is also the unit of ordering and of work distribution in a consumer group, while a Redis slot only distributes keys. Multi-key commands must hit the same slot, so I use hash tags like cart:{42}.

Q3. Replication của Redis có mất dữ liệu không?

🇻🇳 Tiếng Việt:

Có thể, vì replication async. Write vừa được master xác nhận có thể mất khi failover. Cache thì chấp nhận được, nhưng với lock thì hai client có thể cùng giữ lock, nên em không để Redis lock là lớp bảo vệ duy nhất cho dữ liệu quan trọng.

🇬🇧 English:

Yes, because replication is asynchronous. A write acknowledged by the master can be lost during failover. That is fine for a cache, but for a lock two clients may end up holding it, so I never rely on a Redis lock as the only protection for critical data.

Cách nhớ ngắn gọn


Tự kiểm tra

Redis Cluster có bao nhiêu hash slot, tính thế nào?

16384; slot = CRC16(key) mod 16384.

Hash tag dùng để làm gì?

Chỉ phần trong {} được hash, nên các key liên quan nằm cùng slot để dùng MGET, MULTI, Lua.

Lỗi MOVED nghĩa là gì?

Key thuộc slot ở node khác; client cluster-aware cập nhật topology và gửi lại tới node đúng.

Sentinel cần tối thiểu bao nhiêu node, vì sao?

Ba, để có quorum và tránh một sentinel bị cô lập quyết định sai.

Failover ảnh hưởng thế nào tới distributed lock?

Lock chưa replicate có thể mất, client khác lấy được lock, hai bên cùng chạy.