1. 课程导入与场景锚定

在开始写任何一行代码之前,我们需要先把这门课要解决的问题“钉”在一个真实的位置上。所谓实时逐笔数据,指的是以单条记录为单位、持续不断到达、且每条记录都带有明确时间属性的数据流。它有三个典型来源:

  • 交易类数据:委托下单、成交回报、撤单、账户资金变动。特点是单条价值高、顺序敏感、不允许丢失或乱序,往往还要求可追溯。
  • 行情类数据:逐笔委托、逐笔成交、快照、盘口变化。特点是吞吐量极大、峰值突发明显,例如开盘集合竞价结束瞬间或极端行情下,单秒可达数万到数十万条。
  • 日志类数据:网关访问日志、风控命中日志、系统运行指标。特点是写入持续、单条较小、允许极短的延迟,但长期累积体量惊人。

这三类数据有一个共同点:到达是“逐笔”的,而落盘是“昂贵”的。如果每来一条记录就立刻写一次磁盘或发一次数据库请求,系统会被 I/O 次数拖垮;如果为了省事把数据全部攒在内存里,一旦进程崩溃或机器宕机,未落盘的数据就全部丢失。这就是本课程要处理的核心矛盾——吞吐、延迟与可靠性之间的三角权衡。

缓冲与批量落盘的本质,是用“可控的延迟”和“可控的内存占用”,换取“更少的 I/O 次数”和“更高的写入吞吐”,同时通过持久化策略把“丢失窗口”压缩到业务可接受的范围。

为了把这个矛盾讲清楚,我们先看一条数据从产生到安全落盘的完整链路。下图展示了本节要建立的整体心智模型:数据源逐笔进入缓冲区,缓冲区按策略触发批量落盘,落盘结果再进入可校验的存储层。

逐笔数据 → 缓冲 → 批量落盘 → 可校验存储 数据源(逐笔到达) 交易回报 委托 / 成交 / 撤单 行情逐笔 高吞吐 / 突发峰值 运行日志 持续 / 体量大 共同特征:单条到达、顺序敏感 逐笔写入 内存缓冲区 环形队列 / 队列容器 容量上限 + 水位线 触发条件 条数 / 字节 / 时间 背压与丢弃策略 阻塞 / 降级 / 告警 未落盘窗口 崩溃即丢失的风险区 批量提交 批量落盘 批量写文件 追加 + 刷盘 批量入库 事务 / 批次提交 失败重试 幂等 / 去重 落盘确认 位点 / 偏移量 可校验 存储与校验 核心权衡:批量越大 → I/O 次数越少、吞吐越高,但未落盘窗口越长、崩溃丢失风险越大; 批量越小 → 丢失窗口越短,但 I/O 放大、吞吐下降。缓冲策略就是在这条曲线上找业务可接受的工作点。

从图中可以看到,整条链路的关键不在“写”,而在“什么时候写、写多少、写失败怎么办”。这三个问题分别对应缓冲触发策略、批量大小设计和可靠性保障。我们用一个具体的示例参数来感受一下量级差异(以下为教学假设,非实测):假设行情逐笔峰值 5 万条/秒,单条记录约 200 字节,即约 10 MB/s。若每条记录单独写一次文件,每秒 5 万次系统调用,开销几乎全部耗在 I/O 上;若改为每 500 条或每 200 毫秒批量写一次,写入次数降到每秒约 100 次,单次写入约 100 KB,吞吐和 CPU 占用都会显著改善,代价是最坏情况下约 200 毫秒的数据停留在内存中。

因此,本课程的整体任务链可以概括为四步递进:先建模——明确数据来源、字段结构、顺序与时间语义;再缓冲——设计队列结构、容量上限、触发条件与背压策略;然后落盘——实现批量写文件或批量入库,处理刷盘、重试与幂等;最后验证——通过位点、条数对账、回放校验确认“不丢、不重、不乱序”。

本课程的最终交付物是一个可运行的“逐笔数据缓冲与批量落盘”最小系统:包含数据模拟器(模拟交易/行情/日志三类来源)、可配置的缓冲区、批量落盘器、以及一套对账校验脚本。每一章都会为这个系统增加一个可验证的能力,而不是停留在概念讲解。

需要特别提醒的是,缓冲不是“把数据堆在内存里等一等”这么简单。缓冲区一旦引入,就同时引入了三个必须回答的问题:内存上限是多少(防止 OOM)、满了之后怎么办(阻塞上游、丢弃低优先级数据还是告警降级)、进程崩溃时未落盘的数据如何界定损失范围(这决定了批量大小和刷盘频率的下限)。这三个问题会在后续章节逐一展开,而本节只需要建立一个判断标准:任何缓冲方案,都必须能清楚说出它的“最大丢失窗口”和“最大内存占用”。

最后,我们用一句话锚定本课程的立场:逐笔数据的第一价值是“完整与有序”,第二价值才是“快”。批量落盘是为了让系统扛得住吞吐,但绝不能以悄悄丢数据为代价。后续所有设计,都会围绕“在可接受的延迟与内存成本下,保证数据完整、有序、可校验地落盘”这一目标展开。