【TiDB 使用环境】测试环境
【TiDB 版本】V 8.5.4
我们针对数据库做了一些测试,有问题请教各位社区大佬。
测试背景:资源组A,配额20000,优先级high,且开了流量突发。资源组B,配额50000,优先级MEDIUM,没开流量突发。A中有个的查询(A.table 2千万全表扫描),占用了很多RU,tikv节点cpu波动不大,当RU占用达到最高的时候,资源组B的大量查询(B.table的查询)进来了,直接导致B的配额被打满,服务的连接池也瞬间被打满,所有tikv节点的cpu也直接被打满;数据库无法对外提供服务。
有以下6点针对tikv层面的问题分析:
缺陷1:优先级限制器被硬编码禁用(最致命)
代码位置:components/resource_control/src/resource_group.rs:279-283
fn enable_priority_limiter(&self) → bool {
// TODO: reenable it once when we fix resource_control: slow read caused by auto priority limiter · Issue #18939 · tikv/tikv · GitHub
// self.get_group_count() > 1
false //
硬编码禁用!
}
问题分析:
这是TiKV官方承认的Bug,指向GitHub issue #18939
优先级限制器被硬编码禁用,导致资源组优先级完全失效
即使A.table在high组、B.table在mid组,两者平等竞争CPU
当非核心业务大查询到来时,无法限制其资源占用
为什么平常正常:
平常负载低,资源充足,即使没有优先级限制也不会崩溃
一旦负载上升,这个缺陷就会导致雪崩
缺陷2:令牌桶容量固定,无法应对突发流量
代码位置:components/resource_control/src/resource_limiter.rs:148-151
limiter: Limiter::builder(limit)
.refill(Duration::from_millis(1000)) //
固定1秒填充
.min_wait(Duration::from_millis(1))
.build(),
问题分析:
令牌桶固定1秒填充,容量固定
无法应对突发流量(如某个时间点有大量查询)
没有自适应调整机制,系统负载90%时仍然按固定速率填充令牌
为什么平常正常:
平常请求量低,令牌桶容量足够
突发流量到来时,令牌桶瞬间耗尽,无法限流
缺陷3:线程池自动调整间隔过长(10秒)
代码位置:src/read_pool.rs:45-53
const READ_POOL_THREAD_CHECK_DURATION: Duration = Duration::from_secs(10); //
10秒检查一次
const READ_POOL_THREAD_HIGH_THRESHOLD: f64 = 0.8; // 80% CPU使用率
const READ_POOL_THREAD_LOW_THRESHOLD: f64 = 0.7; // 70% CPU使用率
const RUNNING_TASKS_PER_THREAD_THRESHOLD: i64 = 3; // 每线程3个任务
问题分析:
线程池自动调整每10秒检查一次
崩溃只用了很短的时间
调整条件苛刻:必须满足4个条件才能扩容
当前线程数 < 最大线程数
扩容后CPU不超载
线程繁忙度 >= 80%
队列任务 >= 每线程3个
为什么平常正常:
平常负载稳定,10秒检查间隔足够
突发流量在10秒内就可能崩溃,来不及扩容
缺陷4:轻任务阈值过低(5ms),大查询容易绕过并发限制
代码位置:src/coprocessor/endpoint.rs:57
const LIGHT_TASK_THRESHOLD: Duration = Duration::from_millis(5); //
只有5ms
问题分析:
查询执行小于5ms不需要获取信号量permit
A.table查询首次执行时可能快速返回(缓存命中)
但后续查询可能因为数据量大而恶化至6-8秒,已经绕过了并发限制
缺乏基于资源消耗的熔断,只有超时熔断
为什么平常正常:
平常查询快速返回(<5ms),无需限流
查询恶化后,已经绕过了并发限制
缺陷5:缺乏查询级别的资源熔断机制
代码位置:src/coprocessor/endpoint.rs:479-480
let deadline = tracker.req_ctx.deadline;
let handle_request_future = check_deadline(handler.handle_request(), deadline);
问题分析:
只有超时熔断(deadline检查),没有资源熔断
emp_assign_detail扫描2530万keys,没有扫描keys上限
tm_charge_whitelist CPU时间恶化至12.5秒,没有CPU时间上限
缺乏基于以下维度的主动熔断:
扫描keys数量
CPU时间消耗
IO读取字节
内存使用量
为什么平常正常:
平常扫描量小(<100万keys),不会触发资源问题
大查询到来时,没有主动熔断,任由资源耗尽
缺陷6:资源组优先级限制器修复算法"buggy"
代码位置:components/resource_control/src/worker.rs(被注释禁用)
// We disable the priority worker by default because the current adjust
// algorithm is buggy. We may reenable it only we find a better algorithm.
问题分析:
TiKV官方注释明确指出调整算法有Bug
优先级限制器的动态调整算法被禁用
无法根据系统负载动态调整各优先级的配额
当系统过载时,无法自动削减低优先级查询的资源配额
为什么平常正常:
平常负载低,不需要动态调整优先级配额
过载时,无法动态调整,导致雪崩