Danh sách bài viết

Bài 102: Redis Cluster — Sharding & Native Failover

Redis Cluster giải quyết hai giới hạn mà Sentinel không có: sharding dữ liệu tự động qua nhiều master node và failover tích hợp sẵn không cần tiến trình ngoài. Bài này đi qua cơ chế 16384 hash slot, cách client routing hoạt động với MOVED/ASK, hash tag để group key cùng slot, setup 6-node cluster, resharding online, native failover, giới hạn multi-key ops, và so sánh với Sentinel.

01/06/2026
0 lượt xem
1

Mục Tiêu Bài Học

  • Giải thích được tại sao Sentinel không giải quyết được bài toán data lớn hơn RAM của một node.
  • Mô tả cơ chế 16384 hash slot: key map sang slot bằng CRC16, slot map sang node.
  • Hiểu hash tag: cú pháp {tag} trong key name, mục đích gom key cùng slot để dùng multi-key ops.
  • Phân biệt MOVED (redirect vĩnh viễn) và ASK (redirect tạm thời trong lúc resharding).
  • Setup được cluster 6 node trên localhost, tạo cluster bằng redis-cli --cluster create.
  • Dùng được redis.cluster.RedisCluster trong redis-py để thao tác với cluster.
  • Nhận diện các giới hạn: cross-slot MGET, MULTI/EXEC, Lua script — và workaround với hash tag.
  • Mô tả quy trình failure detection và auto-failover trong cluster.
  • So sánh Sentinel và Cluster theo từng tiêu chí để chọn đúng cho bài toán cụ thể.
2

Giới Hạn Của Sentinel Và Bài Toán Scale

Sentinel (bài 101) giải quyết tốt bài toán high availability: một master với một hoặc vài replica, và khi master chết, Sentinel tự động promote replica. Nhưng mô hình này có một giới hạn cứng: toàn bộ dataset phải vừa trong RAM của một node duy nhất.

Khi dữ liệu tăng lên vài chục GB, điều này vẫn quản lý được với một máy chủ đủ mạnh. Nhưng khi đạt đến 100GB, 500GB, hay hơn, chi phí một máy chủ đơn leo thang nhanh, và rủi ro tập trung trên một node duy nhất tăng theo. Sentinel không có cơ chế chia nhỏ data ra nhiều node (sharding).

Redis Cluster giải quyết cả hai vấn đề:

  • Sharding tự động: data được chia đều qua nhiều master node. Thêm node vào cluster để tăng tổng dung lượng lưu trữ.
  • Native failover: không cần tiến trình Sentinel ngoài. Cluster tự detect node chết và tự promote replica lên làm master.

Đổi lại, Redis Cluster có độ phức tạp vận hành cao hơn và có một số giới hạn về multi-key operations mà standalone Redis không có.

3

Kiến Trúc Redis Cluster

Một Redis Cluster gồm nhiều node, mỗi node chạy một tiến trình Redis. Các node được chia thành hai vai trò:

  • Master node: sở hữu một tập con các hash slot, nhận lệnh đọc/ghi cho những slot đó.
  • Replica node: bản sao của một master cụ thể, dùng để failover và có thể phục vụ read (tùy cấu hình READONLY).

Ngoài cổng client thông thường (ví dụ 7000), mỗi node mở thêm một cluster bus port bằng cổng client + 10000 (ví dụ 17000). Cluster bus là kênh TCP riêng để các node giao tiếp với nhau: gossip trạng thái, phát hiện node chết, đồng thuận promote replica. Firewall phải mở cả hai dải cổng này.

Cấu hình tối thiểu để cluster có khả năng chịu lỗi là 3 master + 3 replica (6 node), mỗi master một replica. Trong môi trường production, đặt mỗi cặp master–replica trên các AZ (Availability Zone) khác nhau để một AZ down không làm mất master.

Ví dụ phân bố slot với 3 master:

Master A (7000): slot 0 – 5460
Master B (7001): slot 5461 – 10922
Master C (7002): slot 10923 – 16383

Phân bố này do redis-cli --cluster create tự tính và chia đều. Có thể reshard sau khi thêm node mới.

4

