Kafka 7 — Vận hành Kafka ở Production

13 thg 7, 2026 3 lượt xem
#security
#monitoring
#kafka
#sre
#van-hanh

Đưa Kafka lên production không phải là chuyện cài cluster rồi tạo topic. Sự khác biệt giữa một cluster chạy êm nhiều năm và một cluster "cháy" mỗi tuần nằm ở cách bạn sizing, giám sát, bảo mật và xử lý sự cố. Bài này là góc nhìn của một SRE/kỹ sư nền tảng: những con số, metric, câu lệnh và checklist thực chiến. Xuyên suốt bài, chúng ta lấy ví dụ cụm Kafka phục vụ luồng giao dịch của một ngân hàng — nơi mất dữ liệu hoặc trễ vài giây là chuyện lớn.

Sizing & topology cluster

Số broker và replication factor

Nguyên tắc mở đầu: replication factor (RF) = 3 cho dữ liệu quan trọng. RF=3 cho phép mất 1 broker vẫn còn 2 bản sao và producer với acks=all vẫn ghi được (nếu min.insync.replicas=2). RF=2 chỉ chịu được mất 1 broker nhưng khi đó min.insync.replicas buộc phải là 1 hoặc 2 — cả hai đều có nhược điểm (mất bền vững hoặc mất khả năng ghi). Với ngân hàng, RF=3 là mức tối thiểu cho topic giao dịch.

Số broker tối thiểu để RF=3 có ý nghĩa là 4 broker (không phải 3): với 3 broker, khi mất 1 broker bạn không thể tái tạo bản sao thứ 3 ở đâu cả, cluster chạy ở trạng thái under-replicated cho tới khi broker trở lại. 4-5 broker cho phép rebalance khi bảo trì.

Ước lượng số broker theo tải:

  • Throughput ghi: tổng_MB_giây_ghi × RF là lưu lượng thực broker phải xử lý. Một broker trên đĩa NVMe/SSD tốt xử lý được hàng trăm MB/s, nhưng nên để headroom, chạy ở ~50-60% công suất.
  • Dung lượng: throughput_ghi × retention_giây × RF. Ví dụ 50 MB/s × 7 ngày × 3 = ~90 TB thô, chia cho số broker và trừ headroom (giữ đĩa dưới 70%).
  • Kết nối và partition: mỗi broker nên gánh dưới ~4.000 partition (bao gồm replica). Con số này quan trọng khi tính tổng partition toàn cluster.

Số partition mỗi topic

Partition là đơn vị song song. Số partition quyết định:

  • Độ song song tối đa của consumer group: không thể có nhiều consumer active hơn số partition.
  • Throughput: mỗi partition có giới hạn ghi/đọc.

Công thức khởi điểm: partitions = max(throughput_mong_muốn / throughput_mỗi_partition, số_consumer_muốn_chạy_song_song). Ví dụ topic giao dịch cần 60 MB/s, mỗi partition đạt ~10 MB/s → tối thiểu 6 partition; nếu muốn 12 consumer song song → chọn 12.

Cảnh báo: đừng đặt quá nhiều partition. Mỗi partition tốn file handle, bộ nhớ, và tăng thời gian recovery/leader election khi broker restart. Tổng partition toàn cluster hàng chục nghìn khiến controller chậm và rebalance lâu. Với KRaft (bỏ ZooKeeper), giới hạn được nới nhưng nguyên tắc "đủ dùng, đừng thừa" vẫn đúng.

Phân bổ và rack awareness

Bật broker.rack để Kafka phân bổ replica sang các rack/AZ khác nhau. Nhờ đó mất cả một rack (hoặc một Availability Zone trên cloud) vẫn còn bản sao. Cấu hình trên mỗi broker:

broker.rack=az-1a
# replica.selector.class cho phép consumer đọc từ replica gần nhất (fetch from follower)
replica.selector.class=org.apache.kafka.common.replica.RackAwareReplicaSelector

Ngân hàng thường triển khai broker trải trên 3 AZ; RF=3 + rack awareness cho phép chịu được mất 1 AZ mà vẫn min.insync.replicas=2.

Giám sát (monitoring)

Không giám sát thì bạn chỉ biết cluster hỏng khi khách hàng phàn nàn. Kafka phơi bày metric qua JMX; pattern chuẩn là dùng Prometheus JMX Exporter (agent Java gắn vào broker) đẩy metric vào Prometheus, rồi vẽ Grafana.

Kiến trúc cluster + monitoring + security

Metrics quan trọng cần theo dõi

