0
0
0
0
博客/.../

tikv-client.max-batch-size 参数与 gRPC 交互模式的思考

 Jayjlchen  发表于  2026-02-13

一、背景

某用户在 TiDB 4.0 集群遇到点查抖动的 CASE,需要设置 tikv-client.max-batch-size: 0,关闭 Batch Client 特性,避免触发 gRPC 饥饿问题。

二、分析

2.1 gRPC 四种交互模式

  1. Simple RPC(简单模式)

客户端发一个请求,服务端处理完立刻返回一个响应。

  1. Server‑side streaming(服务端流式) 客户端发一个请求,服务端持续发多条数据流回去,直到流结束。
  2. Client‑side streaming(客户端流式) 客户端持续发多条数据给服务端,最后服务端合并处理后返回一次响应。
  3. Bidirectional streaming(双向流式) 客户端和服务端都可以不断互相发送数据流,彼此独立收发,直到任意一方关闭流。

Batch Client 基于「双向流式」模式:TiDB client 和 TiKV 每次保持一个长期的 bidi‑stream,复用同一条连接来收发批量命令。

2.2 为什么要 Batch Client?

  • 在高并发场景下,TiDB → TiKV 的 gRPC 调用请求非常频繁。
  • 每发一次 RPC,TiKV 都要调度一个线程去处理网络、反序列化、调度业务逻辑,CPU 开销不小。
  • Batch Client 就是在 TiDB 端把多条小命令(Command)先积累起来,一次性打包(batch)成一个 gRPC 消息发给 TiKV,减少 RPC 次数,从而降低 TiKV gRPC 线程的 CPU 使用率。

2.3 核心参数及含义

image.png

2.4 Batch Client 启用时的工作流程示例

step1: 请求入队 TiDB 收到一条新的 KV 请求,先放到本地的「待发送队列」中。

step2: 检查批量大小

  • 如果队列长度 ≥ max-batch-size(默认为 128),就立即把这 128 条打包发给 TiKV;
  • 否则,继续下一步。

step3: 检查等待策略是否启用

  • 如果 max-batch-wait-time = 0(默认值),表示不等待,直接把队列中所有请求(不足 128 条也好)打包发出;
  • 如果 max-batch-wait-time > 0,则进入第 4 步。

step4: 判断 TiKV gRPC CPU 负载 查询关联 TiKV 实例的 gRPC 线程池 CPU 利用率:

  • 如果 CPU 使用率 ≤ overload-threshold(200%),立即发送当前所有请求;
  • 如果 CPU 使用率 > 200%,进入第 5 步。

step5: 等待收集更多请求max-batch-wait-time(如 50 ms)内:

  • 如果队列长度达到 batch-wait-size(默认 8),立即发送这批请求;
  • 如果时间到(超过 max-batch-wait-time)还没达 8 条,也强制把当前队列里的请求发出。

step6: 完成一次批量发送 清空已发送的请求,队列里剩余请求重新从步骤 2 开始判断。

关闭 Batch Clientmax-batch-size 设为 0 时,上面所有“打包发送”逻辑都不生效,TiDB 收到新请求就立刻做一次简单 RPC,保证最低延迟,但也带来更多的 gRPC 调度开销。

2.5 gRPC 线程饥饿问题

  • 饥饿原因: TiKV 的 gRPC 实现对每个双向流(stream)采取“贪婪处理”策略:只要某条流还有数据就一直跑这个流,不去切换到其他流上。

  • 后果: 当某些流持续发包,其他流就一直拿不到 CPU,造成延迟抖动。

  • 解决思路: 关闭 Batch Client(即 max‑batch‑size=0),让每条请求都走简单模式 RPC:

    • 每个 SQL 操作都会新建或复用一个短连接(goroutine 并行处理),不会因为一个长流占用线程池而饿死其他流。
    • 请求不再打包,虽然 RPC 次数增多,但单条请求的延迟更可控、抖动更小。
    • 适合对延迟敏感、并发流模式复杂的场景。

三、总结

这个问题并不算 issue,这是 gRPC 能力上的不足。gRPC 暂不支持 preemptive scheduling 和 work stealing。如果一个大任务长期占用一个 gRPC 线程,就会使得这个线程的等待队列上的其他小任务延时增加。

高吞吐更重要、对 CPU 开销敏感的集群 → 打开 Batch Client(默认128)。

低延迟更重要的集群 → 关闭 Batch Client(max‑batch‑size=0),回到 Simple RPC。

0
0
0
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论