Hash Slot — Cơ Chế Phân Phối Key

Redis Cluster chia không gian key thành 16384 hash slot (số cố định, không thay đổi). Mỗi key ánh xạ vào đúng một slot theo công thức:

slot = CRC16(key) mod 16384

Slot sau đó ánh xạ sang node đang sở hữu nó. Mapping slot → node thay đổi khi resharding, nhưng số lượng slot luôn là 16384.

Lý do chọn 16384 thay vì 65536: để giảm kích thước của heartbeat message gửi qua cluster bus. Với 16384 slot, bitmask biểu diễn slot ownership của một node chỉ chiếm 2KB — đủ nhỏ để nhúng vào heartbeat gửi định kỳ giữa các node. Con số này được chọn theo phân tích trong Redis commit history (antirez, 2014).

Kiểm tra slot của một key cụ thể:

# Từ redis-cli kết nối bất kỳ node
CLUSTER KEYSLOT user:123
# → 5649

CLUSTER KEYSLOT order:999
# → 7341

Lệnh này hữu ích để debug routing và kiểm tra hash tag có hoạt động đúng không trước khi deploy.

5

Hash Tag — Gom Key Cùng Slot

Mặc định, slot được tính từ toàn bộ tên key. Điều này khiến các key liên quan đến cùng một entity (ví dụ user 123) có thể nằm trên các node khác nhau, làm MGET, ZUNIONSTORE, hay MULTI/EXEC không thực hiện được trên nhóm key đó.

Hash tag giải quyết vấn đề này: khi key chứa cú pháp {tag}, Redis chỉ dùng phần trong dấu ngoặc nhọn đầu tiên để tính CRC16, bỏ qua phần còn lại của tên key.

# Không có hash tag — 3 key có thể nằm 3 node khác nhau
user:123:profile     → slot = CRC16("user:123:profile") mod 16384
user:123:settings    → slot = CRC16("user:123:settings") mod 16384
user:123:session     → slot = CRC16("user:123:session") mod 16384

# Có hash tag — 3 key cùng slot vì cùng hash "123"
user:{123}:profile   → slot = CRC16("123") mod 16384
user:{123}:settings  → slot = CRC16("123") mod 16384
user:{123}:session   → slot = CRC16("123") mod 16384

Xác nhận bằng CLUSTER KEYSLOT:

CLUSTER KEYSLOT user:{123}:profile
# → 2996
CLUSTER KEYSLOT user:{123}:settings
# → 2996  ← cùng slot

Khi các key cùng slot, các lệnh sau hoạt động bình thường trong cluster:

  • MGET user:{123}:profile user:{123}:settings user:{123}:session
  • MULTI / EXEC chứa nhiều key của cùng entity
  • Lua script dùng nhiều key của cùng entity
  • ZUNIONSTORE dest{123} 2 rank{123}:daily rank{123}:weekly

Chọn hash tag theo entity ID là convention phổ biến nhất: {userId}, {orderId}, {sessionId}. Tránh dùng một tag quá rộng (như {global}) vì sẽ dồn tất cả key về một slot.

6

Client Routing: MOVED Và ASK

Redis Cluster không dùng proxy ở giữa. Client kết nối trực tiếp vào các node. Để định tuyến đúng, smart client (như redis-py cluster, ioredis cluster) duy trì một bảng ánh xạ slot → node.

Quy trình khởi tạo:

  1. Client kết nối bất kỳ node nào trong cluster.
  2. Gọi CLUSTER SLOTS hoặc CLUSTER SHARDS để lấy toàn bộ slot map.
  3. Lưu map vào bộ nhớ client.
  4. Với mỗi lệnh, client tính slot từ key, tra map, kết nối thẳng tới node đúng.

Khi slot map của client lỗi thời (do resharding), Redis trả về một trong hai lỗi:

MOVED

Slot đã được chuyển vĩnh viễn sang node khác. Resharding đã hoàn thành.

# Client gửi GET foo tới node A (port 7000)
# Node A trả về:
-MOVED 3999 127.0.0.1:7002