MetricNguồn (MBean / công cụ)Ngưỡng cảnh báoÝ nghĩa
Under-replicated partitionskafka.server:type=ReplicaManager,name=UnderReplicatedPartitions> 0 kéo dàiCó replica không theo kịp leader; nguy cơ mất dữ liệu
Offline partitionskafka.controller:type=KafkaController,name=OfflinePartitionsCount> 0Partition không có leader → không đọc/ghi được
ISR shrink/expand ratekafka.server:...IsrShrinksPerSecTăng đột biếnISR co lại liên tục = broker/network chập chờn
Consumer lagkafka-consumer-groups --describe / BurrowVượt SLA nghiệp vụConsumer xử lý không kịp tốc độ ghi
Request latency (p99)kafka.network:type=RequestMetrics,name=TotalTimeMs,request=Produce/FetchConsumerp99 tăng bất thườngProducer/consumer chậm
Active controller countkafka.controller:...ActiveControllerCount≠ 1 toàn clusterPhải đúng 1 controller active
Log flush latencykafka.log:type=LogFlushStats,name=LogFlushRateAndTimeMsp99 caoĐĩa chậm/quá tải I/O
Disk usagenode_exporter> 70-80%Đĩa đầy = broker dừng, nguy cơ mất cluster
Network/CPU brokernode_exporter> 70% kéo dàiCần thêm broker hoặc rebalance
Request handler idle %kafka.server:...RequestHandlerAvgIdlePercent< 20%Thread pool xử lý bão hòa

Ba metric "vàng" luôn phải có alert: UnderReplicatedPartitions > 0, OfflinePartitionsCount > 0, và consumer lag vượt SLA. Chúng phản ánh trực tiếp sức khỏe bền vững và độ trễ end-to-end.

Đo consumer lag

# Xem lag chi tiết của một consumer group
kafka-consumer-groups.sh --bootstrap-server broker1:9093 \
  --command-config client-ssl.properties \
  --describe --group fraud-detection

# Cột LAG = LOG-END-OFFSET - CURRENT-OFFSET cho mỗi partition
# Liệt kê toàn bộ group để tìm group "chết"
kafka-consumer-groups.sh --bootstrap-server broker1:9093 \
  --command-config client-ssl.properties --list

Với hệ thống lớn nên dùng exporter chuyên biệt (kafka-lag-exporter, Burrow) để đẩy lag vào Prometheus liên tục thay vì chạy tay.

Công cụ vận hành

  • AKHQ / Kafka UI / Redpanda Console: giao diện web xem topic, message, consumer group, ACL — cực tiện cho hỗ trợ vận hành.
  • Cruise Control: tự động cân bằng tải giữa broker, sinh và thực thi kế hoạch reassign, phát hiện broker lệch tải. Rất đáng dùng cho cluster lớn.
  • Grafana + Alertmanager: dashboard và cảnh báo.

Bảo mật

Với ngân hàng, bảo mật không phải tùy chọn. Ba lớp cần cấu hình: mã hóa đường truyền, xác thực, phân quyền.

Mã hóa TLS in-transit

Bật TLS trên listener để mã hóa dữ liệu giữa client–broker và giữa broker–broker:

listeners=SSL://:9093
security.inter.broker.protocol=SSL
ssl.keystore.location=/etc/kafka/ssl/broker.keystore.jks
ssl.keystore.password=<pw>
ssl.truststore.location=/etc/kafka/ssl/broker.truststore.jks
ssl.truststore.password=<pw>
ssl.client.auth=required   # bắt buộc mTLS nếu dùng xác thực bằng chứng chỉ

Xác thực SASL

Kafka hỗ trợ nhiều cơ chế SASL, thường kết hợp với TLS (SASL_SSL):

  • PLAIN: user/password gửi qua kết nối đã mã hóa TLS. Đơn giản nhưng credential thường tĩnh, khó xoay vòng.
  • SCRAM (SCRAM-SHA-256/512): credential lưu băm trong Kafka (KRaft/ZK), an toàn hơn PLAIN, hỗ trợ tạo/xóa user động. Lựa chọn mặc định tốt cho phần lớn cluster on-prem.
  • Kerberos (GSSAPI): tích hợp Active Directory/Kerberos của doanh nghiệp — phổ biến ở ngân hàng đã có hạ tầng AD.
  • OAuth (OAUTHBEARER): dùng token từ Identity Provider (Keycloak, Okta), phù hợp kiến trúc microservice/cloud hiện đại.

Cấu hình listener SASL_SSL với SCRAM:

