# 面向 SaaS 和 AI 产品的实时流式用量计量

> 构建支持实时仪表盘、硬性上限和即时超额处理的实时流式用量计量管道。了解其架构和常见问题。
- **Author**: Ayush Agarwal
- **Published**: 2026-05-19
- **Category**: Architecture, Usage-based Billing, Streaming
- **URL**: https://dodopayments.com/blogs/zh/real-time-streaming-usage-metering

---

实时流式用量计量意味着三件事会在几秒内完成，而不是等到隔夜批处理：用量汇总会更新，硬性上限会生效，阈值通知会触发。如果其中任何一项仍通过夜间批处理运行，你就没有真正的流式管道，而客户会感受到其中最慢的那条路径。

大多数基于用量的计费管道都是为批处理设计的。事件在白天收集，夜间汇总，第二天早上显示在仪表盘和发票中。对于许多 SaaS 产品来说，这种方式完全够用。但对于那些希望即时查看消耗、需要在几秒内启用硬性上限，或需要实时触发超额通知而不是等到当天结束的产品来说，这种方式并不适用。

实时流式用量计量正是用于处理这些场景的架构。事件会持续流经管道，而不是按夜间批次处理。汇总会在几秒内更新。当客户跨过阈值时，上限和通知会立即生效。代价是基础设施更加复杂。收益则是用量体验更像实时状态，而不是事后对账。

本文将介绍实时流式计量实际需要什么、它在哪些场景中值得投入，以及如何构建它而不把自己困在错误的架构中。本文假设你的产品是 SaaS 或 AI 产品，而不是电商产品。

## 实时计量到底意味着什么

在计费领域，"实时"这个词经常被宽泛地使用。要给出一个有用的定义，以下三点必须同时成立。

汇总延迟以秒计算，而不是以小时计算。从事件生成到显示在面向客户的用量总额中，间隔必须足够短，让客户感觉系统正在跟上他们的使用活动。五秒是实时，五小时就不是。

上限和配额执行也发生在同一个时间窗口内。如果客户即将达到硬性上限，管道必须知道最新用量，并能在几秒内拒绝后续请求。第二天早上才触发的上限不是实时上限，而是隔夜执行。

通知路径同样必须是实时的。当客户跨过配额阈值或超出预算时，邮件或 webhook 应立即触发，而不是等到下一次批处理运行。

如果这三项中有任何一项采用批处理，系统就不能算是真正的流式系统。你可以有流式汇总和批量执行，也可以反过来，但客户最终会感受到较慢的那条路径。

## 实时计量在哪些场景中值得投入

大多数产品并不需要实时计量。对于开票和大多数用量仪表盘来说，每日汇总已经足够。当以下任一情况适用时，实时计量才值得额外的基础设施投入。

### 硬性上限可以防止成本失控