Client phải: (1) gửi lại lệnh tới 127.0.0.1:7002, (2) cập nhật bảng slot map để lần sau gửi thẳng. Smart client tự xử lý bước này, application code không thấy lỗi.

ASK

Slot đang trong quá trình migrate, chưa xong. Key có thể còn ở node cũ hoặc đã sang node mới — không chắc.

# Node A trả về:
-ASK 3999 127.0.0.1:7002

Client phải: (1) gửi ASKING tới node 7002, (2) gửi lại lệnh gốc, (3) không cập nhật slot map — redirect này chỉ áp dụng cho lần này, không phải thay đổi vĩnh viễn.

Điều kiện MOVED ASK
Khi nào xảy ra Sau khi resharding hoàn thành Trong lúc slot đang migrate
Cập nhật slot map Không
Cần gửi ASKING trước Không
7

Setup Cluster 6 Node

Ví dụ dưới đây chạy 6 node trên localhost với cổng 7000–7005, phù hợp để dev/test. Production thường đặt mỗi node trên một máy chủ riêng.

Khởi động 6 node:

for port in 7000 7001 7002 7003 7004 7005; do
  mkdir -p /tmp/redis-cluster/$port
  redis-server \
    --port $port \
    --cluster-enabled yes \
    --cluster-config-file /tmp/redis-cluster/$port/nodes.conf \
    --cluster-node-timeout 5000 \
    --appendonly yes \
    --appendfilename appendonly.aof \
    --dbfilename dump.rdb \
    --dir /tmp/redis-cluster/$port \
    --daemonize yes \
    --logfile /tmp/redis-cluster/$port/redis.log
done

Tạo cluster (3 master + 3 replica, tỉ lệ 1 replica/master):

redis-cli --cluster create \
  127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
  127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
  --cluster-replicas 1

Lệnh này in ra đề xuất phân bố slot và master–replica pairing, hỏi xác nhận trước khi tạo cluster. Redis CLI tự chia đều slot cho 3 master đầu tiên, 3 node còn lại trở thành replica.

Kiểm tra cluster đã healthy:

redis-cli -p 7000 CLUSTER INFO
# cluster_state: ok
# cluster_slots_assigned: 16384
# cluster_known_nodes: 6
# cluster_size: 3

Kết nối dưới dạng cluster client (thêm -c để redis-cli tự theo MOVED):

redis-cli -c -p 7000

127.0.0.1:7000> SET user:{1}:name "Alice"
-> Redirected to slot [9189] located at 127.0.0.1:7001
OK

127.0.0.1:7001> GET user:{1}:name
"Alice"
8

Code Python — Cluster Client

redis-py 4.x trở lên cung cấp redis.cluster.RedisCluster. Package cần cài đêm:

pip install "redis[hiredis]"  # redis-py >= 4.1.0
from redis.cluster import RedisCluster
from redis.cluster import ClusterNode

# Cách 1: Chỉ cần một startup node, client tự discover toàn cluster
r = RedisCluster(host="localhost", port=7000, decode_responses=True)

# Cách 2: Cung cấp nhiều startup node để tăng độ ổn định khi khởi động
startup_nodes = [
    ClusterNode("localhost", 7000),
    ClusterNode("localhost", 7001),
    ClusterNode("localhost", 7002),
]
r = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)

# Ghi / đọc thông thường — MOVED handling tự động
r.set("counter", 0)
r.incr("counter")
print(r.get("counter"))  # "1"

# Multi-key ops với hash tag
r.set("user:{42}:name", "Bob")
r.set("user:{42}:age", "30")
r.set("user:{42}:email", "[email protected]")

# MGET hoạt động vì cùng hash tag {42} → cùng slot
values = r.mget("user:{42}:name", "user:{42}:age", "user:{42}:email")
print(values)  # ['Bob', '30', '[email protected]']

# Pipeline cùng slot
pipe = r.pipeline()
pipe.set("order:{99}:status", "pending")
pipe.set("order:{99}:total", "1500")
pipe.execute()

# Cluster info
info = r.cluster("info")
print(info["cluster_state"])  # ok

Khi một key nằm sai node, RedisCluster tự theo MOVED và retry. Application code không cần xử lý MOVED manually. Nếu cluster đang reshape và nhận ASK, client cũng tự gửi ASKING trước khi retry.