listeners=SASL_SSL://:9093
security.inter.broker.protocol=SASL_SSL
sasl.enabled.mechanisms=SCRAM-SHA-512
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-512
listener.name.sasl_ssl.scram-sha-512.sasl.jaas.config=\
  org.apache.kafka.common.security.scram.ScramLoginModule required;

Client:

security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="ledger-service" password="<secret>";
ssl.truststore.location=/etc/kafka/ssl/client.truststore.jks

Phân quyền ACL

Sau khi biết "ai" (authentication), ACL quyết định "được làm gì" (authorization). Bật authorizer và mặc định từ chối:

authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
allow.everyone.if.no.acl.found=false
super.users=User:admin

Cấp quyền theo nguyên tắc tối thiểu:

# Cho producer core-banking chỉ được WRITE topic txn.events
kafka-acls.sh --bootstrap-server broker1:9093 --command-config admin.properties \
  --add --allow-principal User:core-banking \
  --operation Write --operation Describe --topic txn.events

# Cho consumer fraud chỉ được READ topic đó với group cố định
kafka-acls.sh --bootstrap-server broker1:9093 --command-config admin.properties \
  --add --allow-principal User:fraud-detection \
  --operation Read --operation Describe --topic txn.events \
  --group fraud-detection

Encryption at rest

Kafka không có mã hóa dữ liệu-tại-chỗ tích hợp ở tầng ứng dụng. Cách chuẩn là mã hóa ở tầng đĩa/hệ điều hành: LUKS/dm-crypt trên on-prem, hoặc volume mã hóa (EBS encryption, KMS) trên cloud. Với dữ liệu cực nhạy cảm (số thẻ, PII), một số ngân hàng còn mã hóa payload ở tầng ứng dụng trước khi đưa vào Kafka (field-level encryption / tokenization).

Tối ưu hiệu năng

Throughput vs latency

Đây là đánh đổi trung tâm. Muốn throughput cao: gom message thành batch lớn. Muốn latency thấp: gửi ngay, batch nhỏ. Producer:

# Nghiêng về throughput
batch.size=131072          # 128KB, gom nhiều message/batch
linger.ms=20               # chờ tới 20ms để batch đầy
compression.type=lz4       # nén giảm băng thông & I/O đĩa
acks=all                   # bền vững (bắt buộc cho giao dịch ngân hàng)
  • linger.ms: chờ thêm chút để gom batch → tăng throughput, tăng latency. Với giao dịch nhạy độ trễ, giữ nhỏ (0-5ms); với pipeline phân tích, có thể để 20-100ms.
  • compression.type: lz4/zstd giảm dung lượng lưu và băng thông mạng đáng kể; zstd nén tốt hơn nhưng tốn CPU hơn. Nén một lần ở producer và giữ nguyên qua broker (broker không giải nén nếu format tương thích).

Cấu hình broker

num.network.threads=8      # nhận/gửi request mạng
num.io.threads=16          # đọc/ghi đĩa; ~ số core hoặc gấp đôi
num.replica.fetchers=4     # tăng tốc replica đuổi kịp leader
socket.send.buffer.bytes=1048576
socket.receive.buffer.bytes=1048576

Page cache là bạn thân

Kafka dựa vào OS page cache để đọc nhanh: consumer đọc dữ liệu mới thường lấy từ RAM, không chạm đĩa. Vì vậy:

  • Đừng cấp heap JVM quá lớn (thường 6-8GB là đủ), để RAM còn lại cho page cache.
  • Dữ liệu ghi sạch sẽ theo tuần tự (sequential I/O) rất hợp với đĩa quay lẫn SSD.
  • Cẩn thận với consumer đọc dữ liệu cũ (backfill) — nó "quét" đĩa và đẩy dữ liệu nóng ra khỏi cache, làm chậm consumer khác.

Số partition hợp lý

Như đã nói: partition nhiều = song song cao nhưng chi phí quản lý và recovery tăng. Quy tắc thực chiến: chọn theo throughput/consumer cần thiết, để dư một chút cho tăng trưởng, và giữ tổng partition/broker dưới ~4.000. Tránh thói quen tạo 100 partition "cho chắc" khi chỉ cần 6.

Quản trị cluster

Thêm broker & reassign partitions

Thêm broker mới không tự động kéo dữ liệu về. Phải chạy reassignment để phân bổ lại partition:

# 1. Sinh kế hoạch: liệt kê topic cần cân bằng vào topics.json
kafka-reassign-partitions.sh --bootstrap-server broker1:9093 \
  --command-config admin.properties \
  --topics-to-move-json-file topics.json \
  --broker-list "1,2,3,4" --generate > plan.json

