Lag là chỉ số quan trọng nhất của một hệ thống Kafka, và cũng là chỉ số bị đặt cảnh báo sai nhiều nhất. Bài này đo cùng một trạng thái theo hai cách và cho thấy vì sao cách phổ biến gần như vô dụng.

Lag theo tin và theo thời gian, cách tính đúng, và bốn cách tính sai

Cùng một trạng thái, hai con số

Một nhóm consumer đã ngừng đọc, đo được:

Partition Lag theo tin Lag theo thời gian
p0 511.277 102,6 giây
p1 511.386 102,6 giây
p2 511.319 102,6 giây
p3 518.058 102,6 giây

Tổng lag theo tin là 2.052.040. Nghe rất tệ, nhưng không hành động được: hai triệu tin là nhiều hay ít? Bao lâu nữa thì đuổi kịp? Dữ liệu hạ nguồn đang cũ cỡ nào?

102,6 giây trả lời tất cả những câu đó ngay lập tức: dữ liệu hạ nguồn đang cũ hơn hai phút.

Sự khác biệt trở nên rõ hơn khi so hai topic:

100.000 tin lag ở tốc độ 20.000 tin/giây   =  5 giây
100.000 tin lag ở tốc độ     10 tin/giây   =  2,8 GIỜ

Cùng một con số, chênh nhau hai nghìn lần về ý nghĩa. Đây là lý do một ngưỡng cố định theo số tin không dùng chung được cho hai topic khác nhau — và trong một cụm thật thì có hàng chục topic với tốc độ khác nhau hàng nghìn lần.

Cách tính lag thời gian

Ba bước, và không cần công cụ đặc biệt nào:

  1. Lấy CURRENT-OFFSET của partition từ kafka-consumer-groups --describe.
  2. Đọc đúng bản ghi tại offset đó và lấy dấu thời gian của nó.
  3. lag thời gian = bây giờ − dấu thời gian đó.
kafka-consumer-groups.sh --bootstrap-server kf:9092 --describe --group nhom \
  | awk 'NR>1 && $6 ~ /^[0-9]+$/ {print $3, $4}' \
  | while read P CUR; do
      T=$(kafka-console-consumer.sh --bootstrap-server kf:9092 --topic ten-topic \
          --partition $P --offset $CUR --max-messages 1 \
          --property print.timestamp=true --timeout-ms 6000 2>/dev/null \
          | grep -oE "CreateTime:[0-9]+" | cut -d: -f2)
      echo "p$P  tre $(( ($(date +%s%3N) - T) / 1000 )) giay"
    done

Cách này đúng cả khi lưu lượng thay đổi, và — quan trọng hơn — đúng cả trên topic có giao dịch, nơi hiệu số offset không bao giờ về 0.

Nếu bạn dùng Burrow hoặc Kafka Lag Exporter, chúng đã tính sẵn con số này. Nếu bạn tự dựng bảng theo dõi, đây là thứ đáng dựng.

Bốn cách tính lag sai

1. Ngưỡng cố định theo số tin.

Cùng một ngưỡng lag > 100.000 áp cho topic 20.000 tin/giây và topic 10 tin/giây sẽ hoặc kêu suốt ngày ở cái đầu, hoặc không bao giờ kêu ở cái sau. Không có con số nào đúng cho cả hai.

2. Cảnh báo ở lag > 0 trên topic có giao dịch.

Phần 26 đã đo: giao dịch cỡ 100 để lại 1.000 bản ghi điều khiển chiếm offset mà không consumer nào đọc được. Consumer đã đọc hết mọi thứ vẫn hiện lag = 1.000, mãi mãi. Cảnh báo ở > 0 sẽ kêu liên tục cho tới khi có người tắt nó đi — và khi có sự cố thật thì không còn ai nhìn nữa.

3. Cộng lag của mọi partition rồi cảnh báo trên tổng.

Một partition kẹt hoàn toàn bị chín partition khoẻ pha loãng. Với topic 10 partition, một partition không có consumer nào đọc chỉ đẩy tổng lag lên 10% — dưới mọi ngưỡng hợp lý — trong khi một phần mười dữ liệu của bạn đang dừng.

