TDengine Catalog 与元数据缓存

分类 :17.内部机制 | 篇章:04 Catalog 与元数据缓存

免费详情

Catalog 是数据库的"地图":库、表、列、Tag、路由信息。本文讲解 Catalog 设计、客户端缓存、一致性机制。

Catalog 内容速查

说明
数据库 库元信息
超级表 Schema + Tag 定义
子表 Tag 值 + 所在 VGroup
路由 VGroup → DNode 映射
用户 权限信息
索引 索引元数据

详细解析

1. 元数据层级

复制代码
集群元数据(MNode 维护):

  Cluster
    │
    ├── DNode 列表(节点)
    │
    ├── Database 列表
    │     │
    │     ├── STable 列表
    │     │     │
    │     │     ├── Schema(列定义)
    │     │     ├── Tag Schema
    │     │     └── 子表索引
    │     │
    │     └── VGroup 列表
    │           │
    │           └── 副本分配
    │
    ├── User 列表
    │
    └── 流/订阅 列表


权威性:
  - MNode RAFT 副本保证
  - 强一致
  - 操作通过 Leader
  - 失效后自动选举

2. 元数据存储

复制代码
MNode 持久化:

  ① 内存常驻
     - 全部元数据加载到内存
     - 高效查询
     
  ② 持久化机制
     - 写日志 + Snapshot
     - 启动时恢复
     - RAFT 复制到副本


VNode 元数据:

  ① 包含 VGroup 内的:
     - 超级表 Schema
     - 子表信息(Tag + 列)
     - 索引
     
  ② 持久化在 VNode 数据目录


大小估算:
  - 单超级表元数据 ~ KB
  - 单子表 Tag ~ 百字节
  - 100 万子表 ~ 100 MB 内存

3. 客户端缓存

复制代码
客户端 Catalog Cache:

  ① 连接时获取:
     - 库列表
     - 表列表(按需)
     - 路由表
     
  ② 解析 SQL 用:
     - 查表是否存在
     - 校验列名
     - 路由到 VGroup
     
  ③ 缓存策略:
     - LRU
     - TTL
     - 版本号检测


缓存命中率:
  - 静态环境:> 99%
  - 频繁建表:低
  - 影响每次查询的额外开销

4. 元数据一致性

复制代码
版本号机制:

  ① 每次 DDL 操作:
     - MNode 版本号递增
     - 元数据更新持久化
     - 通知关联 DNode/VNode
     
  ② 客户端检测:
     - 每个请求带版本号
     - 服务端返回最新版本
     - 客户端发现落后 → 主动刷新
     
  ③ VNode 检测:
     - 收到请求版本号过旧 → 拒绝
     - 收到过新 → 主动拉取


一致性保证:
  - DDL 操作:通过 MNode 串行化
  - 客户端缓存:最终一致
  - VNode:强一致(RAFT)

5. 路由解析

复制代码
SQL 执行的路由步骤:

  ① 解析 SQL → AST
       └─ 提取库名 + 表名 + WHERE 条件
  
  ② Catalog 查询:
       └─ 库存在?
       └─ 表存在?
       └─ Schema 信息?
  
  ③ Tag 过滤优化:
       └─ WHERE 含 Tag 条件
       └─ 利用 Tag 索引缩小子表集
  
  ④ 路由计算:
       └─ 子表 → VGroup
       └─ VGroup → DNode(取 Leader)
  
  ⑤ 任务下发:
       └─ 按 VGroup 拆分子任务
       └─ 并行发送到各 DNode

6. DDL 操作流程

复制代码
CREATE TABLE / ALTER TABLE 流程:

  ① 客户端 → MNode(任意节点中转)
  
  ② MNode Leader 接收:
     - 验证语法
     - 验证权限
     - 检查冲突
     
  ③ RAFT 写入:
     - 写日志
     - 复制到 Follower
     - majority 确认
     
  ④ 应用到状态机:
     - 更新元数据
     - 版本号递增
     
  ⑤ 通知 VNode:
     - 异步推送变更
     - VNode 应用 schema
     
  ⑥ 返回客户端


延迟:
  - 简单 DDL:< 100ms
  - 复杂(大量子表):秒级
  - 跨节点同步:异步

7. 缓存失效

复制代码
失效场景:

  ① 主动失效:
     - DDL 操作(DROP TABLE)
     - 用户权限变化
     
  ② 检测失效:
     - 请求带旧版本号
     - 服务端返回错误
     - 客户端清缓存重试
     
  ③ TTL 失效:
     - 缓存条目过期
     - 主动刷新


客户端策略:
  - 失败重试时刷新
  - 周期心跳获取最新版本
  - 收到 invalidation 通知(视实现)


典型情况:
  - DROP TABLE 后查询 → 错误 → 客户端刷新 → 重试 → 报"表不存在"
  - ALTER ADD COLUMN → 旧客户端可继续工作,新列需更新