# Cross-slot error — xảy ra khi dùng key không cùng slot
try:
    r.mget("user:1:name", "user:2:name")  # key khác nhau, khác slot
except Exception as e:
    print(e)
    # CROSSSLOT Keys in request don't hash to the same slot
9

Giới Hạn Multi-Key Operations

Đây là điểm quan trọng nhất để tránh lỗi khi migrate application từ standalone sang cluster.

Các lệnh sau chỉ hoạt động trong cluster nếu tất cả key liên quan nằm cùng một slot:

  • MGET k1 k2 k3 — đọc nhiều key
  • MSET k1 v1 k2 v2 — ghi nhiều key
  • MSETNX k1 v1 k2 v2
  • SUNIONSTORE / SINTERSTORE / SDIFFSTORE
  • ZUNIONSTORE / ZINTERSTORE / ZDIFFSTORE
  • MULTI / EXEC chứa nhiều key
  • EVAL (Lua script) với nhiều key
  • COPY src dst
  • RENAME src dst

Khi key không cùng slot, Redis trả lỗi ngay:

MGET user:1 user:2
# (error) CROSSSLOT Keys in request don't hash to the same slot

Hai workaround:

  1. Dùng hash tag: đặt entity ID vào {} để force cùng slot. Đây là cách đúng đắn khi các key liên quan theo business logic.
    # user:1 và user:2 KHÔNG liên quan → không nên dùng cùng hash tag
    # user:{123}:profile và user:{123}:cart LIÊN QUAN → hash tag hợp lý
  2. Pipeline single-key ops: khi không thể hoặc không nên gom vào cùng slot, dùng pipeline nhiều lệnh đơn thay vì một lệnh multi-key. Kết quả nhận về cùng lúc, chỉ có độ trễ network tăng nhẹ.
    pipe = r.pipeline(transaction=False)
    pipe.get("user:1")
    pipe.get("user:2")
    results = pipe.execute()  # [val1, val2]

Với Lua script, Redis yêu cầu tất cả KEYS[n] phải cùng slot. Nếu không, script bị từ chối khi cluster phát hiện cross-slot access.

10

Failure Detection Và Failover

Redis Cluster tự detect node chết và promote replica mà không cần tiến trình ngoài như Sentinel.

Failure detection

  1. Mỗi node định kỳ gửi PING tới các node khác qua cluster bus.
  2. Nếu một node không trả PONG trong cluster-node-timeout (mặc định 15000ms), node gọi là PFAIL (Possible Failure — nghi ngờ chết).
  3. Node đánh dấu PFAIL lan truyền thông tin này qua gossip.
  4. Khi phần lớn master node (quorum) đồng ý node đó PFAIL, trạng thái nâng lên FAIL (xác nhận chết).

Failover process

  1. Replica của master FAIL phát hiện master đã bị đánh dấu FAIL.
  2. Replica yêu cầu bầu chọn từ các master node khác (election).
  3. Master node vote cho replica nào có replication offset cao nhất (đồng bộ dữ liệu gần nhất với master cũ nhất).
  4. Replica thắng election tự promote thành master.
  5. Node mới broadcast cập nhật slot ownership.
  6. Các node còn lại cập nhật routing table.

Thời gian failover điển hình: 10–30 giây tùy cluster-node-timeout. Trong thời gian này, slot của master chết không phục vụ được request (cluster trả lỗi cho key thuộc slot đó).

Nếu một master chết mà không có replica, các slot của nó không ai sở hữu. Với cấu hình mặc định cluster-require-full-coverage yes, toàn bộ cluster ngừng nhận request. Đây là lý do tại sao mỗi master cần ít nhất một replica.

11

Resharding Và Quản Lý Node

Thêm master node và reshard

Thêm master node mới (chưa có slot):

# Khởi động node mới trên port 7006 (tương tự bước setup)
# Thêm vào cluster
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000

Node mới được thêm vào cluster nhưng chưa có slot. Cần reshard để chuyển một số slot từ node hiện có:

redis-cli --cluster reshard 127.0.0.1:7000

