INFO trả về hơn hai trăm dòng. Bài này đo xem dòng nào báo sớm, dòng nào báo muộn, và dòng nào không báo gì cả.

Diễn biến bộ nhớ khi chạm giới hạn, và bốn nguồn thông tin về một lệnh chậm

used_memory dừng ở 100% và ở đó mãi

Tôi nạp dữ liệu đều tay vào một Redis giới hạn 64 MB với chính sách allkeys-lru:

Giây used_memory % maxmemory Khoá bị đuổi mỗi giây
2 10.787.720 16,1% 0
8 37.418.432 55,8% 0
14 65.074.352 97,0% 0
16 67.142.720 100,1% 12.339
18 67.122.448 100,0% 15.102
24 67.122.240 100,0% 15.870

Từ giây 16 trở đi, tỉ lệ phần trăm không còn nói gì nữa. Nó ghim ở 100% dù tình hình tệ đến đâu.

Cảnh báo đặt trên used_memory / maxmemory > 90% cho bạn đúng 2 giây báo trước — từ 97% ở giây 14 lên 100% ở giây 16. Với tốc độ nạp thật của một hệ thống production, cửa sổ đó có thể rộng hơn, nhưng bản chất không đổi: đó là chỉ số bão hoà, không phải chỉ số cảnh báo.

Cái nói lên mức độ nghiêm trọng là tốc độ đuổi khoá: 0 → 12.339 → 15.870 mỗi giây. Con số đó tiếp tục tăng khi tình hình xấu đi, còn phần trăm thì không.

Nên cảnh báo đúng là:

rate(redis_evicted_keys_total[5m]) > 0

Bất kỳ giá trị nào lớn hơn 0 đều đáng nhìn, vì nó nghĩa là bộ đệm đang vứt đi thứ nó vừa nhận.

Bốn nguồn cho cùng một lệnh chậm

Redis có bốn cách nhìn vào hiệu năng lệnh, và chúng trả lời bốn câu hỏi khác nhau.

INFO commandstats — lệnh nào tốn nhất

cmdstat_keys: calls=2   usec_per_call=11576.50
cmdstat_get : calls=200 usec_per_call=0.06

get 0,06 µs so với keys 11.576 µs — chênh gần 200.000 lần. Độ trễ trung bình toàn cục không bao giờ thấy điều này; commandstats thấy ngay.

Đây là nơi bắt đầu mọi cuộc điều tra hiệu năng: sắp xếp theo usec_per_call × calls để biết loại lệnh nào đang ăn hết luồng duy nhất.

INFO latencystats — phân bố, không phải trung bình

keys: p50=11206.655  p99=13762.559

Redis 7 thêm mục này, và nó là thứ commandstats thiếu: trung bình che mất đuôi. Một lệnh có p50 0,1 ms và p99 50 ms là vấn đề mà usec_per_call không hiện.

LATENCY LATEST — thời điểm có sự cố

command  1788208869  13 ms  max 13 ms

Ghi lại sự kiện vượt ngưỡng latency-monitor-threshold, kèm dấu thời gian. Dùng để trả lời "lúc 3 giờ sáng có gì bất thường không".

SLOWLOG GET — chính xác lệnh nào

13732 us  keys *  127.0.0.1:49110

Đây là nguồn duy nhất cho bạn tham số thậtđịa chỉ khách. Ba nguồn kia nói loại lệnh; cái này nói ai gọi và gọi gì.

Mười chỉ số đáng đưa lên bảng điều khiển

Chỉ số Vì sao
evicted_keys (tốc độ) Bộ nhớ đầy, đo được ở trên
keyspace_misses / (hits+misses) Tỉ lệ trượt bộ đệm
instantaneous_ops_per_sec Tải hiện tại
connected_clients so với maxclients Trần kết nối (phần 31)
blocked_clients Worker đang chờ, và có đang tăng bất thường không
mem_fragmentation_ratio kèm used_memory Chỉ có nghĩa khi dữ liệu đủ lớn (phần 10)
rdb_changes_since_last_save Lượng sẽ mất nếu chết ngay (phần 18)
master_repl_offset trừ offset bản sao Lượng sẽ mất khi chuyển đổi (phần 21)
rejected_connections Đã chạm maxclients
latency_percentiles_usec_* Đuôi độ trễ theo lệnh