# 2. Thực thi kế hoạch (giới hạn băng thông để không nghẽn cluster)
kafka-reassign-partitions.sh --bootstrap-server broker1:9093 \
  --command-config admin.properties \
  --reassignment-json-file plan.json --execute \
  --throttle 50000000        # 50 MB/s

# 3. Kiểm tra tiến độ, và gỡ throttle khi xong
kafka-reassign-partitions.sh --bootstrap-server broker1:9093 \
  --command-config admin.properties \
  --reassignment-json-file plan.json --verify

Luôn đặt --throttle khi reassign trên cluster đang chạy để tránh replica fetch ngốn hết băng thông và đẩy các partition khác vào under-replicated. Cruise Control tự động hóa toàn bộ quy trình này.

Tăng số partition & hệ quả thứ tự

Có thể tăng partition (kafka-topics.sh --alter --partitions) nhưng không giảm được. Quan trọng: Kafka đảm bảo thứ tự trong một partition, và message được phân vào partition theo hash(key) % số_partition. Khi tăng số partition, cùng một key có thể rơi vào partition khác trước và sau khi đổi → thứ tự theo key bị phá vỡ với dữ liệu cũ/mới. Với luồng giao dịch phân theo account_id, đây là rủi ro nghiêm trọng. Cách an toàn: sizing đủ partition từ đầu, hoặc dùng topic mới và migrate có kiểm soát.

Nâng cấp rolling

Nâng cấp không downtime bằng cách restart từng broker một:

  1. Đặt inter.broker.protocol.version (và log.message.format.version với bản cũ) khớp phiên bản hiện tại trước khi nâng.
  2. Nâng binary và restart từng broker một, chờ nó trở lại ISR đầy đủ (UnderReplicated về 0) rồi mới làm broker tiếp theo.
  3. Khi tất cả broker đã lên bản mới, nâng inter.broker.protocol.version và rolling restart lần nữa.

Với KRaft, nâng cấp có thêm bước về metadata.version (feature flag) — kiểm tra release notes phiên bản đích.

Thay đổi cấu hình động

Nhiều cấu hình đổi được nóng, không cần restart:

kafka-configs.sh --bootstrap-server broker1:9093 --command-config admin.properties \
  --alter --entity-type topics --entity-name txn.events \
  --add-config retention.ms=1209600000    # đổi retention topic sang 14 ngày

Sự cố thường gặp & cách xử lý

Sự cốNguyên nhân thường gặpCách xử lý
Under-replicated partitions kéo dàiBroker chậm/quá tải I/O, network chập chờn, replica fetcher không kịpKiểm tra broker chậm; tăng num.replica.fetchers; giảm tải/reassign; thay đĩa nếu I/O bão hòa
Offline partitionsMất quá số broker cho phép; không đủ replica còn sốngKhôi phục broker; nếu chấp nhận rủi ro, unclean.leader.election (có thể mất dữ liệu — cân nhắc kỹ)
Consumer lag tăng liên tụcConsumer chậm, đối tác downstream nghẽn, ít consumer hơn partition, rebalance liên tụcTăng số consumer (≤ số partition); tối ưu xử lý; kiểm tra max.poll.interval.ms để tránh bị đá khỏi group
Disk đầyRetention quá dài, throughput vượt dự tính, log dồnGiảm retention.ms/retention.bytes; thêm broker & reassign; không xóa file .log thủ công
Rebalance bão (rebalance storm)Consumer chết/timeout liên tục, session.timeout.ms quá thấp, deploy rollingDùng cooperative-sticky assignor; tăng session.timeout.ms; dùng static membership (group.instance.id)
Hot partitionKey phân bố lệch (nhiều giao dịch dồn 1 account/1 key)Xem lại chiến lược key/partitioner; tách key nóng; cân nhắc thêm salt vào key
ISR shrink liên tụcGC pause dài, đĩa/network nghẽn, replica.lag.time.max.ms quá thấpTinh chỉnh GC, giảm heap để dành page cache; kiểm tra hạ tầng mạng/đĩa

Nguyên tắc điều tra chung: bắt đầu từ dashboard (UnderReplicated, Offline, lag, disk), khoanh vùng broker bất thường qua per-broker metric, rồi mới xuống log của broker đó. Đừng "sửa mù" bằng cách restart cả cluster.

Backup/DR & multi-region