Lệnh sẽ hỏi:

  • Số slot muốn chuyển (ví dụ: 4096 để phân bố đều 4 node)
  • ID của node đích (node 7006 vừa thêm)
  • Nguồn: có thể chọn all để lấy đều từ tất cả node, hoặc chỉ định ID cụ thể

Resharding hoạt động online: không có downtime. Key đang migrate sẽ nhận ASK redirect trong thời gian chuyển. Sau khi slot hoàn toàn sang node mới, node cũ gửi MOVED.

Thêm replica

redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 \
  --cluster-slave \
  --cluster-master-id <ID của master 7006>

Xóa node

Trước khi xóa một master, phải chuyển hết slot về các node khác (reshard về slot 0). Sau đó:

redis-cli --cluster del-node 127.0.0.1:7000 <node-id>

Replica không có slot nên có thể xóa trực tiếp mà không cần reshard trước.

Rebalance tự động

redis-cli --cluster rebalance 127.0.0.1:7000 --cluster-use-empty-masters

Lệnh này tự tính lại phân bố đều và reshard theo. Tiện khi sau khi thêm nhiều node.

12

Lệnh Quản Trị Cluster

Các lệnh CLUSTER * cho phép inspect và quản lý cluster từ bất kỳ node nào:

Lệnh Mô tả
CLUSTER INFO Trạng thái tổng quan: cluster_state, số slot assigned, số node, epoch hiện tại
CLUSTER NODES Danh sách tất cả node: ID, địa chỉ, role (master/replica), trạng thái, slot range
CLUSTER SLOTS Mapping slot range → node (deprecated, dùng CLUSTER SHARDS từ Redis 7)
CLUSTER SHARDS Mapping chi tiết hơn: slot range, master, replicas (Redis 7.0+)
CLUSTER KEYSLOT key Tính slot number cho một key cụ thể
CLUSTER COUNTKEYSINSLOT slot Số key trong một slot
CLUSTER GETKEYSINSLOT slot count Lấy tên key trong một slot (dùng khi debug hoặc migrate)
CLUSTER MYID ID của node hiện tại đang kết nối
CLUSTER RESET SOFT Reset node về trạng thái chưa join cluster (giữ data, chỉ xóa cluster state)

Ví dụ kiểm tra từ redis-cli:

redis-cli -p 7000 CLUSTER INFO | grep cluster_state
# cluster_state:ok

redis-cli -p 7000 CLUSTER NODES
# [danh sách node với ID, địa chỉ, role, slot range]
13

Cluster Constraints

Quorum và cluster availability

Cluster yêu cầu quá nửa số master node phải hoạt động để tiếp tục nhận request. Với 3 master, mất 2 master → cluster down (không đủ quorum để vote failover). Với 5 master, mất 3 master → cluster down.

Đây là đặc tính CAP của Redis Cluster: ưu tiên Consistency và Partition Tolerance, sẵn sàng từ chối request khi không đủ quorum.

cluster-require-full-coverage

Hai chế độ xử lý khi có slot không được phủ (master chết, không có replica):

# /etc/redis/redis.conf hoặc config của từng node

# Mặc định: nếu bất kỳ slot nào không có owner → cluster down hoàn toàn
cluster-require-full-coverage yes

# Degraded mode: cluster vẫn phục vụ các slot còn healthy
# Key thuộc slot mất → trả lỗi; key thuộc slot còn lại → hoạt động bình thường
cluster-require-full-coverage no

Trong môi trường production thông thường dùng yes để tránh partial failure gây inconsistency khó debug. no phù hợp với các use case có thể chấp nhận mất một phần data tạm thời (ví dụ: caching layer, không phải primary store).

Replica migration

Nếu một master có nhiều replica hơn cần thiết trong khi master khác không có replica nào, cluster có thể tự động migrate replica qua cấu hình cluster-migration-barrier. Tính năng này giúp đảm bảo mỗi master luôn có ít nhất một replica ngay cả sau khi replica của master khác chết.

14

Pub/Sub, Transactions, Persistence Trong Cluster

Pub/Sub