按调用计费的 API 即服务产品、按 token 计费的 AI 产品，以及按资源计费的基础设施产品，都面临成本失控问题。我们的 [API 变现指南](https://dodopayments.com/blogs/api-monetization)介绍了这类按调用计费模式通常如何设计。行为异常的客户端或代码中的 bug，可能在几分钟内累积数千美元的用量。如果没有实时执行上限，客户就要承担整个用量峰值。有了实时执行，上限会在峰值造成严重损害之前生效。

### 实时用量仪表盘本身就是产品功能

有些产品的差异化优势就在于可见性。客户使用产品时，可以看到自己的用量持续更新。仪表盘展示的是实时视图，而不是延迟报告。对于开发者工具、基础设施和 AI 产品来说，这正越来越成为基本要求。

### 基于配额的访问控制

如果功能访问由用量配额控制，那么控制逻辑必须是实时的，否则客户会遇到错误拒绝和错误放行。配额可能生效太晚，放行本应被拦截的用量；也可能因为缓存数据过期而生效太早。

### 按事件执行业务逻辑

有些产品会在每个事件到达时执行相应的业务逻辑，例如反滥用检查、异常检测、自动升级套餐和实时风控信号。这些逻辑都无法通过批处理正常运行。

### 多区域产品

对于服务跨区域客户的产品，批量对账可能导致不同区域之间出现长达一天的不一致。带有区域扇出的流式管道，可以让所有区域在很小的时间窗口内保持一致。

如果你的产品符合上述任一模式，实时处理就值得投入。如果不符合，批处理完全够用，额外的复杂性也无法带来相应回报。

## 逐层拆解架构

流式计量管道与批处理管道拥有相同的概念层次，但每一层的形态都不同。

### 发出结构化事件的埋点

埋点位置与批处理相同。应用或基础设施层捕获用量事件，并携带相关字段发出。区别在于，事件会发送到流式传输系统，而不是先缓存在批处理中。每个事件生成后都会立即离开应用。

### 具备可靠交付语义的流式传输系统

流式传输所使用的是为低延迟而设计的队列或日志系统。Cloudflare Queues、AWS Kinesis、Google Pub Sub、Kafka、NATS 都可以使用。具体选择取决于运维偏好和现有基础设施。关键要求包括端到端低延迟、分区内有序交付，以及持久性。

顺序很重要，因为依赖事件顺序的汇总如果收到乱序事件就会出现错误。大多数管道会按客户标识符进行分区，使单个客户的事件彼此有序，同时允许不同客户并行进行流式处理。

持久性很重要，因为事件丢失就意味着收入和可信度的丢失。传输系统应在确认事件之前提交事件，并在节点或可用区之间进行复制。

### 维护汇总数据的流处理器

流处理器从传输系统读取事件，并按客户、按计量项维护持续更新的汇总。它负责将事件流转化为当前用量值。

实现方式各不相同，例如进程内运行的有状态工作器、Apache Flink 作业、Dataflow 管道，或由 Durable Objects 支持的自定义 Cloudflare Workers。模式是一致的：每个事件到达后，处理器更新相关汇总，持久化新的汇总值，下游消费者会在几秒内看到新值。

处理器还需要处理延迟事件和乱序到达的事件。对于在逻辑时间窗口结束后才到达的事件，系统仍会应用它们，并回溯更新汇总。上限和通知逻辑也要考虑这一点，避免延迟到达的用量峰值绕过执行控制。

### 暴露当前状态的实时存储

应用和执行逻辑需要在热路径上读取汇总数据。因此，需要使用由 Redis、DynamoDB 或 Cloudflare Durable Objects 等技术支持的实时键值存储，保存每个客户、每个计量项的当前状态。

当应用需要判断请求是否应被允许时，会读取该存储。上限执行逻辑读取存储，将当前值与配置的上限进行比较，然后允许或拒绝请求。执行决策会在几毫秒内完成。

客户仪表盘也会读取该存储。当客户打开用量页面时，页面中的数字来自这个存储，而不是批处理汇总，因此能够反映最新活动。关于仪表盘应展示哪些内容，请参阅我们关于 [用量上限和提醒 UX](https://dodopayments.com/blogs/billing-ux-usage-caps-alerts) 的文章。

### 让流式视图与事实来源保持一致的对账层

即使使用流式处理，计费仍然有一个事实来源，也就是开具发票的平台。流式汇总是应用用于执行控制和仪表盘展示的快速缓存。对账层会让流式视图与平台总额保持一致，避免两者产生偏差。

对于基于 Dodo Payments 的产品，对账过程会读取平台计量总额和流式汇总，比较两者，并在必要时修正偏差。在稳定状态下，两者应当一致。偏差说明流式管道中的某个环节需要调查。

## 有效的实现模式

以下几种模式可以让流式计量在实践中更加可靠。

为上限配置使用单一事实来源。上限值、客户订阅状态和权益规则应存放在同一个位置，由流式层读取。将这些信息分散在多个系统中会造成偏差。

使用显式失效来缓存汇总，而不是基于时间过期。如果汇总缓存六十秒，客户可能会暂时看到过期数字，上限也可能被暂时绕过。不要让缓存自然过期，而应永久缓存并在写入时主动使其失效。

让上限执行决策可逆。如果上限生效后客户立即提高上限，那么下一次请求就应该成功。写入长时间运行的 token 中的上限决策，比在请求时做出的决策更难撤销。

将热路径与慢路径解耦。响应客户请求的应用路径从实时存储中读取数据并快速做出决策。将事件持久化到平台和分析层的慢路径则异步运行。客户体验受热路径延迟限制，而不是慢路径延迟限制。

让仪表盘直接读取实时存储。客户点击用量页面后即可看到最新数字。慢路径最终也会反映相同的数字，但客户不需要等待它完成。

为部分故障做好准备。即使流式层暂时无法连接平台，也不应丢失事件，因为事件已经持久化在传输系统中。连接恢复后，对账层会追上进度。

## Dodo Payments 如何融入其中

Dodo Payments 提供事件接入 API 和计量汇总，它们在此架构中充当事实来源。你的应用中的流式层位于平台之前，为客户和执行逻辑提供低延迟视图。

具体模式是：将事件发送到你的流式传输系统，让流处理器更新实时存储，同时将事件转发到 Dodo Payments 事件接入 API。平台负责汇总事件，用于开票和慢路径分析。你的实时存储则为仪表盘和上限提供热路径服务。

对账通过定期任务运行，将平台计量总额与实时存储进行比较。在稳定状态下，两者应在很小的时间窗口内保持一致。偏差说明管道中存在值得调查的问题。

事件接入 API 和计量配置的完整参考位于 [基于用量的计费指南](https://docs.dodopayments.com/developer-resources/usage-based-billing-guide) 中。本文介绍的是流式架构，而平台负责处理计费基础能力。

## 流式计量中的常见问题

实时管道中经常会反复出现以下几类错误。

将流式汇总当作开票的事实来源。流式层本来就是为了速度而设计的近似视图。开具发票的平台才是事实来源。混淆两者会导致发票与平台记录不一致。

低估事件量。如果分区方式不正确，一个每秒处理一千个事件的流式系统，在每秒一万个事件时就可能崩溃。规划传输系统容量时，应按当前峰值的十倍进行设计。

跳过对账层。在网络分区、部署失败和代码变更的情况下，流式层会逐渐偏离平台。对账是发现这些问题的唯一方式。没有对账，偏差会在不知不觉中不断累积。

将流式逻辑硬编码到应用代码中。上限和配额逻辑应位于可以独立于应用更新的层中。硬编码会让上限策略变更与应用发布绑定在一起。

让流式管道成为应用瓶颈。如果实时存储暂时不可用，热路径应能够平稳降级。你可以在记录异常后默认放行，也可以在返回明确错误的情况下拒绝请求，但不要让流式层拖垮整个应用。

忘记时区。流式汇总通常以计费周期为范围。周期之间的边界是真正的切换点。必须正确设置边界时区，否则客户会在错误的时刻看到用量切换。

## 总结

实时流式用量计量并不适合每一种产品。批处理更简单、更便宜，而且对大多数产品来说已经足够。当产品确实需要实时能力时，无论是因为硬性上限可以保护成本、实时仪表盘本身就是功能，还是因为它依赖按事件执行业务逻辑，本文介绍的架构都能扩展到大型产品，同时保持可管理性。

关键在于让流式层待在自己的职责范围内。它服务于热路径，但不拥有计费的事实来源。它将事件发送给真正拥有事实来源的平台，并通过对账保持一致。按照这种方式构建，流式层就是一个干净的补充，而不是一个与平台竞争的平行计费系统。

## 常见问题

### 汇总实际需要多快？

对于硬性上限和实时仪表盘，端到端延迟低于五秒通常就足够了。对于与请求同步运行的按事件业务逻辑，亚秒级延迟很重要。大多数应用会通过衡量用户感知来找到合适的平衡点，而不是一味追求可能的最低数值。

### 我应该自己构建流式计量，还是使用托管服务？

两种方式都可行。流处理和实时存储的托管服务可以减少大量运维工作。自行管理则能提供更多控制权。最终的决定通常取决于现有基础设施和团队经验。对于大多数团队来说，托管服务是风险更低的路径；而我们关于 [最适合基于用量定价的计费平台](https://dodopayments.com/blogs/best-billing-platform-usage-based-pricing) 的对比文章，也可以作为这套技术栈计费部分的合理起点。

### 流式处理和批处理可以使用同一批事件吗？

可以。最简洁的模式是将事件发送到流式传输系统，然后让一个消费者为实时存储提供数据，另一个消费者为批处理平台提供数据。两个消费者读取同一批事件。它们使用不同的方式计算汇总，但数据源相同。

### 如何处理延迟事件？

流处理器会将它们应用到相关的历史汇总中。如果事件在所属的同一计费周期内到达，就只需更新该周期的总额。如果事件在周期结束后才到达，则需要修正已关闭周期的汇总。大多数平台都能平稳处理这种情况。

### 上限执行需要做到完全精确吗？

实际应用中的上限通常会允许一个小的宽限窗口。如果上限是 100 万次调用，那么实际在 100 万零一次或 101 万次时生效都可以，具体取决于你希望执行得多严格。更严格的执行意味着更多同步协调和更高延迟。大多数产品会选择几个百分点的容差，并接受这种权衡。
---
- [More Architecture articles](https://dodopayments.com/blogs/category/architecture)
- [All articles](https://dodopayments.com/blogs)