Cách khắc phục lỗi Redis 'TRYAGAIN Multiple keys request during rehashing of slot'

intermediate🔴 Redis2026-07-23| Redis Cluster (v3.0 đến v7.x), Linux (Ubuntu, Debian, CentOS, RHEL), môi trường Production trong quá trình resharding hoặc mở rộng node.

Error Message

TRYAGAIN Multiple keys request during rehashing of slot
#redis-cluster#devops#mo-rong-database#loi-redis#backend

Kịch bản lỗiBạn đang mở rộng Redis Cluster bằng cách thêm node thứ tư hoặc cân bằng lại 16.384 slot để xử lý lưu lượng truy cập tăng đột biến. Đột nhiên, log ứng dụng của bạn tăng vọt với một lỗi cụ thể: (error) TRYAGAIN Multiple keys request during rehashing of slot. Điều này thường làm tạm dừng các hoạt động cho bất kỳ lệnh nào liên quan đến nhiều key, chẳng hạn như MGET, MSET, hoặc các script Lua tùy chỉnh.

Lỗi này xảy ra khi một lệnh nhắm mục tiêu vào nhiều key nằm trong cùng một hash slot, nhưng slot đó hiện đang di chuyển giữa các node. Redis không thể đảm bảo tính nguyên tử (atomicity) khi dữ liệu bị chia tách giữa node nguồn và node đích.

Tại sao điều này xảy raRedis Cluster phân chia dữ liệu thành 16.384 hash slot. Khi bạn di chuyển một slot từ Node A sang Node B, slot đó sẽ chuyển sang trạng thái "migrating" trên nguồn và trạng thái "importing" trên đích. Trong quá trình chuyển đổi này, các key được di chuyển theo từng đợt (batch).

Các lệnh đơn key rất dễ xử lý. Nếu key không còn nữa, Node A sẽ gửi một phản hồi chuyển hướng ASK, và client sẽ thử lại trên Node B. Các lệnh đa key thì khác. Nếu lệnh MGET của bạn yêu cầu 10 key, trong đó 7 key đã chuyển sang Node B trong khi 3 key vẫn ở Node A, Redis không thể xử lý yêu cầu trên bất kỳ node nào. Thay vì trả về dữ liệu không đầy đủ hoặc không nhất quán, Redis sẽ đưa ra lỗi TRYAGAIN. Về cơ bản, nó yêu cầu client đợi cho đến khi quá trình di chuyển của đợt cụ thể đó hoàn tất.

Bước 1: Xác định Slot đang di chuyểnĐể khắc phục sự cố, trước tiên bạn phải xác định vị trí của slot đang bị kẹt trong quá trình chuyển đổi. Chạy lệnh này trên bất kỳ node nào trong cluster để xem slot nào hiện đang di chuyển:

redis-cli -p 6379 CLUSTER NODES | grep -E "importing|migrating"

Kết quả đầu ra của bạn sẽ trông như thế này:

node_id_1 192.168.1.10:6379@16379 master - 0 1625000000000 2 connected 0-5460 [5461->-node_id_2]
node_id_2 192.168.1.11:6379@16379 master - 0 1625000000000 3 connected 5462-10922 [5461-<-node_id_1]

Trong trường hợp cụ thể này, slot 5461 đang ở giữa quá trình di chuyển. Bất kỳ lệnh đa key nào tác động đến các key trong slot 5461 sẽ thất bại cho đến khi quá trình di chuyển kết thúc.

Bước 2: Triển khai logic thử lại phía ứng dụngVì TRYAGAIN là một lỗi tạm thời, nó thường được giải quyết trong vòng vài mili giây. Không giống như lỗi MOVED vốn ám chỉ sự thay đổi cấu trúc liên kết (topology) vĩnh viễn, TRYAGAIN chỉ yêu cầu tạm dừng một chút. Nếu bạn đang sử dụng Python (redis-py), hãy bao bọc các lệnh gọi đa key của mình trong một vòng lặp thử lại.

import time
import redis

def execute_with_retry(client, keys, max_retries=5):
    attempt = 0
    while attempt < max_retries:
        try:
            return client.mget(keys)
        except redis.exceptions.ResponseError as e:
            if "TRYAGAIN" in str(e):
                # Đợi 25ms trước khi thử lại
                time.sleep(0.025)
                attempt += 1
                continue
            raise e
    raise Exception(f"Lệnh thất bại sau {max_retries} lần thử lại do đang di chuyển slot.")

Bước 3: Giải quyết các nút thắt cổ chai về hạ tầngNếu lỗi kéo dài hơn vài giây, quá trình di chuyển của bạn có thể đã bị đình trệ. Điều này thường xảy ra nếu một slot chứa một "hot key" hoặc một cấu trúc dữ liệu O(N) khổng lồ mất nhiều thời gian để tuần tự hóa và truyền tải.

Tăng tốc độ di chuyểnTăng tốc quá trình bằng cách tăng kích thước pipeline. Theo mặc định, redis-cli di chuyển các key một cách chậm rãi để tránh làm tăng vọt CPU. Bạn có thể tăng tốc việc này bằng cách di chuyển 100 key mỗi lượt thay vì một:

redis-cli --cluster reshard <ip>:<port> --cluster-pipeline 100

Cố định trạng thái SlotNếu một quá trình di chuyển bị treo hoàn toàn, bạn có thể cần phải đặt trạng thái slot thành ổn định (stable) một cách thủ công. Chỉ thực hiện việc này nếu bạn đã xác nhận dữ liệu tồn tại trên đích hoặc nếu bạn có kế hoạch chạy lệnh fix ngay sau đó. Trên cả node nguồn và node đích, hãy chạy:

redis-cli -h <node_ip> -p 6379 CLUSTER SETSLOT 5461 NODE <destination_node_id>

Xác minhXác nhận cluster đã trở lại trạng thái khỏe mạnh bằng cách chạy công cụ kiểm tra:

redis-cli --cluster check 192.168.1.10:6379

Tìm dòng xác nhận: [OK] All 16384 slots covered. Nếu bạn thấy thông báo "Nodes don't agree about configuration," hãy chạy redis-cli --cluster fix để đồng bộ hóa bản đồ slot.

Các thực hành tốt nhất để ngăn chặn TRYAGAIN- Sử dụng Hash Tag: Ép các key liên quan vào cùng một slot bằng cách sử dụng dấu ngoặc nhọn, như {user:100}:profile{user:100}:orders. Điều này đảm bảo các hoạt động đa key có thể thực hiện được về mặt vật lý trong một cluster, ngay cả khi nó không loại bỏ hoàn toàn các khoảng thời gian di chuyển.- Theo dõi tiến trình di chuyển: Không bao giờ kích hoạt quá trình chia lại slot (resharding) nặng nề trong giờ cao điểm. Sử dụng watch -n 1 "redis-cli cluster nodes | grep migrating" để theo dõi tiến trình trong thời gian thực.- Chia nhỏ các key lớn: Một Hash hoặc Set duy nhất với 500.000 phần tử sẽ chặn quá trình di chuyển của toàn bộ slot chứa nó. Hãy giữ các key của bạn ở kích thước nhỏ để đảm bảo quá trình di chuyển hoàn tất trong khoảng thời gian dưới một giây.

Related Error Notes