Regular PUBLISH trong cluster: message được broadcast tới tất cả node qua cluster bus. Mọi subscriber trên bất kỳ node nào đều nhận được, nhưng overhead tăng theo số node.

Sharded Pub/Sub (Redis 7.0+, SPUBLISH / SSUBSCRIBE): message chỉ tồn tại trong slot tương ứng với channel, không broadcast qua toàn cluster. Chi tiết về Sharded Pub/Sub đã được trình bày ở bài 68.

Transactions (MULTI/EXEC)

MULTI/EXEC hoạt động bình thường trong cluster nếu tất cả key trong transaction cùng slot. Nếu có cross-slot key, transaction bị từ chối ngay khi gửi lệnh đầu tiên trong MULTI block, trả lỗi CROSSSLOT.

Hash tag là cách duy nhất để dùng transaction với nhiều key liên quan trong cluster. Thiết kế key schema với hash tag ngay từ đầu — thêm vào sau rất tốn công migrate.

Lua scripts

Lua script (EVAL, EVALSHA) yêu cầu tất cả KEYS[n] phải cùng slot. Redis kiểm tra điều này trước khi thực thi script và từ chối nếu cross-slot. Script chạy trên node sở hữu slot của KEYS[1].

Persistence

Mỗi node trong cluster có cấu hình RDB/AOF riêng, giống standalone Redis. Backup cluster đầy đủ cần snapshot từng master node riêng lẻ. Replica cũng persist nếu được cấu hình, cung cấp thêm bản sao dữ liệu.

Khi replica sync với master mới sau failover, toàn bộ quá trình replication hoạt động giống bài 100: partial resync nếu replication ID còn khớp, full resync nếu không.

15

Sentinel Vs Cluster — Bảng So Sánh

Tiêu chí Sentinel Cluster
Sharding Không — toàn bộ data trên một master Có — data chia đều qua N master
Dung lượng tối đa RAM của một node RAM × số master node
Failover Qua tiến trình Sentinel ngoài Built-in trong cluster protocol
Độ phức tạp setup Trung bình (3 Sentinel + N Redis) Cao (6+ node, cluster bus, slot config)
Multi-key ops Hoạt động tự do Yêu cầu cùng slot (hash tag)
Pub/Sub Bình thường Broadcast overhead (hoặc dùng Sharded Pub/Sub)
Client support Hầu hết client hỗ trợ Cần smart client (cluster-aware)
Use case phù hợp Dataset dưới ~50–100GB, HA đơn giản Dataset lớn, cần horizontal scale

Không có lựa chọn nào tốt hơn tuyệt đối. Với dataset vừa (dưới vài chục GB), Sentinel ít phức tạp hơn và đủ dùng. Khi cần scale memory vượt giới hạn một node, Cluster là lựa chọn tự nhiên.

16

Anti-patterns & Best Practices

Anti-patterns

  • Hash tag quá rộng: dùng {global} hay {app} cho tất cả key → toàn bộ data dồn về một slot → một node chịu 100% tải. Cluster không có tác dụng sharding.
  • Không dùng hash tag cho key liên quan: user:1:profileuser:1:cart nằm khác slot → MGET và transaction fail. Phát hiện muộn khi đã production.
  • Lua script với cross-slot key: EVAL nhận KEYS từ nhiều slot → cluster từ chối ngay. Script phải được thiết kế để tất cả key cùng slot.
  • Master và replica cùng AZ: nếu AZ đó down, mất cả master lẫn replica của cùng shard → slot đó mất, cluster có thể down nếu cluster-require-full-coverage yes.
  • Cluster 3 master không có replica: mất một master → slot orphan → cluster down (với full-coverage) hoặc partial failure.
  • Dùng plain Redis client với cluster: client không hiểu MOVED → mỗi lần redirect là một lỗi không xử lý được. Bắt buộc dùng cluster-aware client.

