TDengine 内存管理 — 池化、缓存、回收

分类 :17.内部机制 | 篇章 :01 内存管理

免费详情

TDengine 是高吞吐时序数据库,内存管理直接决定写入和查询性能。本文从原理角度讲解内存池、缓存层、回收机制。

内存模块速查表

模块 用途
内存表 写入缓冲(按 VNode)
块缓存 读取热数据
元数据缓存 Catalog/Schema
查询内存 临时计算
连接缓存 客户端会话
WAL 缓冲 写前日志

详细解析

1. 内存分层架构

复制代码
┌────────────────────────────────────────┐
│           查询临时内存                  │
│  - 中间结果集                           │
│  - 排序/聚合缓冲                        │
│  - JOIN 哈希表                          │
└────────────────────────────────────────┘
        ▲ 查询时按需分配
        │
┌────────────────────────────────────────┐
│           读缓存层                      │
│  - Block Cache(数据块)                │
│  - Last Cache(最新值)                 │
│  - 元数据缓存                           │
└────────────────────────────────────────┘
        ▲ 查询/写入触发
        │
┌────────────────────────────────────────┐
│           写入内存表                    │
│  - 按 VNode 维护                        │
│  - 达阈值 Flush 到磁盘                  │
└────────────────────────────────────────┘
        ▲ 写入入口
        │
┌────────────────────────────────────────┐
│           WAL 缓冲                      │
│  - 写前日志                             │
│  - 定期 fsync                          │
└────────────────────────────────────────┘

2. 写入内存表

复制代码
原理:

  ① 写入流程:
     Client → RPC → VNode 内存表
                          │
                          ├── 排序(按时间)
                          ├── 合并重复
                          └── 累积到阈值
                                │
                                ▼
                          Flush 到磁盘块


  ② 阈值控制:
     - 配置 buffer 大小(每 VNode)
     - 达到阈值后切换内存表
     - 旧内存表后台 Flush
     - 新写入进入新内存表


  ③ 多版本:
     - 内存表 1(正在写)
     - 内存表 2(正在 Flush)
     - 内存表 3(等待回收)


内存使用估算:
  
  单 VNode buffer ~ 几 MB ~ 几十 MB
  集群多个 VGroup × 多副本 × buffer = 总写入内存
  
  示例:3 节点 × 24 VGroups × 16MB = 1.2 GB

3. 块缓存(Block Cache)

复制代码
原理:

  ① 查询时从磁盘读 Block
  ② Block 缓存到内存
  ③ 后续查询命中缓存直接返回
  ④ LRU 策略淘汰


配置:
  - cache 参数控制大小
  - 自适应淘汰
  - 热点块优先保留


命中率:
  - 时序查询时间局部性强
  - 命中率通常 70%+
  - 大范围历史查询命中率低


作用:
  - 重复查询加速 10x+
  - 减少磁盘 IO
  - 节省 CPU 解压

4. 最新值缓存(Last Cache)

复制代码
原理:

  CACHEMODEL 配置:
    - 'none'        不缓存
    - 'last_row'    缓存整行最新
    - 'last_value'  缓存每列最新值
    - 'both'        都缓存


  作用:
    - SELECT LAST(*)、LAST_ROW(*) 极速
    - 直接从内存返回
    - 不扫描数据块


  适用:
    - 设备实时状态查询
    - 大盘最新值
    - SCADA 实时显示


  开销:
    - 每子表占用少量内存
    - 写入时同步更新
    - 万级子表 ~ 几百 MB

5. 元数据缓存

复制代码
缓存内容:

  ① Catalog(数据库/表信息)
     - 库名、表名、超级表
     - Schema 定义
     
  ② Schema(列定义、Tag 定义)
  
  ③ 路由表(哪个 VGroup 在哪个节点)
  
  ④ 用户权限


客户端缓存:
  - 客户端连接后拉取元数据
  - 本地缓存
  - 版本号检测变化


服务端缓存:
  - MNode 维护权威元数据
  - DNode/VNode 缓存子集
  
  
失效机制:
  - DDL 操作触发版本递增
  - 客户端定期 / 主动检查
  - 缓存淘汰旧版本

6. 查询内存

复制代码
查询过程内存分配:

  ① 解析(小):
     - SQL AST
     - 解析树
     
  ② 优化(小):
     - 计划节点
     
  ③ 执行(大):
     - 输入块缓冲
     - 中间结果
     - 排序缓冲
     - 聚合状态(按组)
     - JOIN 哈希表
     - 输出缓冲


控制:
  - 单查询内存上限(配置)
  - 超过后失败 / 溢出磁盘
  - 大查询用 QNode 隔离


典型规模:
  - 小查询:< 1MB
  - 中查询:几 MB ~ 几十 MB
  - 大聚合(高基数 GROUP BY):GB 级

7. 内存回收

复制代码
回收时机:

  ① 写入内存表 Flush:
     - 落盘后释放
     - 新内存表接收新写入
     
  ② 查询结束:
     - 临时分配回收
     - 缓冲池归还
     
  ③ 连接断开:
     - 会话相关释放
     - 缓存查询结果释放
     
  ④ 缓存 LRU:
     - 内存压力下淘汰冷块
     - 释放给新查询使用
     
  ⑤ 后台压缩/合并:
     - 合并后释放旧块


内存碎片:
  - 使用对象池减少碎片
  - 定期检查碎片率
  - 严重时可重启进程