8. 调优与监控

复制代码
元数据相关问题:

  ① 大量子表导致内存高
     - 解决:减少 Tag 组合,合并子表
     
  ② DDL 慢
     - 解决:避免高频建表
     - Schemaless 自动创建走优化路径
     
  ③ 客户端缓存命中低
     - 解决:长连接,避免频繁重连
     - 检查 SQL 是否每次都不同表
     
  ④ 元数据查询延迟
     - 解决:MNode 节点资源
     - 增加 MNode 数(少数情况)


监控:

  -- 子表数量
  SELECT db_name, COUNT(*) 
  FROM information_schema.ins_tables 
  GROUP BY db_name;
  
  -- 超级表数量
  SELECT COUNT(*) FROM information_schema.ins_stables;
  
  -- MNode 状态
  SHOW MNODES;
  SELECT * FROM information_schema.ins_mnodes;

代码示例

客户端连接优化

python 复制代码
# 不好:频繁建连
for _ in range(1000):
  conn = taosws.connect("...")
  conn.execute("SELECT ...")
  conn.close()
# 每次都要重新拉元数据


# 好:长连接复用
conn = taosws.connect("...")
for _ in range(1000):
  conn.execute("SELECT ...")
conn.close()


# 更好:连接池
from queue import Queue

class ConnectionPool:
  def __init__(self, size=10):
    self.pool = Queue()
    for _ in range(size):
      self.pool.put(taosws.connect("..."))
  
  def execute(self, sql):
    conn = self.pool.get()
    try:
      return conn.execute(sql)
    finally:
      self.pool.put(conn)

大量建表优化

python 复制代码
# 不好:逐表 CREATE
for i in range(100000):
  conn.execute(f"CREATE TABLE d_{i} USING meters TAGS ('Beijing')")
# 元数据更新 10 万次


# 好:写入时自动建表
for i in range(100000):
  conn.execute(f"""
    INSERT INTO d_{i} USING meters TAGS ('Beijing') 
    VALUES (NOW, 25.3)
  """)


# 更好:Schemaless 批量
lines = []
for i in range(100000):
  lines.append(f"meters,device=d_{i},location=Beijing current=25.3 {ts}")
conn.execute_schemaless(lines)

性能考量

元数据操作开销

操作 开销
查询缓存命中 < 1µs
查询缓存失效 1~10ms(拉元数据)
CREATE TABLE 10~100ms
ALTER TABLE 10~100ms
子表 INSERT(自动建) 10ms 首次

容量限制

典型上限
单库子表数 千万级
单 STable 列数 4096
单 STable Tag 数 128
单库 STable 数 万级

FAQ

Q1: 元数据丢了怎么办?

MNode RAFT REPLICA 3 提供保护。极端情况:

  • 从备份恢复
  • 联系官方支持

Q2: 客户端缓存怎么手动刷新?

通常自动处理。手动可重连。

Q3: 子表数过多影响性能?

  • 内存占用大(每子表 Tag)
  • 元数据查询慢
  • 建议合理设计 Tag,避免过细

Q4: SHOW TABLES 慢?

子表数过多时慢。优化:

  • 按超级表过滤
  • 用 LIMIT
  • 查 ins_tables 系统表带过滤

Q5: MNode 数怎么选?

  • 小集群:1(无 HA)
  • 标准生产:3
  • 超大集群:3 或 5
    不需要太多,MNode 不存数据。

参考

系统构架篇

数据模型

存储引擎

查询引擎

数据写入

数据订阅

预聚合

索引

SQL 语句

客户端与连接器

运维

安全

生态

应用案例

产品对比

内部机制

关于 TDengine

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

相关推荐
玫瑰互动GEO1 小时前
腾讯AnswerBit(GEO优化监测平台)技术拆解:UI自动化如何采集真实AI回答
大数据·人工智能·ui·ai·自动化·geo优化
CarIise1 小时前
MySQL数据库表关系与多表查询:从表间关系设计到JOIN联表查询
数据库·mysql
网络工程小王2 小时前
【LLM开发实验】FastAPI 学习笔记
数据库·笔记·学习·mysql·fastapi
zhuhai_xigedian2 小时前
源网荷储一体化柜的经济效益优化功能实现机制
大数据·运维·人工智能·重构·能源
Aime_Perfect2 小时前
sqlserver always on
服务器·数据库·sqlserver
摘星编程2 小时前
从“数据出库“到“模型入库“:DolphinDB 库内机器学习全流程实践
数据库
huizhulihuiwu2 小时前
高端大型会议会务系统 私有化部署:如何平衡安全、性能与成本?
大数据·安全·会议签到·智能会议·会务系统
Sagittarius_A*2 小时前
【好靶场】SQL注入-时间盲注
数据库·sql
jianqiang.xue2 小时前
收官:从v0.1到“研发新常态“,一套嵌入式智能体的落地与边界
stm32·单片机·物联网·架构·esp32