Về trang blog
Series: Kafka từ A-Z · Bài 6/6
Kafka trong Production
Monitoring, Tuning & Common Issues

Naming conventions & topic design

Topic name không thể đổi sau khi tạo — đặt tên cẩn thận từ đầu:

naming convention
# Pattern: {domain}.{entity}.{event-type}.{version}
orders.order.placed.v1
orders.order.paid.v1
inventory.product.stock-updated.v1
users.user.registered.v1
payments.payment.failed.v2

# Internal topics bắt đầu bằng _
_orders.order.placed.v1.dlq       # Dead letter queue
__consumer_offsets                  # Kafka internal (đừng động vào)
Best practices
  • Luôn dùng chữ thường, phân cách bằng dấu . hoặc -
  • Không dùng _ (khó phân biệt với Kafka internal topics)
  • Thêm version (.v1, .v2) để migrate schema không breaking
  • Đặt tên topic theo event đã xảy ra (past tense): order-placed không phải place-order

Key metrics cần monitor

consumer_lag
Số message consumer chưa xử lý. Metric quan trọng nhất.
⚠ Alert khi lag tăng liên tục > 5 phút
MessagesInPerSec
Tốc độ message vào cluster. Dùng để capacity planning.
Theo dõi spike bất thường
BytesInPerSec / BytesOutPerSec
Network throughput. Đảm bảo không saturate NIC.
Alert khi > 80% capacity NIC
UnderReplicatedPartitions
Số partition không đủ replica. Dấu hiệu broker lag hoặc down.
Alert khi > 0 trong production
OfflinePartitionsCount
Số partition hoàn toàn offline, không có leader. Nghiêm trọng nhất.
Alert ngay lập tức khi > 0
ActiveControllerCount
Phải luôn bằng 1 trong cluster. 0 = mất controller, >1 = split-brain.
Alert khi != 1
RequestHandlerAvgIdlePercent
% idle của request handler threads. Thấp = broker đang quá tải.
Alert khi < 20%
LogEndOffset
Offset cuối cùng của partition. Kết hợp với committed offset để tính lag.
Dùng để trending

Prometheus + JMX Exporter

Kafka expose metrics qua JMX. Cần JMX Exporter để convert sang Prometheus format.

docker-compose.yml — thêm JMX exporter
  kafka:
    image: apache/kafka:3.9.0
    environment:
      KAFKA_JMX_PORT: 9101
      KAFKA_JMX_HOSTNAME: kafka
        # ... other configs

  kafka-jmx-exporter:
    image: bitnami/jmx-exporter:latest
    ports:
      - "5556:5556"
    environment:
      JMX_HOST: kafka
      JMX_PORT: 9101"
    volumes:
      - ./kafka-jmx-config.yml:/opt/bitnami/jmx-exporter/etc/jmx_config.yml"
Grafana dashboard
Dùng Grafana dashboard ID 7589 (Kafka Overview by Operato) hoặc 721 (Kafka Metrics) — import thẳng vào Grafana từ grafana.com, không cần tự build từ đầu. Kết hợp với AKHQ hoặc Kafka UI để có cả web console.

Common issues và cách fix

IssueTriệu chứngRoot causeFix
Consumer lag tăng Lag metric tăng liên tục Consumer xử lý chậm hơn producer viết Scale horizontal consumer (thêm instance), tối ưu processing code, tăng max.poll.records
Rebalance storm Log liên tục "Rebalancing", lag nhảy vọt max.poll.interval.ms quá ngắn, xử lý chậm Tăng max.poll.interval.ms, dùng async processing, batch nhỏ hơn
Disk full Broker down, LEADER_NOT_AVAILABLE Retention quá cao hoặc disk nhỏ Giảm retention.ms hoặc retention.bytes, thêm disk/broker
Message too large RecordTooLargeException Message vượt message.max.bytes (1MB default) Tăng message.max.bytes (broker) và max.request.size (producer), hoặc split message
Hot partition Một partition nhận 80%+ traffic Key có cardinality thấp (region, status) Thêm salt vào key, dùng custom partitioner, hoặc bỏ key (round-robin)
Duplicate messages Database có record trùng Auto-commit trước khi xử lý xong, hoặc consumer crash Manual commit sau xử lý, implement idempotent consumer (check-before-insert)

