TiKV MVCC 内存引擎
TiKV MVCC 内存引擎 (In-Memory Engine, IME) 主要用于加速需要扫描大量 MVCC 历史版本的查询,即查询扫描的总共版本数量 (total_keys
) 远大于处理的版本数量 (processed_keys
)。
TiKV MVCC 内存引擎适用于以下场景:
- 业务需要查询频繁更新或删除的记录。
- 业务需要调整
tidb_gc_life_time
,使 TiDB 保留较长时间的历史版本(比如 24 小时)。
工作原理
TiKV MVCC 内存引擎在内存中缓存最近写入的 MVCC 版本,并实现独立于 TiDB 的 MVCC GC 机制,使其可快速 GC 内存中的 MVCC 记录,从而减少查询时扫描版本的个数,以达到降低请求延时和减少 CPU 开销的效果。
下图为 TiKV 如何组织 MVCC 版本的示意图:
以上示意图中共有 2 行记录,每行记录各有 9 个 MVCC 版本。在开启内存引擎和未开启内存引擎的情况下,行为对比如下:
- 左侧(未开启内存引擎):表中记录按主键升序保存在 RocksDB 中,相同行的 MVCC 版本紧邻在一起。
- 右侧(开启了内存引擎):RocksDB 中的数据与左侧一致,同时内存引擎缓存了 2 行记录最新的 2 个 MVCC 版本。
- 当 TiKV 处理一个范围为
[k1, k2]
,开始时间戳为8
的扫描请求时:- 左侧未开启内存引擎时需要处理 11 个 MVCC 版本。
- 右侧开启内存引擎时只需处理 4 个 MVCC 版本,因此减少了请求延时和 CPU 消耗。
- 当 TiKV 处理一个范围为
[k1, k2]
,开始时间戳为7
的扫描请求时:- 由于右侧缺少需要读取的历史版本,因此内存引擎缓存失效,回退到读取 RocksDB 中的数据。
使用方式
如果要开启 TiKV MVCC 内存引擎 (IME) 功能,需要调整 TiKV 配置并重启 TiKV。以下是配置说明:
[in-memory-engine]
# 该参数为内存引擎功能的开关,默认为 false,调整为 true 即可开启。
enable = false
# 该参数控制内存引擎可使用的内存大小。默认值为系统内存的 10%,同时最大值为 5 GiB,
# 可通过手动调整配置以使用更多内存。
# 注意:当内存引擎开启后,block-cache.capacity 会减少 10%。
capacity = "5GiB"
# 该参数控制内存引擎 GC 缓存 MVCC 的版本的时间间隔。
# 默认为 3 分钟,代表每 3 分钟 GC 一次缓存的 MVCC 版本。
# 调小该参数可加快 GC 频率,减少 MVCC 记录,但会增加 GC CPU 的消耗和增加内存引擎失效的概率。
gc-run-interval = "3m"
# 该参数控制内存引擎选取加载 Region 时 MVCC 读放大的阈值。
# 默认为 10,表示在某个 Region 中读一行记录需要处理的 MVCC 版本数量超过 10 个时,将有可能会被加载到内存引擎中。
mvcc-amplification-threshold = 10
自动加载
开启内存引擎之后,TiKV 会根据 Region 的读流量和 MVCC 放大程度,选择要自动加载的 Region。具体流程如下:
- Region 按照最近时间段的
next
(RocksDB Iterator next API) 和prev
(RocksDB Iterator prev API) 次数进行排序。 - 使用
mvcc-amplification-threshold
配置项对 Region 进行过滤,该配置项的默认值为10
。MVCC amplification 衡量读放大程度,计算公式为 (next
+prev
) /processed_keys
)。 - 载入前 N 个 MVCC 放大严重的 Region,其中 N 基于内存估算而来。
内存引擎也会定期驱逐 Region。具体流程如下:
- 内存引擎会驱逐那些读流量过小或者 MVCC 放大程度过低的 Region。
- 如果内存使用达到了
capacity
的 90%,并且有新的 Region 需要被载入,那么内存引擎会根据读取流量来筛选 Region 并进行驱逐。
兼容性
- BR:内存引擎与 BR 可同时使用,但 BR restore 会驱逐内存引擎中涉及恢复的 Region,BR restore 完成后,如果对应 Region 还是热点,则会被内存引擎自动加载。
- TiDB Lightning:内存引擎与 TiDB Lightning 可同时使用,但 TiDB Lightning 的物理导入模式会驱逐内存引擎中涉及恢复的 Region,TiDB Lightning 使用物理导入模式完成导入数据后,如果对应 Region 还是热点,则会被内存引擎自动加载。
- Follower Read 与 Stale Read:内存引擎可与这两个特性同时开启,但内存引擎只能加速 Leader 上的 coprocessor 请求,无法加速 Follower Read 和 Stale Read。
FLASHBACK CLUSTER
:内存引擎与 Flashback 可同时使用,但 Flashback 会导致内存引擎缓存失效。Flashback 完成后,内存引擎会自动加载热点 Region。
FAQ
内存引擎能否减少写入延时,提高写入吞吐?
不能。内存引擎只能加速扫描了大量 MVCC 版本的读请求。
如何判断内存引擎是否能改善我的场景?
可以通过执行以下 SQL 语句查看是否存在 Total_keys
远大于 Process_keys
的慢查询:
SELECT
Time,
DB,
Index_names,
Process_keys,
Total_keys,
CONCAT(
LEFT(REGEXP_REPLACE(Query, '\\s+', ' '), 20),
'...',
RIGHT(REGEXP_REPLACE(Query, '\\s+', ' '), 10)
) as Query,
Query_time,
Cop_time,
Process_time
FROM
INFORMATION_SCHEMA.SLOW_QUERY
WHERE
Is_internal = 0
AND Cop_time > 1
AND Process_keys > 0
AND Total_keys / Process_keys >= 10
AND Time >= NOW() - INTERVAL 10 MINUTE
ORDER BY Total_keys DESC
LIMIT 5;
示例:
以下结果显示 db1.tbl1
表上存在 MVCC 放大严重的查询,TiKV 在处理 1358517 个 MVCC 版本后,仅返回了 2 个版本。
+----------------------------+-----+-------------------+--------------+------------+-----------------------------------+--------------------+--------------------+--------------------+
| Time | DB | Index_names | Process_keys | Total_keys | Query | Query_time | Cop_time | Process_time |
+----------------------------+-----+-------------------+--------------+------------+-----------------------------------+--------------------+--------------------+--------------------+
| 2024-11-18 11:56:10.303228 | db1 | [tbl1:some_index] | 2 | 1358517 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.2581352350000001 | 1.25651062 | 1.251837479 |
| 2024-11-18 11:56:11.556257 | db1 | [tbl1:some_index] | 2 | 1358231 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.252694002 | 1.251129038 | 1.240532546 |
| 2024-11-18 12:00:10.553331 | db1 | [tbl1:some_index] | 2 | 1342914 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.473941872 | 1.4720495900000001 | 1.3666103170000001 |
| 2024-11-18 12:01:52.122548 | db1 | [tbl1:some_index] | 2 | 1128064 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.058942591 | 1.056853228 | 1.023483875 |
| 2024-11-18 12:01:52.107951 | db1 | [tbl1:some_index] | 2 | 1128064 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.044847031 | 1.042546122 | 0.934768555 |
+----------------------------+-----+-------------------+--------------+------------+-----------------------------------+--------------------+--------------------+--------------------+
5 rows in set (1.26 sec)