Phần 23 đo Cluster và thấy CRC16 rải khoá rất đều. Bài này đo chuyện gì xảy ra khi nó không đều — và tìm ra rằng hậu quả không nằm ở chỗ tôi tưởng.
Một thẻ băm biến ba nút thành một
20.000 khoá, cụm 3 nút:
tên khoá k:1 ... k:20000 -> 6.663 | 6.669 | 6.668
tên khoá {khach}:1 ... {khach}:N -> 0 | 0 | 20.000
Cùng số khoá, cùng cụm. Chỉ khác một cặp ngoặc nhọn.
Như đo ở phần 23, chỉ phần trong {} được băm. Mọi khoá mang cùng thẻ nằm cùng một slot, và một slot nằm trên một nút.
Hai nút giữ đúng số không.
Nhưng lệch không đồng nghĩa với chậm
Đây là chỗ tôi trông đợi thấy hậu quả rõ ràng và không thấy.
3 kết nối, không đường ống:
tất cả vào MỘT nút 37.137 | 34.353 ops/s
trải đều ba nút 34.368 | 34.120 ops/s
Lệch hoàn toàn mà không chậm hơn. Đo hai lần, cùng kết quả.
Lý do đã được đo ở phần 2: với lệnh gọi từng cái một, nút thắt là số lượt đi về, không phải sức của nút. Ba kết nối tạo ra khoảng 34.000 lệnh mỗi giây bất kể chúng đi tới một nút hay ba nút — và một nút Redis xử lý con số đó mà gần như không phải cố gắng.
Trần thật của một nút
Ba kết nối có đường ống 200 vào cùng một nút:
1.229.164 ops/s
Một nút đơn chịu được trên một triệu lệnh mỗi giây.
Nên phân mảnh lệch chỉ bắt đầu là vấn đề về tốc độ khi lưu lượng của bạn tiến gần con số đó. Dưới ngưỡng, nó không tốn của bạn một mili giây nào.
Điều này đảo ngược một trực giác phổ biến: người ta lo khoá nóng vì nghĩ nó làm chậm hệ thống. Với phần lớn hệ thống, nó không. Điều đáng lo nằm ở chỗ khác.
Cái lệch luôn tốn ngay lập tức: bộ nhớ
Hai nút trống rỗng trong khi một nút giữ hết.
Cụm ba nút có RAM của ba máy, nhưng sức chứa thật bằng một máy. Bạn trả tiền cho ba, dùng được một.
Và khi nút đó chạm maxmemory, nó bắt đầu đuổi khoá hoặc từ chối ghi — như đo ở phần 9 — trong khi hai nút kia còn trống nguyên. Cụm không tự cân bằng lại được, vì slot đã gắn với nút.
Đây mới là lý do chính để tránh thẻ băm quá rộng, không phải tốc độ.
Thẻ băm nên rộng đến đâu
Quy tắc: thẻ nên gom đúng những khoá cần dùng chung trong một lệnh nhiều khoá, không hơn.
{u:12345}:ho-so tốt — vài khoá mỗi người dùng
{u:12345}:gio-hang
{u:12345}:phien
{khach}:12345 xấu — mọi người dùng vào một slot
{san-pham}:98765 xấu — mọi sản phẩm vào một slot
Với {u:12345}, số slot khác nhau bằng số người dùng — rải đều tự nhiên. Với {khach}, có đúng một slot.
Cách kiểm nhanh: thẻ có bao nhiêu giá trị khác nhau? Dưới vài nghìn là dấu hiệu xấu; cụm 16.384 slot cần ít nhất vài chục nghìn giá trị khác nhau để rải đều.
Khoá nóng theo lưu lượng, không theo dữ liệu
Có một dạng lệch thứ hai mà số khoá không thấy được: một khoá duy nhất nhận phần lớn lượt đọc. Ví dụ cấu hình toàn cục, danh sách bài nổi bật, tỉ giá.
Khoá đó nằm trên một nút, và nút đó nhận toàn bộ lưu lượng. Với ngưỡng một triệu ops/s đo được ở trên, phần lớn hệ thống vẫn không sao. Nhưng khi có sao, có ba cách:
- Đệm ở phía ứng dụng. Giá trị đọc nhiều mà đổi ít nên nằm trong bộ nhớ tiến trình với TTL vài giây. Đây là cách rẻ nhất và hiệu quả nhất.
- Nhân bản khoá.
cauhinh:0đếncauhinh:9, khách chọn ngẫu nhiên. Mười khoá rơi vào mười slot khác nhau. Đổi lại: cập nhật phải ghi cả mười. - Đọc từ bản sao. Cluster cho phép đọc từ bản sao bằng
READONLY, chia lưu lượng đọc ra hai máy.
Chuyển slot khi đã lệch
Nếu đã lỡ lệch, redis-cli --cluster rebalance không cứu được — nó cân bằng số slot, không cân bằng số khoá. Một slot chứa 20.000 khoá vẫn là một slot.
Cách duy nhất là đổi tên khoá, tức là ghi lại dữ liệu với thẻ băm mới. Đây là dự án di trú, và đó là lý do việc chọn thẻ băm đúng ngay từ đầu quan trọng đến vậy.
Thử ba mươi giây
Xem cụm của bạn có lệch không, và lệch ở đâu:
# so khoa tren tung nut chinh
for n in $(redis-cli --cluster call <mot-nut>:6379 dbsize 2>/dev/null | grep -B1 '^[0-9]'); do
echo "$n"
done
# hoac don gian hon
redis-cli --cluster info <mot-nut>:6379
--cluster info in số khoá của từng nút. Lệch quá hai lần giữa nút nhiều nhất và ít nhất là dấu hiệu có thẻ băm quá rộng.
Tìm thủ phạm:
redis-cli --scan --count 500 | head -5000 | \
grep -o '{[^}]*}' | sort | uniq -c | sort -rn | head -10
Thẻ nào xuất hiện hàng nghìn lần chính là thẻ đang gom mọi thứ vào một slot. Nếu dòng đầu bảng chiếm phần lớn tổng số, bạn đã tìm ra.
Phần sau: kích thước khoá và giá trị lớn — đo lúc nào chúng bắt đầu gây nghẽn.