使用资源控制实现资源组限制与流量控制
作为集群管理员,你可以使用资源控制功能创建资源组,设置资源组配额,并绑定用户到这些资源组。
TiDB 的资源控制功能提供了两层资源管理能力:TiDB 层的流量控制能力和 TiKV 层的优先级调度能力。这两种能力可以单独启用或同时启用。详细信息请参见 Parameters for resource control。这样,TiDB 层可以根据为资源组设置的配额控制用户读写请求的流量,而 TiKV 层可以根据映射到读写配额的优先级调度请求。通过这种方式,你可以确保应用的资源隔离,并满足服务质量(QoS)要求。
TiDB 流量控制:TiDB 流量控制采用 token bucket 算法。如果桶中的令牌不足,且资源组未指定
BURSTABLE
选项,请求将等待令牌桶补充令牌后重试。重试可能因超时而失败。TiKV 调度:你可以根据需要设置绝对优先级
PRIORITY
。不同的资源根据PRIORITY
设置进行调度。PRIORITY
高的任务优先调度。如果未设置绝对优先级,TiKV 会根据每个资源组的RU_PER_SEC
值来确定读写请求的优先级。存储层会根据优先级使用优先级队列调度和处理请求。
从 v7.4.0 版本开始,资源控制功能支持控制 TiFlash 资源。其原理类似于 TiDB 流量控制和 TiKV 调度:
- TiFlash 流量控制:结合 TiFlash pipeline 执行模型,TiFlash 能更准确地获取不同查询的 CPU 消耗,并将其转换为用于扣减的 Request Units (RU)。流量控制采用 token bucket 算法实现。
- TiFlash 调度:当系统资源不足时,TiFlash 会根据优先级在多个资源组之间调度 pipeline 任务。具体逻辑为:首先评估资源组的
PRIORITY
,然后考虑 CPU 使用情况和RU_PER_SEC
。例如,若rg1
和rg2
的PRIORITY
相同,但rg2
的RU_PER_SEC
是rg1
的两倍,则rg2
的 CPU 使用率也会是rg1
的两倍。
关于如何管理后台任务和处理资源密集型查询(Runaway Queries),请参阅以下文档:
资源控制场景
引入资源控制功能是 TiDB 的一个里程碑。它可以将分布式数据库集群划分为多个逻辑单元。即使某个单元资源过度使用,也不会挤占其他单元所需的资源。
有了这个功能,你可以:
- 将来自不同系统的多个中小型应用合并到一个 TiDB 集群中。当某个应用的工作负载变大时,不会影响其他应用的正常运行。当系统负载较低时,即使超出配额,繁忙的应用仍能获得所需的系统资源,从而实现资源的最大利用。
- 选择将所有测试环境合并到一个 TiDB 集群,或将消耗较多资源的批处理任务分组到一个资源组中。这可以提高硬件利用率,降低运营成本,同时确保关键应用始终获得必要的资源。
- 当系统中存在混合负载时,可以将不同的负载放入不同的资源组。通过使用资源控制功能,可以确保事务型应用的响应时间不受数据分析或批处理应用的影响。
- 当集群遇到意外的 SQL 性能问题时,可以结合 SQL 绑定和资源组,临时限制某个 SQL 语句的资源消耗。
此外,合理使用资源控制功能还可以减少集群数量,简化运维难度,降低管理成本。
限制
资源控制会带来额外的调度开销。因此,启用该功能时,可能会出现轻微的性能下降(小于 5%)。
什么是 Request Unit (RU)
Request Unit (RU) 是 TiDB 中对系统资源的统一抽象单位,目前包括 CPU、IOPS 和 IO 带宽指标。它用于表示对数据库的单个请求所消耗的资源量。请求消耗的 RU 数量取决于多种因素,例如操作类型、查询或修改的数据量。目前,RU 包含以下表格中的资源消耗统计:
Resource type | RU consumption |
---|---|
Read | 2 storage read batches consume 1 RU |
8 storage read requests consume 1 RU | |
64 KiB read request payload consumes 1 RU | |
Write | 1 storage write batch consumes 1 RU |
1 storage write request consumes 1 RU | |
1 KiB write request payload consumes 1 RU | |
CPU | 3 ms consumes 1 RU |
资源控制参数
资源控制功能引入了以下系统变量或参数:
- TiDB:可以使用
tidb_enable_resource_control
系统变量控制是否启用资源组的流量控制。
- TiKV:对于 TiDB 自管理,可以使用
resource-control.enabled
参数控制是否基于资源组配额进行请求调度。对于 TiDB Cloud,resource-control.enabled
参数的值默认为true
,不支持动态修改。 - TiFlash:对于 TiDB 自管理,可以使用
tidb_enable_resource_control
系统变量和enable_resource_control
配置项(在 v7.4.0 引入)控制是否启用 TiFlash 资源控制。
从 TiDB v7.0.0 版本开始,tidb_enable_resource_control
和 resource-control.enabled
默认开启。这两个参数组合的结果如下表所示。
resource-control.enabled | tidb_enable_resource_control = ON | tidb_enable_resource_control = OFF |
---|---|---|
resource-control.enabled = true | 流量控制和调度(推荐) | 无效组合 |
resource-control.enabled = false | 仅流量控制(不推荐) | 该功能已禁用 |
从 v7.4.0 版本开始,TiFlash 配置项 enable_resource_control
默认为开启。它与 tidb_enable_resource_control
一起控制 TiFlash 资源控制功能。只有当 enable_resource_control
和 tidb_enable_resource_control
都启用时,TiFlash 才会执行流量控制和优先级调度。此外,启用 enable_resource_control
后,TiFlash 使用 Pipeline 执行模型。
关于资源控制机制和参数的更多信息,请参见 RFC: Global Resource Control in TiDB 和 TiFlash Resource Control。
如何使用资源控制
本节介绍如何使用资源控制功能管理资源组以及控制各资源组的资源分配。
估算集群容量
对于 TiDB 自管理,你可以使用 CALIBRATE RESOURCE
语句估算集群容量。
对于 TiDB Cloud,该语句不适用。
管理资源组
要创建、修改或删除资源组,你需要拥有 SUPER
或 RESOURCE_GROUP_ADMIN
权限。
你可以使用 CREATE RESOURCE GROUP
创建集群的资源组。
对于已存在的资源组,可以使用 ALTER RESOURCE GROUP
修改其 RU_PER_SEC
(每秒的 RU 补充速率)选项。对资源组的更改会立即生效。
你也可以使用 DROP RESOURCE GROUP
删除资源组。
创建资源组
以下是创建资源组的示例。
创建资源组
rg1
,资源限制为每秒 500 RU,允许应用在该资源组中超出资源限制。CREATE RESOURCE GROUP IF NOT EXISTS rg1 RU_PER_SEC = 500 BURSTABLE;创建资源组
rg2
,RU 补充速率为每秒 600 RU,不允许应用超出资源限制。CREATE RESOURCE GROUP IF NOT EXISTS rg2 RU_PER_SEC = 600;创建资源组
rg3
,绝对优先级设置为HIGH
。目前支持LOW|MEDIUM|HIGH
,默认值为MEDIUM
。CREATE RESOURCE GROUP IF NOT EXISTS rg3 RU_PER_SEC = 100 PRIORITY = HIGH;
绑定资源组
TiDB 支持以下三个层级的资源组设置。
- 用户层。通过
CREATE USER
或ALTER USER
语句,将用户绑定到特定资源组。用户绑定后,用户创建的会话会自动绑定到对应的资源组。 - 会话层。通过
SET RESOURCE GROUP
设置当前会话的资源组。 - 语句层。通过
RESOURCE_GROUP()
优化器提示,为当前语句设置资源组。
绑定用户到资源组
以下示例创建用户 usr1
,并将其绑定到资源组 rg1
。rg1
是在 创建资源组 中示例创建的资源组。
CREATE USER 'usr1'@'%' IDENTIFIED BY '123' RESOURCE GROUP rg1;
以下示例使用 ALTER USER
将用户 usr2
绑定到资源组 rg2
。rg2
是在 创建资源组 中示例创建的资源组。
ALTER USER usr2 RESOURCE GROUP rg2;
绑定用户后,新创建会话的资源消耗将由指定的配额(Request Unit,RU)控制。如果系统负载较高且没有剩余容量,usr2
的资源消耗速率将受到严格限制,不得超过配额。由于 usr1
绑定在配置了 BURSTABLE
的 rg1
上,usr1
的消耗速率允许超出配额。
如果请求过多导致资源组资源不足,客户端请求将等待。如果等待时间过长,请求会报错。
ALTER USER 'usr3'@'%' RESOURCE GROUP `default`;
有关详细信息,请参见 ALTER USER ... RESOURCE GROUP
。
将当前会话绑定到资源组
你可以使用 SET RESOURCE GROUP
语句,改变当前会话绑定的资源组。通过绑定会话到资源组,限制该会话的资源使用(RU)。
当系统变量 tidb_resource_control_strict_mode
设置为 ON
时,执行此语句需要拥有 SUPER
或 RESOURCE_GROUP_ADMIN
或 RESOURCE_GROUP_USER
权限。
以下示例将当前会话绑定到资源组 rg1
。
SET RESOURCE GROUP rg1;
将当前语句绑定到资源组
通过在 SQL 语句中添加 RESOURCE_GROUP(resource_group_name)
提示,可以指定该语句绑定的资源组。此提示支持 SELECT
、INSERT
、UPDATE
和 DELETE
语句。
当系统变量 tidb_resource_control_strict_mode
设置为 ON
时,使用此提示需要拥有 SUPER
或 RESOURCE_GROUP_ADMIN
或 RESOURCE_GROUP_USER
权限。
以下示例将当前语句绑定到资源组 rg1
。
SELECT /*+ RESOURCE_GROUP(rg1) */ * FROM t limit 10;
禁用资源控制
执行以下语句禁用资源控制功能。
SET GLOBAL tidb_enable_resource_control = 'OFF';对于 TiDB 自管理,可以使用
resource-control.enabled
参数控制是否基于资源组配额进行请求调度。对于 TiDB Cloud,resource-control.enabled
参数的值默认为true
,不支持动态修改。如需在 TiDB Cloud Dedicated 集群中禁用此功能,请联系 TiDB Cloud Support。对于 TiDB 自管理,可以使用
enable_resource_control
配置项控制是否启用 TiFlash 资源控制。对于 TiDB Cloud,enable_resource_control
参数的值默认为true
,不支持动态修改。如需在 TiDB Cloud Dedicated 集群中禁用此功能,请联系 TiDB Cloud Support。
查看 RU 消耗
你可以查看 RU 消耗信息。
查看 SQL 的 RU 消耗
你可以通过以下方式查看 SQL 语句的 RU 消耗:
- 系统变量
tidb_last_query_info
EXPLAIN ANALYZE
- 慢查询及对应的系统表
statements_summary
通过查询系统变量 tidb_last_query_info
查看上次 SQL 执行的 RU
TiDB 提供了系统变量 tidb_last_query_info
。该变量记录了上次执行的 DML 语句信息,包括该 SQL 执行的 RU。
示例:
执行
UPDATE
语句:UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id = 1;Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0查询系统变量
tidb_last_query_info
查看上次执行语句的信息:SELECT @@tidb_last_query_info;+------------------------------------------------------------------------------------------------------------------------+ | @@tidb_last_query_info | +------------------------------------------------------------------------------------------------------------------------+ | {"txn_scope":"global","start_ts":446809472210829315,"for_update_ts":446809472210829315,"ru_consumption":4.34885578125} | +------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec)结果中,
ru_consumption
即为该 SQL 执行所消耗的 RU。
通过 EXPLAIN ANALYZE
查看 SQL 执行的 RU
你可以使用 EXPLAIN ANALYZE
获取 SQL 执行过程中消耗的 RU 数量。注意,RU 数量受缓存(例如 coprocessor cache)影响。当多次执行相同 SQL 时,每次的 RU 消耗可能不同。RU 数值不代表每次执行的精确值,但可作为估算参考。
慢查询及对应的系统表
启用资源控制后,系统表 INFORMATION_SCHEMA.SLOW_QUERY
会包含资源组信息、对应 SQL 的 RU 消耗以及等待可用 RU 的时间。
通过 statements_summary
查看 RU 统计信息
TiDB 的系统表 INFORMATION_SCHEMA.statements_summary
存储了 SQL 语句的归一化和聚合统计信息。你可以通过该表查看和分析 SQL 执行性能,还包含资源控制的统计信息,包括资源组名、RU 消耗和等待可用 RU 的时间。更多详情请参见 statements_summary
字段说明。
查看资源组的 RU 消耗
从 v7.6.0 版本开始,TiDB 提供了系统表 mysql.request_unit_by_group
,用于存储各资源组的 RU 消耗历史记录。
示例:
SELECT * FROM request_unit_by_group LIMIT 5;
+----------------------------+----------------------------+----------------+----------+
| start_time | end_time | resource_group | total_ru |
+----------------------------+----------------------------+----------------+----------+
| 2024-01-01 00:00:00.000000 | 2024-01-02 00:00:00.000000 | default | 334147 |
| 2024-01-01 00:00:00.000000 | 2024-01-02 00:00:00.000000 | rg1 | 4172 |
| 2024-01-01 00:00:00.000000 | 2024-01-02 00:00:00.000000 | rg2 | 34028 |
| 2024-01-02 00:00:00.000000 | 2024-01-03 00:00:00.000000 | default | 334088 |
| 2024-01-02 00:00:00.000000 | 2024-01-03 00:00:00.000000 | rg1 | 3850 |
+----------------------------+----------------------------+----------------+----------+
5 rows in set (0.01 sec)
监控指标与图表
TiDB 定期收集资源控制的运行时信息,并在 Grafana 的 TiDB > Resource Control 仪表盘中提供指标的可视化图表。
TiKV 也会在 Grafana 的 TiKV 仪表盘中记录来自不同资源组的请求 QPS。
工具兼容性
资源控制功能不会影响数据导入、导出及其他复制工具的正常使用。BR、TiDB Lightning 和 TiCDC 目前不支持处理与资源控制相关的 DDL 操作,其资源消耗也不受资源控制限制。
常见问题
如果我不想使用资源组,是否必须禁用资源控制?
不需要。未指定资源组的用户会绑定到资源无限制的
default
资源组。当所有用户都属于default
资源组时,资源分配方式与禁用资源控制时相同。数据库用户可以绑定多个资源组吗?
不可以。一个数据库用户只能绑定到一个资源组。但在会话运行期间,可以使用
SET RESOURCE GROUP
设置当前会话使用的资源组,也可以使用优化器提示RESOURCE_GROUP()
设置运行语句的资源组。如果所有资源组的总资源分配(
RU_PER_SEC
)超过系统容量,会发生什么?TiDB 在创建资源组时不会验证容量。只要系统有足够的可用资源,TiDB 就能满足每个资源组的资源需求。当系统资源超出限制时,TiDB 会优先满足高优先级资源组的请求。如果同一优先级的请求不能全部满足,TiDB 会根据
RU_PER_SEC
按比例分配资源。