跳到主要内容
版本:Nightly

写入限流

GreptimeDB 企业版支持按数据库限制每秒写入的行数。同一数据库中的所有表共享 限流额度,每个数据库可以独立配置。该功能适用于单机和分布式部署。

限流机制​

限流分为两部分:在本地决定是否接受一个写入批次,以及在分布式模式下将 数据库的行数额度分配给各个 Frontend。本地令牌桶负责写入准入,Metasrv 根据心跳反馈重新分配额度。

客户端写入在准入检查时消耗行数额度,此时尚未向存储节点分发写入请求。 写入协议转换后生成的行也计入目标数据库的额度。Flow 生成的内部写入不消耗 限流额度。

下图展示了分布式部署中的处理流程。每个 Frontend 上的每个数据库都遵循 相同的反馈机制,虚线箭头表示心跳消息:

突发写入和大批次​

每个 Frontend 或单机实例使用令牌桶限流,桶容量等于该节点一秒的有效行数 额度。额度随时间补充。

只要桶内至少有一个完整的行令牌,就可以接受一个批次,即使该批次超过剩余 额度。超出的部分会形成债务,由后续补充的额度偿还。在重新获得足够额度 之前,后续写入会被拒绝。这使大于限流额度的批次仍能完成写入,但大批次可能 导致之后较长一段时间内的写入被拒绝。

例如,当额度固定为每秒 1,000 行时,一个满桶可以接受 3,000 行的批次,并产生 2,000 行的债务。在债务偿还完毕且至少补充一个新令牌之前,后续写入会被拒绝。

写入通过准入检查后,即使后续存储处理失败,已消耗的额度也不会退还。 关闭后重新开启限流不会清除尚未偿还的债务。

单机和分布式部署​

单机模式直接按数据库配置的速率限流。

分布式模式由 Metasrv 根据各 Frontend 上报的写入需求,为它们分配数据库额度, 并重新分配空闲额度。Frontend 通过心跳接收更新,在本地执行分配到的额度, 且有效额度不超过数据库配置的速率。

配置的速率是整个集群中该数据库的目标写入速率,并非每个一秒窗口内的严格 上限:

  • 突发写入和大批次可能暂时超过配置速率。
  • 尚未收到分配额度的 Frontend 会在本地使用完整的数据库配置速率,因此在 额度分配收敛前,集群总写入速率可能超过目标值。
  • 每个 Frontend 的有效额度至少为每秒一行。如果配置值小于参与分配的 Frontend 数量,各节点额度之和可能超过配置值。

配置限流​

将数据库选项 ingest_rows_rate_limit 设置为正整数,以指定目标写入速率,单位为 行/秒。该值必须在无符号 64 位整数范围内,不接受 1000/s 等带单位的值。 默认不设置此选项,写入速率不受限制。

通过 CREATE DATABASE 创建数据库, 将目标写入速率设置为每秒 10,000 行:

CREATE DATABASE logs WITH ('ingest_rows_rate_limit' = '10000');

通过 ALTER DATABASE 修改已有数据库的 写入速率:

ALTER DATABASE logs SET 'ingest_rows_rate_limit' = '20000';

修改后无需重启服务。在分布式部署中,各 Frontend 的额度重新分配还取决于 后续的心跳更新。

该选项作用于整个数据库,不能在单个表上设置。创建新表时,它不会作为表选项 被继承。

通过 SHOW CREATE DATABASE 查看已配置的值:

SHOW CREATE DATABASE logs;

关闭限流​

移除该选项即可恢复不限速的写入:

ALTER DATABASE logs UNSET 'ingest_rows_rate_limit';

将值设置为 0 也可以关闭限流:

ALTER DATABASE logs SET 'ingest_rows_rate_limit' = '0';

处理被拒绝的写入​

额度不足时,写入会返回可重试的 RateLimited 错误,GreptimeDB 状态码为 6001。HTTP 写入请求返回 429 Too Many Requests,原生 gRPC 请求返回 RESOURCE_EXHAUSTED。错误信息包含数据库名、被拒绝的行数、当前额度和 数据库配置的限流值。

重试时应使用带随机抖动的指数退避,为额度补充留出时间。减小批次可以减少 单次大批量写入产生的债务,并缩短恢复时间。避免立即连续重试。