Bản sao là cơ chế Kafka dùng để không mất dữ liệu khi máy chết. Bài này giết máy thật và bấm giờ.
Đọc một dòng describe
Topic: r3 Partition: 0 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2
Ba cột, ba nghĩa khác nhau:
Replicas— broker nào giữ bản sao. Cố định, do lúc tạo topic quyết định.Isr— broker nào đang theo kịp (in-sync replica). Thay đổi liên tục.Leader— broker nào nhận ghi và phục vụ đọc. Luôn là một phần tử củaIsr.
Một chi tiết quan trọng và hay bị bỏ qua: phần tử đầu tiên của Replicas là "leader ưu tiên". Kafka cố gắng giữ nó làm leader, và lúc tạo topic nó rải các leader ưu tiên đều trên các broker. Cuối bài sẽ thấy vì sao chỗ này đáng nhớ.
"Theo kịp" nghĩa là follower đã yêu cầu dữ liệu trong vòng replica.lag.time.max.ms (mặc định 30.000 ms). Không phải "đã có đủ mọi tin" — một follower chậm 5 giây vẫn nằm trong ISR.
Giết một broker
Cụm 3 broker, topic 6 partition, replication-factor=3. kb3 đang làm leader cho 2 partition. docker kill kb3:
bầu xong leader mới cho mọi partition: 9.142 ms
kb3 bị loại khỏi ISR: 9.142 ms
Chín giây. Con số đó không ngẫu nhiên: nó là broker.session.timeout.ms, mặc định 9.000 ms. Đó là thời gian controller đợi trước khi tuyên bố một broker đã chết.
Trước khi hết thời gian đó, controller vẫn coi kb3 còn sống và không làm gì cả. Mọi partition mà kb3 làm leader đều không phục vụ được trong chín giây đó.
Producer thấy gì trong chín giây ấy
Cho producer gửi đều 2.000 tin/giây với acks=all, rồi giết kb3 giữa chừng. Số liệu theo từng khoảng báo cáo:
| Giai đoạn | Thông lượng | Độ trễ lớn nhất |
|---|---|---|
| trước | 1.999 tin/giây | 917 ms |
| lúc giết | 481 tin/giây | 8.759 ms |
| ngay sau | 5.503 tin/giây | 11.766 ms |
| sau đó | 2.000 tin/giây | 5 ms |
Ba điều đọc được từ bảng này.
Không mất tin nào. Tổng số tin gửi đi vẫn đủ. Producer giữ chúng trong bộ đệm và gửi lại khi có leader mới.
Nhưng có tin mất 11,7 giây mới tới nơi. Nếu ứng dụng của bạn có ngưỡng thời gian chờ dưới 12 giây cho việc gửi, nó sẽ báo lỗi trong khoảng này — dù Kafka cuối cùng vẫn ghi được.
Khoảng bù dồn cũng là một vấn đề. Khoảng ngay sau chạy ở 5.503 tin/giây, gấp 2,75 lần bình thường. Consumer phía sau nhận đột ngột gấp ba lưu lượng, và nếu nó không chịu nổi thì sự cố lan sang chỗ khác.
Muốn phát hiện nhanh hơn thì hạ broker.session.timeout.ms. Cái giá: một nhịp mạng chậm hoặc một lần GC dài cũng đủ bị coi là chết, và bầu lại leader không cần thiết. Mặc định 9 giây là chỗ cân bằng hợp lý cho mạng trong một trung tâm dữ liệu.
Broker sống lại nhưng không lấy lại việc
Đây là phần bất ngờ nhất. Cho kb2 khởi động lại, đợi tới khi nó vào lại đủ ISR của cả 6 partition:
p0 Leader: 3 p1 Leader: 1 p2 Leader: 3
p3 Leader: 3 p4 Leader: 1 p5 Leader: 3
kb3 gánh 4 partition, kb1 gánh 2, kb2 gánh 0
kb2 nằm trong ISR của cả sáu partition — nó đang sao chép đủ mọi thứ, tốn đủ băng thông và đĩa — nhưng không phục vụ một yêu cầu nào. Toàn bộ tải đọc và ghi dồn lên hai broker còn lại.
Theo cột Replicas, kb2 là leader ưu tiên của p2 và p5. Nó chỉ cần được trao lại:
kafka-leader-election.sh --bootstrap-server kb1:9092 \
--election-type preferred --all-topic-partitions
Successfully completed leader election (PREFERRED) for partitions r3-2, r3-5
Sau lệnh này tải về đều 2–2–2.
Kafka có cơ chế tự làm việc này — auto.leader.rebalance.enable bật mặc định — nhưng nó chạy theo chu kỳ leader.imbalance.check.interval.seconds, mặc định 300 giây. Nghĩa là sau mỗi lần khởi động lại một broker, cụm chạy lệch tải tới năm phút trước khi tự cân lại.
Với triển khai cuốn chiếu ba broker, đó là mười lăm phút chạy lệch — và nếu bạn khởi động lại broker tiếp theo trước khi chu kỳ đó chạy, tình trạng lệch chồng lên nhau. Chạy tay lệnh trên sau mỗi lần khởi động lại là thói quen đáng có.
Cách nhìn nhanh trạng thái
Một partition thiếu bản sao là partition có Isr ngắn hơn Replicas:
kafka-topics.sh --bootstrap-server kb1:9092 --describe --under-replicated-partitions
Lệnh này im lặng là cụm khoẻ. Có dòng nào hiện ra là có follower đang tụt lại — và với min.insync.replicas=2 trên replication-factor=3, bạn chỉ còn một mức dự phòng nữa trước khi việc ghi bị chặn.
Còn một lệnh nữa quan trọng hơn nhiều người nghĩ:
kafka-topics.sh --bootstrap-server kb1:9092 --describe --unavailable-partitions
Nó liệt kê partition không có leader — tức là không đọc được, không ghi được. Đây là chỉ báo sự cố thật, còn under-replicated chỉ là cảnh báo sớm.
Đặt replication-factor bao nhiêu
- 1 — không có bản sao. Broker chết là mất dữ liệu vĩnh viễn. Chỉ dùng cho dữ liệu tạm dựng lại được.
- 2 — chịu được một broker chết, nhưng không kết hợp được với
min.insync.replicas=2: mất một broker là ghi bị chặn ngay. Vị trí khó chịu. - 3 — mặc định thực dụng. Với
min.insync.replicas=2, chịu được một broker chết mà vẫn ghi bình thường. - Trên 3 — chỉ khi dữ liệu cực kỳ quan trọng hoặc bản sao trải trên nhiều vùng. Mỗi bản sao thêm là thêm một lần ghi đĩa và một luồng sao chép qua mạng.
Cần ít nhất replication-factor broker để tạo topic. Cụm 3 broker thì replication-factor=3 là trần.
Thử ba mươi giây
Kiểm cụm của bạn có đang chạy lệch leader không:
kafka-topics.sh --bootstrap-server kb1:9092 --describe \
| grep -oE "Leader: [0-9]+" | sort | uniq -c | sort -rn
Nếu một broker có nhiều partition hơn hẳn broker khác, gần như chắc chắn vừa có một lần khởi động lại và chu kỳ cân bằng chưa chạy tới. Lệnh --election-type preferred chữa trong vài giây.
Phần sau đo min.insync.replicas: chính xác lúc nào producer bị chặn, và một cách hỏng mà con số đó không cứu được.