Best practices

  • Ít nhất 3 master, mỗi master 1 replica trên AZ khác nhau. 5 master cho cluster có khả năng chịu 2 master chết cùng lúc mà vẫn đủ quorum.
  • Chuẩn hóa key naming convention với hash tag ngay từ đầu. Dùng entity ID (userId, orderId) làm hash tag. Document rõ trong codebase.
  • Smart client. redis-py RedisCluster, ioredis cluster mode, Jedis cluster (Java), StackExchange.Redis cluster (C#) đều handle MOVED/ASK tự động.
  • Monitor cluster state. Alert khi cluster_state != ok, khi số node thay đổi, khi có node PFAIL/FAIL. Chi tiết monitoring ở bài 103.
  • Test failover định kỳ. Kill một master node để xác nhận replica promote đúng và client recover trong thời gian chấp nhận được.
  • Cẩn thận với cluster-require-full-coverage yes (mặc định). Nếu use case có thể chấp nhận degraded mode, cân nhắc đổi sang no để tránh toàn cluster down khi mất một shard.
  • Giữ cluster bus port thông thoáng. Port = data port + 10000 phải mở giữa tất cả node. Firewall chặn cluster bus là nguyên nhân phổ biến khiến node không join được cluster.
17

Tổng Kết & Quiz

Điểm cần nhớ

  • Redis Cluster dùng 16384 hash slot cố định. Slot = CRC16(key) mod 16384 → node sở hữu slot đó xử lý key.
  • Hash tag {tag} override phần tên key dùng để hash → gom key liên quan về cùng slot → cho phép multi-key ops và transaction.
  • MOVED: slot chuyển xong, client update map. ASK: slot đang migrate, client không update map, gửi ASKING trước khi retry.
  • Native failover: cluster tự detect FAIL qua gossip quorum và tự promote replica, không cần Sentinel.
  • Multi-key ops (MGET, MSET, MULTI/EXEC, Lua) chỉ hoạt động khi tất cả key cùng slot.
  • Resharding online: không downtime, key đang di chuyển nhận ASK redirect.
  • Tối thiểu 3 master + 3 replica. Master và replica nên đặt khác AZ.

Quiz

  1. Key session:{abc}:datasession:{abc}:meta có nằm cùng slot không? Giải thích tại sao.
  2. Client nhận phản hồi -MOVED 3456 127.0.0.1:7002. Client cần làm gì tiếp theo? So sánh với khi nhận -ASK 3456 127.0.0.1:7002.
  3. Cluster có 3 master. Master thứ 2 không có replica. Master thứ 2 chết. Điều gì xảy ra với cluster (giả sử cluster-require-full-coverage yes)?
  4. Tại sao không nên dùng {global} làm hash tag cho tất cả key trong hệ thống?
  5. Khi resharding slot 5000 từ node A sang node B, tại sao Redis dùng ASK thay vì MOVED trong lúc migration đang chạy?

Đáp án gợi ý

  1. Có. Cả hai key đều chứa {abc} → CRC16 tính trên abc → cùng kết quả → cùng slot. Xác nhận bằng CLUSTER KEYSLOT session:{abc}:dataCLUSTER KEYSLOT session:{abc}:meta.
  2. MOVED: gửi lại lệnh tới 127.0.0.1:7002, cập nhật slot map — các request sau với slot 3456 gửi thẳng tới 7002. ASK: gửi ASKING tới 7002 rồi gửi lại lệnh gốc, nhưng không cập nhật slot map vì slot chưa chuyển hẳn.
  3. Master 2 chết → slot của nó trở thành orphan. Không có replica → không thể failover. Với cluster-require-full-coverage yes, toàn cluster ngừng nhận request ngay lập tức.
  4. Tất cả key đều hash về cùng một slot (slot của global). Slot đó chỉ trên một node → một node chịu toàn bộ tải trong khi các node khác nhàn rỗi. Cluster không scale được.
  5. Slot đang migrate có thể chứa key một phần ở node A (chưa move), một phần đã sang node B. Dùng ASK để redirect từng request mà không cập nhật slot map — client vẫn tiếp tục hỏi node A trước, chỉ khi nhận ASK mới thử node B. Sau khi tất cả key đã sang B, node A gửi MOVED để báo chuyển vĩnh viễn.

Bài tiếp theo

Bài 103 đi vào monitoring Redis: đọc INFO, phân tích SLOWLOG, kiểm tra memory usage, và các metric cần alert trong production.

Tham khảo