Kafka Connect

Kafka Connect là framework để tích hợp Kafka với external systems (database, S3, Elasticsearch...) mà không cần viết code. Chỉ cần cấu hình JSON.

Source Connector — dữ liệu vào Kafka

  • Debezium MySQL/Postgres — CDC, đọc binlog → stream mọi INSERT/UPDATE/DELETE
  • JDBC Source — polling database định kỳ
  • S3 Source — đọc file từ S3 vào Kafka

Sink Connector — dữ liệu ra ngoài Kafka

  • S3 Sink — archive Kafka data vào S3 (Parquet, JSON, Avro)
  • Elasticsearch Sink — index document để search
  • JDBC Sink — upsert vào database
  • BigQuery/Snowflake Sink — stream vào data warehouse
json — Debezium MySQL source connector config
{
  "name": "mysql-orders-cdc",
  "config": {
    "connector.class": "io.debezium.connector.mysql.MySqlConnector",
    "database.hostname": "mysql",
    "database.port": "3306",
    "database.user": "debezium",
    "database.password": "dbz",
    "database.server.id": "184054",
    "database.include.list": "shop",
    "table.include.list": "shop.orders",
    "topic.prefix": "mysql"
    // output topic: mysql.shop.orders
  }
}

Schema Registry & Avro

Khi nhiều producer/consumer chia sẻ cùng topic, schema drift là vấn đề thực: producer thêm field mới mà consumer cũ không biết xử lý thế nào. Schema Registry giải quyết bằng cách lưu trữ và validate schema tập trung.

  • Confluent Schema Registry — phổ biến nhất, open source
  • Avro — format binary compact, hỗ trợ schema evolution tốt nhất
  • Producer đăng ký schema → nhận schema ID → gửi (schema ID + binary payload)
  • Consumer nhận → lookup schema theo ID → deserialize

Managed Kafka — khi nào nên dùng?

Confluent Cloud
Fully managed, Schema Registry included, Kafka Connect hosted. Đắt nhất nhưng feature đầy đủ nhất.
Managed
AWS MSK
Managed Kafka trên AWS. Integrate tốt với IAM, S3, Lambda. Không có Confluent ecosystem.
Managed
Aiven Kafka
Multi-cloud (AWS/GCP/Azure). Giá cạnh tranh, hỗ trợ tốt, có Kafka Connect managed.
Managed
Redpanda
Kafka-compatible, viết bằng C++. Nhanh hơn Kafka, không cần JVM, tiêu thụ ít resource hơn.
Self-hosted
Apache Kafka (self-hosted)
Full control, open source, không phụ thuộc vendor. Cần team có expertise để operate.
Self-hosted
Quyết định
Nếu team < 10 người, không có Kafka expert, hoặc không muốn lo infrastructure — dùng managed service. Chi phí thường rẻ hơn khi tính cả nhân lực vận hành. Self-host khi cần data sovereignty, compliance, hoặc đã có infra team mạnh.

Production Checklist

  • Cluster 3+ broker, replication.factor=3, min.insync.replicas=2
  • KRaft mode (không dùng ZooKeeper cho cluster mới)
  • Naming convention thống nhất cho tất cả topic
  • Consumer lag monitoring + alert trong Grafana
  • UnderReplicatedPartitions alert khi > 0
  • OfflinePartitionsCount alert khi > 0
  • Retention policy phù hợp với từng topic (không để default mãi)
  • Producer idempotent=true cho critical data
  • Manual commit cho consumer xử lý critical message
  • Dead Letter Queue cho mọi consumer
  • Schema Registry nếu nhiều team chia sẻ cùng topic
  • Kafka Connect (không viết custom integration code nếu có sẵn connector)
  • Backup/restore plan — test restore ít nhất hàng quý
  • Security: SASL/SSL cho cluster production, ACL cho từng service