Ba chỉ số gây hiểu nhầm

used_memory_rss và tỉ lệ phân mảnh. Như đo ở phần 10: một instance gần rỗng có tỉ lệ 16,59 và hoàn toàn khoẻ. Chỉ đọc nó khi used_memory đã đủ lớn, và ưu tiên allocator_frag_bytes.

Độ trễ trung bình. Phần 11 đo được: một lệnh KEYS đẩy max lên 263 ms trong khi p50 gần như không đổi. Trung bình che mất đúng thứ người dùng cảm nhận.

connected_clients một mình. Con số này ổn định không có nghĩa mọi thứ ổn — có thể là các kết nối rò rỉ đang giữ chỗ, như phần 31. Đọc kèm idle trong CLIENT LIST.

Ba cảnh báo tối thiểu

Nếu chỉ đặt được ba, đây là ba:

1. rate(evicted_keys) > 0                    bo nho da day
2. rdb_changes_since_last_save > <nguong>    dang khong duoc luu
3. rejected_connections tang                 da cham maxclients

Cả ba đều là sự kiện rời rạc chứ không phải ngưỡng trên một đại lượng liên tục — và đó chính là điểm mạnh của chúng: chúng không có vấn đề "ghim ở 100%" như phần trăm bộ nhớ.

Cách lấy chỉ số

INFO là một lệnh rẻ nhưng không miễn phí: nó duyệt vài cấu trúc và sinh ra một chuỗi vài KB. Gọi mỗi giây từ mười bộ thu thập là một khoản tải thật trên luồng duy nhất.

Gọi INFO mỗi 10–15 giây là đủ cho gần như mọi mục đích. Với INFO all (gồm commandstatslatencystats) thì chi phí cao hơn nữa — chúng duyệt toàn bộ bảng lệnh.

CONFIG RESETSTAT xoá commandstats, latencystats và các bộ đếm. Hữu ích để đo một cửa sổ sạch, nhưng nó cũng làm mọi bộ thu thập khác thấy con số nhảy về 0 — đừng gõ nó trên production khi có ai đang theo dõi.

Thử ba mươi giây

Lấy bức tranh đầy đủ trong một lệnh:

redis-cli info | grep -E \
  'used_memory:|maxmemory:|evicted_keys|expired_keys|keyspace_hits|keyspace_misses|connected_clients|blocked_clients|rejected_connections|instantaneous_ops_per_sec|rdb_changes_since_last_save|master_repl_offset'

Rồi tìm lệnh đang ăn nhiều thời gian nhất:

redis-cli info commandstats | python3 -c '
import sys, re
rows = []
for line in sys.stdin:
    m = re.match(r"cmdstat_(\S+?):calls=(\d+),usec=(\d+),usec_per_call=([\d.]+)", line)
    if m: rows.append((int(m.group(3)), m.group(1), int(m.group(2)), float(m.group(4))))
rows.sort(reverse=True)
print("%10s  %10s  %12s  %s" % ("tong (s)", "so lan", "us moi lan", "lenh"))
for usec, name, calls, per in rows[:10]:
    print("%10.3f  %10d  %12.2f  %s" % (usec/1e6, calls, per, name))
'

Kết quả trên chính instance vừa đo:

  tong (s)      so lan    us moi lan  lenh
     0.046           4      11576.50  keys
     0.010           2       4786.00  eval
     0.000           5         70.00  info
     0.000         200          0.06  get

Cột đầu là tổng số giây CPU mà mỗi loại lệnh đã tiêu. Dòng đầu bảng là thứ đang chiếm luồng duy nhất của bạn — và nó thường không phải lệnh bạn đoán. Ở đây, 4 lệnh keys tốn nhiều CPU hơn 200 lệnh get gấp hàng nghìn lần.

Phần sau: nhật ký lệnh chậm — cách bắt và cách đọc.