Kafka bản thân đã có replica trong cùng cluster, nhưng đó không phải backup cho thảm họa cấp DC/region. Cho DR và multi-region, công cụ chuẩn là MirrorMaker 2 (MM2) — chạy trên nền Kafka Connect, sao chép topic, offset và consumer group giữa các cluster.

  • Active-Passive: cluster chính ở DC1, MM2 sao chép sang DC2 dự phòng. Khi thảm họa, failover consumer sang DC2 (MM2 dịch offset qua RemoteClusterUtils).
  • Active-Active: hai region cùng nhận ghi, MM2 sao chép hai chiều. MM2 dùng tiền tố cluster (ví dụ dc1.txn.events) để tránh vòng lặp sao chép.

MM2 sao chép bất đồng bộ → luôn có độ trễ và có thể mất một ít dữ liệu chưa kịp nhân bản khi thảm họa (RPO > 0). Ngân hàng cần định rõ RPO/RTO và test failover định kỳ.

Checklist production

  • RF=3, min.insync.replicas=2, producer acks=all cho topic quan trọng.
  • Broker trải trên ≥3 rack/AZ, bật broker.rack.
  • unclean.leader.election.enable=false cho topic không được mất dữ liệu.
  • Giám sát: alert cho UnderReplicated, Offline, consumer lag, disk > 70%, active controller ≠ 1.
  • Bảo mật: TLS + SASL (SCRAM/Kerberos), ACL mặc định deny, encryption at rest ở tầng đĩa.
  • Heap JVM vừa phải (6-8GB), để RAM cho page cache; đĩa dành riêng cho log Kafka.
  • Quy trình reassign luôn kèm --throttle; có Cruise Control cho cluster lớn.
  • Sizing partition đủ từ đầu (tránh tăng partition phá thứ tự theo key).
  • Có kế hoạch nâng cấp rolling và đã test trên staging.
  • DR: MM2 sang region dự phòng, định nghĩa RPO/RTO, test failover định kỳ.
  • Runbook cho từng sự cố trong bảng trên; có on-call và escalation.

Tóm tắt

Vận hành Kafka production là bài toán bốn trụ: sizing đúng (RF=3, đủ broker và partition, rack awareness), giám sát đúng metric (under-replicated, offline, lag, latency, disk qua JMX → Prometheus → Grafana), bảo mật ba lớp (TLS + SASL + ACL + mã hóa đĩa), và tối ưu cân bằng throughput/latency dựa trên batching, nén và page cache. Quản trị đòi hỏi hiểu reassign có throttle, hệ quả thứ tự khi tăng partition, và quy trình rolling upgrade. Khi sự cố xảy ra, đi theo dữ liệu từ dashboard xuống log, và luôn có runbook. Cuối cùng, DR bằng MirrorMaker 2 và một checklist production kỷ luật là thứ phân biệt một cluster ngân hàng đáng tin với một cluster hay cháy.

Tự kiểm tra

  1. Tại sao cần tối thiểu 4 broker để RF=3 thực sự có ý nghĩa, thay vì đúng 3?
  2. Ba metric nào bạn bắt buộc phải đặt alert đầu tiên, và mỗi metric phản ánh điều gì?
  3. Khác biệt giữa SASL/PLAIN, SCRAM và Kerberos là gì, và vì sao ngân hàng thường ưu tiên SCRAM hoặc Kerberos?
  4. Vì sao không nên cấp heap JVM quá lớn cho broker Kafka?
  5. Tăng số partition của một topic gây hệ quả gì với thứ tự message theo key, và cách phòng tránh?
  6. Khi reassign partition trên cluster đang chạy, vì sao phải đặt --throttle, và điều gì xảy ra nếu quên?

Đọc tiếp

  • Quay lại nền tảng kiến trúc: Kafka 1 — Kiến trúc Kafka để ôn lại broker, partition, ISR và controller trước khi vận hành sâu.
  • Gợi ý series tiếp theo: Oracle CDC — đưa dữ liệu thay đổi từ Oracle vào Kafka (Debezium/GoldenGate), một mảnh ghép rất phổ biến của luồng dữ liệu ngân hàng.

Bài viết liên quan

CSV/JSON/Parquet/Avro, lưu trữ theo hàng vs cột, nén, và OLTP vs OLAP.

13 thg 7, 2026 8

Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.

13 thg 7, 2026 5

Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.

13 thg 7, 2026 5

Đảm bảo chất lượng & minh bạch dữ liệu bằng dbt: data tests dựng sẵn (unique, not_null, relationships, accepted_values), singular test, unit test, và tài liệu tự sinh kèm lineage graph.

13 thg 7, 2026 5