Cảnh báo phải chạy trên lag lớn nhất của một partition, không trên tổng.

4. Đếm lag qua một danh sách hiển thị bị giới hạn.

Công cụ và giao diện thường cắt ở 50 hay 100 dòng. Đếm qua danh sách đó thì con số trần ở 50 — càng kẹt nhiều càng sai, đúng vào lúc cần con số đúng nhất. Luôn tính bằng truy vấn, không tính qua thứ đã hiển thị.

Cảnh báo đúng: theo xu hướng

Ngưỡng theo mức đòi bạn biết trước "bao nhiêu là nhiều", và với hàng chục topic khác nhau thì không ai biết.

Xu hướng thì không cần biết:

lag tăng liên tục trong 10 phút   ->  cảnh báo

Nó bắt được mọi tốc độ. Consumer khoẻ có lag dao động quanh một mức; consumer không theo kịp có lag tăng đơn điệu. Đó là dấu hiệu rõ ràng và không phụ thuộc quy mô.

Kết hợp với một ngưỡng thời gian cứng cho những đường ống có yêu cầu rõ ràng:

lag thời gian > 5 phút trên topic don-hang   ->  cảnh báo

Con số 5 phút này đến từ nghiệp vụ, không từ kỹ thuật — và đó là điều khiến nó đúng.

Lag âm, và lag của nhóm không có ai

Hai tình huống hay gây bối rối trong --describe:

CONSUMER-ID- nghĩa là partition đó không có consumer nào đang giữ. Lag vẫn được tính (từ offset đã chốt lần cuối tới cuối log), nhưng không ai đang xử lý. Đây là tình huống nghiêm trọng hơn lag cao, và nó không hiện ra trong bất kỳ con số lag nào.

Đếm nó riêng:

kafka-consumer-groups.sh --bootstrap-server kf:9092 --describe --group nhom \
  | awk 'NR>1 && $7=="-" {n++} END {print n+0, "partition khong co consumer"}'

Lag hiện rỗng hoặc âm xảy ra khi nhóm chưa bao giờ chốt offset cho partition đó. Không phải lỗi — chỉ là chưa có gì để so.

Lag không phải lúc nào cũng là lỗi của consumer

Ba nguyên nhân, và chỉ nguyên nhân đầu tiên là "consumer chậm":

Consumer xử lý chậm. Chữa bằng cách tăng số consumer — nhưng chỉ tới trần là số partition (phần 11). Hết partition thì phải tối ưu chính việc xử lý.

Producer tăng đột ngột. Lag tăng trong khi consumer vẫn chạy đúng tốc độ cũ. Đồ thị MessagesInPerSec của broker phân biệt được hai trường hợp này ngay.

Nhóm đang cân bằng lại. Phần 9 đo được 3 giây cho kiểu hợp tác, và phần 27 đo được 44 giây cho một ứng dụng Streams khởi động lại nhanh. Trong khoảng đó không ai đọc gì và lag tăng — rồi tự hết. Cảnh báo có độ trễ 5–10 phút sẽ không kêu vì chuyện này.

Nếu bảng theo dõi của bạn chỉ có lag mà không có tốc độ ghi, bạn không phân biệt được ba trường hợp trên, và mọi sự cố lag đều bắt đầu bằng việc đoán.

Thử ba mươi giây

Tìm partition tệ nhất của bạn, không phải tổng:

kafka-consumer-groups.sh --bootstrap-server kf:9092 --all-groups --describe 2>/dev/null \
  | awk 'NR>1 && $6 ~ /^[0-9]+$/ {print $6, $1, $2, $3, $7}' \
  | sort -rn | head -10

Mười dòng đầu là mười chỗ đau nhất trong cụm. Nếu cột cuối là -, partition đó không có ai đọc — và đó là dòng đáng xem trước mọi dòng khác.

Phần sau đo bảo mật: TLS, SASL và cái giá thật của việc bật chúng.