8. 内存压力应对

复制代码
监控指标:

  - 总内存使用
  - 各模块占比
  - 缓存命中率
  - OOM 风险


应对:

  ① 减少 buffer
     ALTER DATABASE ... BUFFER 8;
     # 减小写入内存
     
  ② 减少 cache
     # 减小块缓存
     
  ③ 关闭 LastCache
     ALTER DATABASE ... CACHEMODEL 'none';
     
  ④ 限制单查询
     # 大查询走 QNode
     
  ⑤ 限制连接数
     ALTER ALL DNODES 'numOfRpcSessions' '5000';
     
  ⑥ 增加物理内存
     # 根本解决


OOM 自我保护:
  - 写入限流
  - 查询拒绝
  - 缓存清理
  - 极端情况:进程退出

代码示例

内存配置参数

cfg 复制代码
# /etc/taos/taos.cfg

# 全局
cache                  16        # 写入缓存(MB)
numOfRpcSessions       5000      # 连接数
numOfCommitThreads     4         # 提交线程

# 按库配置
# CREATE DATABASE iot 
#   BUFFER 256        -- 单 VNode 写入 buffer (MB)
#   CACHE 16          -- 单 VNode 块缓存 (MB)
#   CACHEMODEL 'last_value'   -- LastCache 模式

监控内存使用

sql 复制代码
-- DNode 内存
SELECT endpoint, mem_used, mem_total, 
       mem_used * 100.0 / mem_total AS pct 
FROM information_schema.ins_dnodes;


-- VNode 内存
SELECT db_name, vgroup_id, dnode_id,
       memory_size_mb 
FROM information_schema.ins_vnodes 
ORDER BY memory_size_mb DESC LIMIT 10;


-- log 数据库(监控历史)
SELECT _wstart, endpoint, 
       AVG(memory_usage_pct) AS avg_mem 
FROM log.taosd_dnodes_info 
WHERE ts > NOW - 1h 
PARTITION BY endpoint 
INTERVAL(5m);

内存调优案例

sql 复制代码
-- 案例 1: OOM 频繁
-- 排查:缓存过大
SELECT memory_usage_pct FROM log.taosd_dnodes_info 
WHERE ts > NOW - 1h ORDER BY ts DESC;

-- 措施:缩小 cache
-- ALTER DATABASE ... CACHE 8;


-- 案例 2: 查询慢
-- 排查:缓存命中率低
-- 措施:增加 cache,CACHEMODEL 'last_value'


-- 案例 3: 写入卡顿
-- 排查:内存表 Flush 不及时
-- 措施:增加 numOfCommitThreads,加大 BUFFER

性能考量

内存与性能

内存配置 写入性能 查询性能
充足 最佳 最佳
适中
紧张 退化 退化
不足 OOM OOM

典型配置

集群规模 单节点内存
测试 8 GB
小型生产 32 GB
中型 64 GB
大型 128 GB+

FAQ

Q1: 怎么知道内存够不够?

看 mem_used_pct:

  • < 60%:充足
  • 60~80%:合理
  • 80~90%:紧张
  • 90%:危险

Q2: CACHEMODEL last_value 占多少?

每子表 ~ 200 B × 列数。10 万子表 + 10 列 ~ 200 MB。

Q3: 内存表大小怎么调?

按写入负载和延迟:

  • 高吞吐:大 BUFFER(256MB+)
  • 低延迟:小 BUFFER(16~64MB)

Q4: 查询 OOM 怎么办?

  • 用 LIMIT 限制
  • 加时间过滤
  • 拆分子查询
  • 用 qnode 隔离
  • 升级内存

Q5: 重启后缓存丢失?

是的,缓存是内存中的。重启后第一波查询稍慢,逐步预热。

参考

系统构架篇

数据模型

存储引擎

查询引擎

数据写入

数据订阅

预聚合

索引

SQL 语句

客户端与连接器

运维

安全

生态

应用案例

产品对比

关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

相关推荐
智讯阁17 分钟前
能直接操作电脑的AI助手有哪些?AiPy、QoderWork、TRAE Work、WorkBuddy深度实测
大数据·人工智能
空堂与归19 分钟前
南大 AI 课 Token 自费:用缓存命中率算一学期账单
人工智能·缓存·ai·deepseek
小白说大模型25 分钟前
AI 提示词专栏:Zero-Shot 与 One-Shot Prompt 的差别与适用场景
大数据·数据库·人工智能·sql·深度学习·prompt
oradh30 分钟前
Oracle TM 锁 Mode 4(Share)问题排查总结
数据库·oracle·oracle tm 锁·tm 锁 mode 4
MuMuMu122335 分钟前
文旅户外场景智能回收终端工程难点解析:越华环保集团碳惠小屋耐候与供电系统实践
java·大数据·算法
hzxpaipai37 分钟前
制造业官网产品信息架构怎么设计?从产品分类到后台数据结构
大数据·数据结构
L-岁月染过的梦40 分钟前
把常用开发小工具收进 IDEA:Develop Helper 插件介绍
java·数据库·intellij-idea
IT码农-爱吃辣条41 分钟前
Milvus 向量数据库 Python 实战教程
数据库·python·milvus
hh95042 分钟前
Agent Plan × DeepSeek Harness:基于 DeepSeek 的物理系统数字孪生建模与实时同步:架构设计与实现深度解析
大数据·人工智能·adg·agent plan·adg成都社区