01学完你能做到
解释 Kafka 的 topic、partition、offset、key 和 consumer group;为行情消息选择分区键;区分分区内有序、消费组并行和不同投递语义;设计回放、去重和积压监控方案。
02这课解决什么问题
行情源不断推来 Tick 时,怎样让实时 K 线、风控、前端、归档和数据接口各自消费,互不拖累,还能在故障后从某个位置回放?消息队列提供了采集与加工之间的缓冲、分发和回放层。
03Kafka 的核心概念
- Topic:一类消息的逻辑名称,例如
ticks.sh。 - Partition:topic 的并行子日志,是扩展吞吐和消费组并行度的基本单位。
- Offset:消息在分区中的位置编号,消费者可从已提交位置继续读取。
- Key:消息分区键。按股票代码分区时,同一代码通常进入同一分区,从而保持该分区内的处理顺序。
- Consumer group:共同分担一个 topic 的消费者集合。同一消费组内,一个分区在同一时刻通常只分配给一个成员;不同消费组各自维护读取位置,互不抢数据。
- Retention:日志按时间或大小保留,保留多久由 broker、topic 和集群配置决定,不能把某个默认值当成所有部署的承诺。
- 投递语义:至多一次可能丢失,至少一次可能重复,精确一次需要生产端、处理端和下游共同配合。
Kafka 只保证分区内有序,不保证跨分区全局有序。分区数增加后,key 到分区的映射和扩展策略也要重新评估。热门股票可能形成热点分区,应监控每个分区的消费积压。
04行情链路中的位置
行情源 -> 生产者(解码、标准化) -> Kafka topic
-> K 线聚合消费组
-> 风控消费组
-> 落库与归档消费组Kafka 负责缓冲、分发和回放;长期存储与随机查询应交给数据湖、数据库或缓存。下游处理慢于生产速度时,consumer lag 会持续增加,实时接口返回的可能是旧行情。
05代码:模拟 topic、分区和回放
下面的代码只模拟核心语义,不是真实 Kafka 客户端;示例用 CRC32 代替默认分区器的具体哈希实现。
import zlib
from collections import defaultdict
class Topic:
def __init__(self, partitions):
self.logs = [[] for _ in range(partitions)]
def send(self, key, value):
partition = zlib.crc32(key.encode()) % len(self.logs)
self.logs[partition].append((key, value))
return partition, len(self.logs[partition]) - 1
class ConsumerGroup:
def __init__(self, topic, members):
self.topic = topic
self.committed = defaultdict(int)
self.assignment = defaultdict(list)
for p in range(len(topic.logs)):
self.assignment[members[p % len(members)]].append(p)
def poll(self, member):
out = []
for p in self.assignment[member]:
start = self.committed[p]
batch = self.topic.logs[p][start:]
out.extend((p, start + i, k, v) for i, (k, v) in enumerate(batch))
self.committed[p] = start + len(batch)
return out真实系统还要定义提交 offset 的时机、失败重试、幂等写入、消息版本、序列号和回放边界。单纯把 offset 重置到 0 不能自动保证外部数据库不重复。
06常见误区
- 认为 Kafka 全局有序;跨分区的消息没有全局顺序。
- 不设 key 或 key 选错,导致同一证券消息分散到多个分区。
- 分区数随意增加;并行度提高的同时,映射变化和热点问题也要评估。
- 认为精确一次可以覆盖所有外部系统;写入数据库或下游服务仍需事务或幂等策略。
- 把 Kafka 当数据库;它不适合按代码查询某时刻的最终状态。
- 忽视 consumer lag;积压意味着下游延迟,可能已经影响实时服务。
07延伸阅读
08一分钟讲给别人
试着用自己的话讲一遍Kafka 像一条可回放的公共传送带。行情源只管往上放,风控、K 线计算和落库各自组队来取;同一只股票用同一个 key,能在分区内保持顺序。出了问题可以按 offset 回放,但下游仍要做去重或幂等写入。
5 道自测
先在心里答一遍,再展开对照。能说清理由,比答对数字更重要。
01Kafka 保证什么范围内的消息顺序?
02为什么行情消息常用证券代码作为 key?
03两个不同消费组会互相抢同一 topic 的消息吗?
04消费组成员多于分区数时会发生什么?
05至少一次投递语义要求下游做什么?
已看 0/5 题
练动手练习
任务:把模拟消费组改成 4 个成员,但 topic 仍只有 3 个分区,观察是否有成员空闲;再写出一个按证券代码去重的消息主键,并说明它在重放时如何使用。
完成这一课
读完讲义、看完自测答案,这一课就算学完了。
- 读完讲义
- 看完全部自测
本课为投资者教育内容,案例数字均为示意,不构成任何投资建议,也不承诺收益。规则和费率会变,实际操作前请以交易所、监管机构和产品的最新公告为准。