diff --git a/docs/zh/10-tdinternal/01-arch.md b/docs/zh/10-tdinternal/01-arch.md
new file mode 100644
index 0000000000..c45ae56bb6
--- /dev/null
+++ b/docs/zh/10-tdinternal/01-arch.md
@@ -0,0 +1,324 @@
+---
+sidebar_label: 整体架构
+title: 整体架构
+toc_max_heading_level: 4
+description: TDengine 架构设计,包括:集群、存储、缓存与持久化、数据备份、多级存储等
+---
+
+## 集群与基本逻辑单元
+
+TDengine 的设计是基于单个硬件、软件系统不可靠,基于任何单台计算机都无法提供足够计算能力和存储能力处理海量数据的假设进行设计的。因此 TDengine 从研发的第一天起,就按照分布式高可靠架构进行设计,是支持水平扩展的,这样任何单台或多台服务器发生硬件故障或软件错误都不影响系统的可用性和可靠性。同时,通过节点虚拟化并辅以负载均衡技术,TDengine 能最高效率地利用异构集群中的计算和存储资源降低硬件投资。
+
+### 主要逻辑单元
+
+TDengine 分布式架构的逻辑结构图如下:
+
+
+
+
图 1 TDengine架构示意图
+
+一个完整的 TDengine 系统是运行在一到多个物理节点上的,逻辑上,它包含数据节点(dnode)、TDengine 应用驱动(taosc)以及应用(app)。系统中存在一到多个数据节点,这些数据节点组成一个集群(cluster)。应用通过 taosc 的 API 与 TDengine 集群进行互动。下面对每个逻辑单元进行简要介绍。
+
+**物理节点(pnode):**
+pnode 是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有 OS 的物理机、虚拟机或 Docker 容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine 完全依赖 FQDN 来进行网络通讯。
+
+**数据节点(dnode):**
+dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例。在一个 TDengine 系统中,至少需要一个 dnode 来确保系统的正常运行。每个 dnode 包含零到多个逻辑的虚拟节点(vnode),但管理节点、弹性计算节点和流计算节点各有 0 个或 1 个逻辑实例。
+
+dnode 在 TDengine 集群中的唯一标识由其实例的 endpoint(EP)决定。endpoint 是由dnode 所在物理节点的 FQDN 和配置的网络端口组合而成。通过配置不同的端口,一个pnode(无论是物理机、虚拟机还是 Docker 容器)可以运行多个实例,即拥有多个 dnode。
+
+**虚拟节点(vnode):**
+为了更好地支持数据分片、负载均衡以及防止数据过热或倾斜,TDengine 引入了 vnode(虚拟节点)的概念。虚拟节点被虚拟化为多个独立的 vnode 实例(如上面架构图中的 V2、V3、V4 等),每个 vnode 都是一个相对独立的工作单元,负责存储和管理一部分时序数据。
+
+每个 vnode 都拥有独立的运行线程、内存空间和持久化存储路径,确保数据的隔离性和高效访问。一个 vnode 可以包含多张表(即数据采集点),这些表在物理上分布在不
+同的 vnode 上,以实现数据的均匀分布和负载均衡。
+
+当在集群中创建一个新的数据库时,系统会自动为该数据库创建相应的 vnode。一个dnode 上能够创建的 vnode 数量取决于该 dnode 所在物理节点的硬件资源,如 CPU、内存和存储容量等。需要注意的是,一个 vnode 只能属于一个数据库,但一个数据库可以包含多个 vnode。
+
+除了存储时序数据以外,每个 vnode 还保存了其包含的表的 schema 信息和标签值等元数据。这些信息对于数据的查询和管理至关重要。
+
+在集群内部,一个 vnode 由其所归属的 dnode 的 endpoint 和所属的 vgroup ID 唯一标识。管理节点负责创建和管理这些 vnode,确保它们能够正常运行并协同工作。
+
+**管理节点(mnode):**
+mnode(管理节点)是 TDengine 集群中的核心逻辑单元,负责监控和维护所有 dnode的运行状态,并在节点之间实现负载均衡(如图 15-1 中的 M1、M2、M3 所示)。作为元数据(包括用户、数据库、超级表等)的存储和管理中心,mnode 也被称为 MetaNode。
+
+为了提高集群的高可用性和可靠性,TDengine 集群允许有多个(最多不超过 3 个)mnode。这些 mnode 自动组成一个虚拟的 mnode 组,共同承担管理职责。mnode 支持多副本,并采用 Raft 一致性协议来确保数据的一致性和操作的可靠性。在 mnode 集群中,任何数据更新操作都必须在 leader 节点上执行。
+
+mnode 集群的第 1 个节点在集群部署时自动创建,而其他节点的创建和删除则由用户通过 SQL 手动完成。每个 dnode 上最多有一个 mnode,并由其所归属的 dnode 的endpoint 唯一标识。
+
+为了实现集群内部的信息共享和通信,每个 dnode 通过内部消息交互机制自动获取整个集群中所有 mnode 所在的 dnode 的 endpoint。
+
+**计算节点(qnode):**
+qnode(计算节点)是 TDengine 集群中负责执行查询计算任务的虚拟逻辑单元,同时也处理基于系统表的 show 命令。为了提高查询性能和并行处理能力,集群中可以配置多个 qnode,这些 qnode 在整个集群范围内共享使用(如图 15-1 中的 Q1、Q2、Q3 所示)。
+
+与 dnode 不同,qnode 并不与特定的数据库绑定,这意味着一个 qnode 可以同时处理来自多个数据库的查询任务。每个 dnode 上最多有一个 qnode,并由其所归属的 dnode 的endpoint 唯一标识。
+
+当客户端发起查询请求时,首先与 mnode 交互以获取当前可用的 qnode 列表。如果在集群中没有可用的 qnode,计算任务将在 vnode 中执行。当执行查询时,调度器会根据执行计划分配一个或多个 qnode 来共同完成任务。qnode 能够从 vnode 获取所需的数据,并将计算结果发送给其他 qnode 进行进一步处理。
+
+通过引入独立的 qnode,TDengine 实现了存储和计算的分离。
+
+**流计算节点(snode):**
+snode(流计算节点)是 TDengine 集群中专门负责处理流计算任务的虚拟逻辑单元(如上架构图 中的 S1、S2、S3 所示)。为了满足实时数据处理的需求,集群中可以配置多个 snode,这些 snode 在整个集群范围内共享使用。
+
+与 dnode 类似,snode 并不与特定的流绑定,这意味着一个 snode 可以同时处理多个流的计算任务。每个 dnode 上最多有一个 snode,并由其所归属的 dnode 的 endpoint 唯一标识。
+
+当需要执行流计算任务时,mnode 会调度可用的 snode 来完成这些任务。如果在集群中没有可用的 snode,流计算任务将在 vnode 中执行。
+
+通过将流计算任务集中在 snode 中处理,TDengine 实现了流计算与批量计算的分离,从而提高了系统对实时数据的处理能力。
+
+**虚拟节点组(VGroup):**
+
+vgroup(虚拟节点组)是由不同 dnode 上的 vnode 组成的一个逻辑单元。这些 vnode之间采用 Raft 一致性协议,确保集群的高可用性和高可靠性。在 vgroup 中,写操作只能在 leader vnode 上执行,而数据则以异步复制的方式同步到其他 follower vnode,从而在多个物理节点上保留数据副本。
+
+vgroup 中的 vnode 数量决定了数据的副本数。要创建一个副本数为 N 的数据库,集群必须至少包含 N 个 dnode。副本数可以在创建数据库时通过参数 replica 指定,默认值为 1。利用 TDengine 的多副本特性,企业可以摒弃昂贵的硬盘阵列等传统存储设备,依然实现数据的高可靠性。
+
+vgroup 由 mnode 负责创建和管理,并为其分配一个集群唯一的 ID,即 vgroup ID。如果两个 vnode 的 vgroup ID 相同,则说明它们属于同一组,数据互为备份。值得注意的是,vgroup 中的 vnode 数量可以动态调整,但 vgroup ID 始终保持不变,即使 vgroup 被删除,其 ID 也不会被回收和重复利用。
+
+通过这种设计,TDengine 在保证数据安全性的同时,实现了灵活的副本管理和动态扩展能力
+
+**Taosc**
+
+taosc(应用驱动)是 TDengine 为应用程序提供的驱动程序,负责处理应用程序与集群之间的接口交互。taosc 提供了 C/C++ 语言的原生接口,并被内嵌于 JDBC、C#、Python、Go、Node.js 等多种编程语言的连接库中,从而支持这些编程语言与数据库交互。
+
+应用程序通过 taosc 而非直接连接集群中的 dnode 与整个集群进行通信。taosc 负责获取并缓存元数据,将写入、查询等请求转发到正确的 dnode,并在将结果返回给应用程序之前,执行最后一级的聚合、排序、过滤等操作。对于 JDBC、C/C++、C#、Python、Go、Node.js 等接口,taosc 是在应用程序所处的物理节点上运行的。
+
+此外,taosc 还可以与 taosAdapter 交互,支持全分布式的 RESTful 接口。这种设计使得 TDengine 能够以统一的方式支持多种编程语言和接口,同时保持高性能和可扩展性。
+
+### 节点之间的通信
+
+**通信方式:**
+
+TDengine 集群内部的各个 dnode 之间以及应用驱动程序与各个 dnode 之间的通信均通过 TCP 方式实现。这种通信方式确保了数据传输的稳定性和可靠性。
+
+为了优化网络传输性能并保障数据安全,TDengine 会根据配置自动对传输的数据进行压缩和解压缩处理,以减少网络带宽的占用。同时,TDengine 还支持数字签名和认证机制,确保数据在传输过程中的完整性和机密性得到保障。
+
+**FQDN 配置:**
+
+在 TDengine 集群中,每个 dnode 可以拥有一个或多个 FQDN。为了指定 dnode 的 FQDN,可以在配置文件 taos.cfg 中使用 fqdn 参数进行配置。如果没有明确指定,dnode 将自动获取其所在计算机的 hostname 并作为默认的 FQDN。
+
+虽然理论上可以将 taos.cfg 中的 FQDN 参数设置为 IP 地址,但官方并不推荐这种做法。因为 IP 地址可能会随着网络环境的变化而变化,这可能导致集群无法正常工作。当使用 FQDN 时,需要确保 DNS 服务能够正常工作,或者在节点和应用程序所在的节点上正确配置 hosts 文件,以便解析 FQDN 到对应的 IP 地址。此外,为了保持良好的兼容性和可移植性,fqdn 参数值的长度应控制在 96 个字符以内。
+
+**端口配置:**
+
+在 TDengine 集群中,每个 dnode 对外提供服务时使用的端口由配置参数 serverPort 决定。默认情况下,该参数的值为 6030。通过调整 serverPort 参数,可以灵活地配置 dnode 的对外服务端口,以满足不同部署环境和安全策略的需求。
+
+**集群对外连接:**
+
+TDengine 集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可。这种设计简化了应用程序与集群之间的交互过程,提高了系统的可扩展性和易用性。
+
+当使用 TDengine CLI 启动 taos 时,可以通过以下选项来指定 dnode 的连接信息。
+- -h :用于指定 dnode 的 FQDN。这是一个必需项,用于告知应用程序连接到哪个dnode。
+- -P :用于指定 dnode 的端口。这是一个可选项,如果不指定,将使用 TDengine 的配置参数 serverPort 作为默认值。
+
+通过这种方式,应用程序可以灵活地连接到集群中的任意 dnode,而无须关心集群的具体拓扑结构。
+
+**集群内部通讯:**
+
+在 TDengine 集群中,各个 dnode 之间通过 TCP 方式进行通信。当一个 dnode 启动时,它会首先获取 mnode 所在 dnode 的 endpoint 信息。其次,新启动的 dnode 与集群中的 mnode 建立连接,并进行信息交换。
+
+这一过程确保了 dnode 能够及时加入集群,并与 mnode 保持同步,从而能够接收和执行集群层面的命令和任务。通过 TCP 连接,dnode 之间以及 dnode 与 mnode 之间能够可靠地传输数据,保障集群的稳定运行和高效的数据处理能力。
+
+获取 mnode 的 endpoint 信息的步骤如下:
+- 第 1 步:检查自己的 dnode.json 文件是否存在,如果不存在或不能正常打开以获得mnode endpoint 信息,进入第 2 步。
+- 第 2 步,检查配置文件 taos.cfg,获取节点配置参数 firstEp、secondEp(这两个参数指定的节点可以是不带 mnode 的普通节点,这样的话,节点被连接时会尝试重定向到 mnode 节点),如果不存在 firstEP、secondEP,或者 taos.cfg 中没有这两个配置参数,或者参数无效,进入第 3 步。
+- 第 3 步,将自己的 endpoint 设为 mnode endpoint,并独立运行。
+
+获取 mnode 的 endpoint 列表后,dnode 发起连接,如果连接成功,则成功加入工作的集群;如果不成功,则尝试 mnode endpoint 列表中的下一个。如果都尝试了,但仍然连接失败,则休眠几秒后再次尝试。
+
+**Mnode 的选择:**
+
+在 TDengine 集群中,mnode 是一个逻辑上的概念,它并不对应于一个单独执行代码的实体。实际上,mnode 的功能由服务器侧的 taosd 进程负责管理。
+
+在集群部署阶段,第 1 个 dnode 会自动承担 mnode 的角色。随后,用户可以通过 SQL 在集群中创建或删除额外的 mnode,以满足集群管理的需求。这种设计使得 mnode 的数量和配置具有很高的灵活性,可以根据实际应用场景进行调整。
+
+**新数据节点的加入:**
+
+一旦 TDengine 集群中有一个 dnode 启动并运行,该集群便具备了基本的工作能力。为了扩展集群的规模,可以按照以下两个步骤添加新节点。
+- 第 1 步,首先使用 TDengine CLI 连接现有的 dnode。其次,执行 create dnode 命令来 添加新的 dnode。这个过程将引导用户完成新 dnode 的配置和注册过程- 。
+- 第 2 步,在新加入的 dnode 的配置文件 taos.cfg 中设置 firstEp 和 secondEp 参数。这两个参数应分别指向现有集群中任意两个活跃 dnode 的 endpoint。这样做可以确保新dnode 能够正确加入集群,并与现有节点进行通信。
+
+**重定向:**
+
+在 TDengine 集群中,无论是新启动的 dnode 还是 taosc,它们首先需要与集群中的mnode 建立连接。然而,用户通常并不知道哪个 dnode 正在运行 mnode。为了解决这个问题,TDengine 采用了一种巧妙的机制来确保它们之间的正确连接。
+
+具体来说,TDengine 不要求 dnode 或 taosc 直接连接到特定的 mnode。相反,它们只需要向集群中的任何一个正在工作的 dnode 发起连接。由于每个活跃的 dnode 都维护着当前运行的 mnode endpoint 列表,因此这个连接请求会被转发到适当的 mnode。
+
+当接收到来自新启动的 dnode 或 taosc 的连接请求时,如果当前 dnode 不是 mnode,它会立即将 mnode endpoint 列表回复给请求方。收到这个列表后,taosc 或新启动的dnode 可以根据这个列表重新尝试建立与 mnode 的连接。
+
+此外,为了确保集群中的所有节点都能及时获取最新的 mnode endpoint 列表,TDengine 采用了节点间的消息交互机制。当 mnode endpoint 列表发生变化时,相关的更新会通过消息迅速传播到各个 dnode,进而通知到 taosc。
+
+### 一个典型的消息流程
+
+为解释 vnode、mnode、taosc 和应用之间的关系以及各自扮演的角色,下面对写入数据这个典型操作的流程进行剖析。
+
+
+
+ 图 2 TDengine 典型的操作流程
+
+1. 应用通过 JDBC 或其他 API 接口发起插入数据的请求。
+2. taosc 会检查缓存,看是否保存有该表所在数据库的 vgroup-info 信息。如果有,直接到第 4 步。如果没有,taosc 将向 mnode 发出 get vgroup-info 请求。
+3. mnode 将该表所在数据库的 vgroup-info 返回给 taosc。Vgroup-info 包含数据库的 vgroup 分布信息(vnode ID 以及所在的 dnode 的 End Point,如果副本数为 N,就有 N 组 End Point),还包含每个 vgroup 中存储数据表的 hash 范围。如果 taosc 迟迟得不到 mnode 回应,而且存在多个 mnode,taosc 将向下一个 mnode 发出请求。
+4. taosc 会继续检查缓存,看是否保存有该表的 meta-data。如果有,直接到第 6 步。如果没有,taosc 将向 vnode 发出 get meta-data 请求。
+5. vnode 将该表的 meta-data 返回给 taosc。Meta-data 包含有该表的 schema。
+6. taosc 向 leader vnode 发起插入请求。
+7. vnode 插入数据后,给 taosc 一个应答,表示插入成功。如果 taosc 迟迟得不到 vnode 的回应,taosc 会认为该节点已经离线。这种情况下,如果被插入的数据库有多个副本,taosc 将向 vgroup 里下一个 vnode 发出插入请求。
+8. taosc 通知 APP,写入成功。
+
+对于第二步,taosc 启动时,并不知道 mnode 的 End Point,因此会直接向配置的集群对外服务的 End Point 发起请求。如果接收到该请求的 dnode 并没有配置 mnode,该 dnode 会在回复的消息中告知 mnode EP 列表,这样 taosc 会重新向新的 mnode 的 EP 发出获取 meta-data 的请求。
+
+对于第四和第六步,没有缓存的情况下,taosc 无法知道虚拟节点组里谁是 leader,就假设第一个 vnodeID 就是 leader,向它发出请求。如果接收到请求的 vnode 并不是 leader,它会在回复中告知谁是 leader,这样 taosc 就向建议的 leader vnode 发出请求。一旦得到插入成功的回复,taosc 会缓存 leader 节点的信息。
+
+上述是插入数据的流程,查询、计算的流程也完全一致。taosc 把这些复杂的流程全部封装屏蔽了,对于应用来说无感知也无需任何特别处理。
+
+通过 taosc 缓存机制,只有在第一次对一张表操作时,才需要访问 mnode,因此 mnode 不会成为系统瓶颈。但因为 schema 有可能变化,而且 vgroup 有可能发生改变(比如负载均衡发生),因此 taosc 会定时和 mnode 交互,自动更新缓存。
+
+## 存储模型与数据分区、分片
+
+### 存储模型
+
+TDengine 存储的数据包括采集的时序数据以及库、表相关的元数据、标签数据等,这些数据具体分为三部分:
+
+- 时序数据:TDengine 的核心存储对象,存放于 vnode 里,由 data、head 和 last 三个文件组成,数据量大,查询量取决于应用场景。容许乱序写入,但暂时不支持删除操作,并且仅在 update 参数设置为 1 时允许更新操作。通过采用一个采集点一张表的模型,一个时间段的数据是连续存储,对单张表的写入是简单的追加操作,一次读,可以读到多条记录,这样保证对单个采集点的插入和查询操作,性能达到最优。
+- 数据表元数据:包含标签信息和 Table Schema 信息,存放于 vnode 里的 meta 文件,支持增删改查四个标准操作。数据量很大,有 N 张表,就有 N 条记录,因此采用 LRU 存储,支持标签数据的索引。TDengine 支持多核多线程并发查询。只要计算内存足够,元数据全内存存储,千万级别规模的标签数据过滤结果能毫秒级返回。在内存资源不足的情况下,仍然可以支持数千万张表的快速查询。
+- 数据库元数据:存放于 mnode 里,包含系统节点、用户、DB、STable Schema 等信息,支持增删改查四个标准操作。这部分数据的量不大,可以全内存保存,而且由于客户端有缓存,查询量也不大。因此目前的设计虽是集中式存储管理,但不会构成性能瓶颈。
+
+与传统的 NoSQL 存储模型相比,TDengine 将标签数据与时序数据完全分离存储,它具有两大优势:
+
+- 显著降低标签数据存储的冗余度。在常见的 NoSQL 数据库或时序数据库中,通常采用 Key-Value 存储模型,其中 Key 包含时间戳、设备 ID 以及各种标签。这导致每条记录都携带大量重复的标签信息,从而浪费宝贵的存储空间。此外,如果应用程序需要在历史数据上增加、修改或删除标签,就必须遍历整个数据集并重新写入,这样的操作成本极高。相比之下,TDengine 通过将标签数据与时序数据分离存储,有效避免了这些问题,大大减少了存储空间的浪费,并降低了标签数据操作的成本。
+- 实现极为高效的多表之间的聚合查询。在进行多表之间的聚合查询时,TDengine 首先根据标签过滤条件找出符合条件的表,然后查找这些表对应的数据块。这种方法显著减少了需要扫描的数据集大小,从而大幅提高了查询效率。这种优化策略使得 TDengine 能够在处理大规模时序数据时保持高效的查询性能,满足各种复杂场景下的数据分析需求。
+
+### 数据分片
+
+在进行海量数据管理时,为了实现水平扩展,通常需要采用数据分片(sharding)和数据分区(partitioning)策略。TDengine 通过 vnode 来实现数据分片,并通过按时间段划分数据文件来实现时序数据的分区。
+
+vnode 不仅负责处理时序数据的写入、查询和计算任务,还承担着负载均衡、数据恢复以及支持异构环境的重要角色。为了实现这些目标,TDengine 将一个 dnode 根据其计算和存储资源切分为多个 vnode。这些 vnode 的管理过程对应用程序是完全透明的,由TDengine 自动完成。。
+
+对于单个数据采集点,无论其数据量有多大,一个 vnode 都拥有足够的计算资源和存储资源来应对(例如,如果每秒生成一条 16B 的记录,一年产生的原始数据量也不到 0.5GB)。因此,TDengine 将一张表(即一个数据采集点)的所有数据都存储在一个vnode 中,避免将同一数据采集点的数据分散到两个或多个 dnode 上。同时,一个 vnode 可以存储多个数据采集点(表)的数据,最大可容纳的表数目上限为 100 万。设计上,一个 vnode 中的所有表都属于同一个数据库。
+
+TDengine 3.0 采用一致性哈希算法来确定每张数据表所在的 vnode。在创建数据库时,集群会立即分配指定数量的 vnode,并确定每个 vnode 负责的数据表范围。当创建一张表时,集群会根据数据表名计算出其所在的 vnode ID,并在该 vnode 上创建表。如果数据库有多个副本,TDengine 集群会创建一个 vgroup,而不是仅创建一个 vnode。集群对 vnode 的数量没有限制,仅受限于物理节点本身的计算和存储资源。
+
+每张表的元数据(包括 schema、标签等)也存储在 vnode 中,而不是集中存储在mnode 上。这种设计实际上是对元数据的分片,有助于高效并行地进行标签过滤操作,进一步提高查询性能。
+
+### 数据分区
+
+除了通过 vnode 进行数据分片以外,TDengine 还采用按时间段对时序数据进行分区的策略。每个数据文件仅包含一个特定时间段的时序数据,而时间段的长度由数据库参数 duration 决定。这种按时间段分区的做法不仅简化了数据管理,还便于高效实施数据的保留策略。一旦数据文件超过了规定的天数(由数据库参数 keep 指定),系统将自动删除这些过期的数据文件。
+
+此外,TDengine 还支持将不同时间段的数据存储在不同的路径和存储介质中。这种灵活性使得大数据的冷热管理变得简单易行,用户可以根据实际需求实现多级存储,从而优化存储成本和访问性能。
+
+综合来看,TDengine 通过 vnode 和时间两个维度对大数据进行精细切分,实现了高效并行管理和水平扩展。这种设计不仅提高了数据处理的速度和效率,还为用户提供了灵活、可扩展的数据存储和查询解决方案,满足了不同规模和需求的场景应用。
+
+### 负载均衡与扩容
+
+每个 dnode 都会定期向 mnode 报告其当前状态,包括硬盘空间使用情况、内存大小、CPU 利用率、网络状况以及 vnode 的数量等关键指标。这些信息对于集群的健康监控和资源调度至关重要。
+
+关于负载均衡的触发时机,目前 TDengine 允许用户手动指定。当新的 dnode 被添加到集群中时,用户需要手动启动负载均衡流程,以确保集群在最佳状态下运行。
+
+随着时间的推移,集群中的数据分布可能会发生变化,导致某些 vnode 成为数据热点。为了应对这种情况,TDengine 采用基于 Raft 协议的副本调整和数据拆分算法,实现了数据的动态扩容和再分配。这一过程可以在集群运行时无缝进行,不会影响数据的写入和查询服务,从而确保了系统的稳定性和可用性。
+
+## 数据写入与复制流程
+
+在一个具有 N 个副本的数据库中,相应的 vgroup 将包含 N 个编号相同的 vnode。在这些 vnode 中,只有一个被指定为 leader,其余的都充当 follower 的角色。这种主从架构确保了数据的一致性和可靠性。
+
+当应用程序尝试将新记录写入集群时,只有 leader vnode 能够接受写入请求。如果 follower vnode 意外地收到写入请求,集群会立即通知 taosc 需要重新定向到 leader vnode。这一措施确保所有的写入操作都发生在正确的 leader vnode 上,从而维护数据的一致性和完整性。
+
+通过这种设计,TDengine 确保了在分布式环境下数据的可靠性和一致性,同时提供高效的读写性能。
+
+### Leader Vnode 写入流程
+
+Leader Vnode 遵循下面的写入流程:
+
+
+
+ 图 3 TDengine Leader 写入流程
+
+- 第 1 步: leader vnode 收到应用的写入数据请求,验证 OK,验证有效性后进入第 2 步;
+- 第 2 步:vnode 将该请求的原始数据包写入数据库日志文件 WAL。如果 `wal_level` 设置为 2,而且 `wal_fsync_period` 设置为 0,TDengine 还将 WAL 数据立即落盘,以保证即使宕机,也能从数据库日志文件中恢复数据,避免数据的丢失;
+- 第 3 步:如果有多个副本,vnode 将把数据包转发给同一虚拟节点组内的 follower vnodes,该转发包带有数据的版本号(version);
+- 第 4 步:写入内存,并将记录加入到 skip list。但如果未达成一致,会触发回滚操作;
+- 第 5 步:leader vnode 返回确认信息给应用,表示写入成功;
+- 第 6 步:如果第 2、3、4 步中任何一步失败,将直接返回错误给应用;
+
+### Follower Vnode 写入流程
+
+对于 follower vnode,写入流程是:
+
+
+
+ 图 4 TDengine Follower 写入流程
+
+- 第 1 步:follower vnode 收到 leader vnode 转发了的数据插入请求。
+- 第 2 步:vnode 将把该请求的原始数据包写入数据库日志文件 WAL。如果 `wal_level` 设置为 2,而且 `wal_fsync_period` 设置为 0,TDengine 还将 WAL 数据立即落盘,以保证即使宕机,也能从数据库日志文件中恢复数据,避免数据的丢失。
+- 第 3 步:写入内存,更新内存中的 skip list。
+
+与 leader vnode 相比,follower vnode 不存在转发环节,也不存在回复确认环节,少了两步。但写内存与 WAL 是完全一样的。
+
+### 主从选择
+
+每个 vnode 都维护一个数据的版本号,该版本号在 vnode 对内存中的数据进行持久化存储时也会被一并持久化。每次更新数据时,无论是时序数据还是元数据,都会使版本号递增,确保数据的每次修改都被准确记录。
+
+当 vnode 启动时,它的角色(leader 或 follower)是不确定的,且数据处于未同步状态。为了确定自己的角色并同步数据,vnode 需要与同一 vgroup 内的其他节点建立 TCP连接。在连接建立后,vnode 之间会互相交换版本号、任期等关键信息。基于这些信息,vnode 将使用标准的 Raft 一致性算法完成选主过程,从而确定谁是 leader,谁应该作为follower。
+
+这一机制确保在分布式环境下,vnode 之间能够有效地协调一致,维护数据的一致性和系统的稳定性
+
+### 同步复制
+
+在 TDengine 中,每次 leader vnode 接收到写入数据请求并将其转发给其他副本时,它并不会立即通知应用程序写入成功。相反,leader vnode 需要等待超过半数的副本(包括自身)达成一致意见后,才会向应用程序确认写入操作已成功。如果在规定的时间内未能获得半数以上副本的确认,leader vnode 将返回错误信息给应用程序,表明写入数据操作失败。
+
+这种同步复制的机制确保了数据在多个副本之间的一致性和安全性,但同时也带来了写入性能方面的挑战。为了平衡数据一致性和性能需求,TDengine 在同步复制过程中引入了流水线复制算法。
+
+流水线复制算法允许不同数据库连接的写入数据请求确认过程同时进行,而不是顺序等待。这样,即使某个副本的确认延迟,也不会影响到其他副本的写入操作。通过这种方式,TDengine 在保证数据一致性的同时,显著提升了写入性能,满足了高吞吐量和低延迟的数据处理需求。
+
+### 成员变更
+
+在数据扩容、节点迁移等场景中,需要对 vgroup 的副本数目进行调整。在这些情况下,存量数据的多少直接影响到副本之间数据复制的所需时间,过多的数据复制可能会
+严重阻塞数据的读写过程。
+
+为了解决这一问题,TDengine 对 Raft 协议进行了扩展,引入了 learner 角色。learner 角色在复制过程中起到至关重要的作用,但它们不参与投票过程,只负责接收数据的复制。由于 learner 不参与投票,因此在数据写入时,判断写入成功的条件并不包括 learner 的确认。
+
+当 learner 与 leader 之间的数据差异较大时,learner 会采用快照(snapshot)方式进行数据同步。快照同步完成后,learner 会继续追赶 leader 的日志,直至两者数据量接近。一旦 learner 与 leader 的数据量足够接近,learner 便会转变为 follower 角色,开始参与数据写入的投票和选举投票过程。
+
+### 重定向
+
+当 taosc 将新的记录写入 TDengine 集群时,它首先需要定位到当前的 leader vnode,因为只有 leader vnode 负责处理写入数据请求。如果 taosc 尝试将写入数据请求发送到 follower vnode,集群会立即通知 taosc 需要重新定向到正确的 leader vnode。
+
+为了确保写入数据请求能够正确路由到 leader vnode,taosc 会维护一个关于节点组拓扑的本地缓存。当收到集群的通知后,taosc 会根据最新的节点组拓扑信息,重新计算并确定 leader vnode 的位置,然后将写入数据请求发送给它。同时,taosc 还会更新本地缓存中的 leader 分布信息,以备后续使用。
+
+这种机制确保了应用在通过 taosc 访问 TDengine 时,无须关心网络重试的问题。无论集群中的节点如何变化,taosc 都能自动处理这些变化,确保写入数据请求始终被正确地路由到 leader vnode
+
+## 缓存与持久化
+
+### 时序数据缓存
+
+TDengine 采纳了一种独特的时间驱动缓存管理策略,亦称为写驱动缓存管理机制。这一策略与传统的读驱动数据缓存模式有所不同,其核心在于优先将最新写入的数据存储在集群的缓存中。当缓存容量接近阈值时,系统会将最早期的数据进行批量写入硬盘的操作。详细来讲,每个 vnode 都拥有独立的内存空间,这些内存被划分为多个固定大小的内存块,且不同 vnode 之间的内存是完全隔离的。在数据写入过程中,采用的是类似日志记录的顺序追加方式,每个 vnode 还维护有自身的 SkipList 结构,以便于数据的快速检索。一旦超过三分之一的内存块被写满,系统便会启动数据落盘的过程,并将新的写入操作引导至新的内存块。通过这种方式,vnode 中的三分之一内存块得以保留最新的数据,既实现了缓存的目的,又保证了查询的高效性。vnode 的内存大小可以通过数据库参数 buffer 进行配置。
+
+此外,考虑到物联网数据的特点,用户通常最关注的是数据的实时性,即最新产生的数据。TDengine 很好地利用了这一特点,优先将最新到达的(即当前状态)数据存储在缓存中。具体而言,TDengine 会将最新到达的数据直接存入缓存,以便快速响应用户对最新一条或多条数据的查询和分析需求,从而在整体上提高数据库查询的响应速度。从这个角度来看,通过合理设置数据库参数,TDengine 完全可以作为数据缓存来使用,这样就无须再部署 Redis 或其他额外的缓存系统。这种做法不仅有效简化了系统架构,还有助于降低运维成本。需要注意的是,一旦 TDengine 重启,缓存中的数据将被清除,所有先前缓存的数据都会被批量写入硬盘,而不会像专业的 Key-Value 缓存系统那样自动将之前缓存的数据重新加载回缓存。
+
+### 持久化存储
+
+TDengine 采用了一种数据驱动的策略来实现缓存数据的持久化存储。当 vnode 中的缓存数据积累到一定量时,为了避免阻塞后续数据的写入,TDengine 会启动落盘线程,将这些缓存数据写入持久化存储设备。在此过程中,TDengine 会创建新的数据库日志文件用于数据落盘,并在落盘成功后删除旧的日志文件,以防止日志文件无限制增长。
+
+为了充分发挥时序数据的特性,TDengine 将一个 vnode 的数据分割成多个文件,每个文件仅存储固定天数的数据,这个天数由数据库参数 duration 设定。通过这种分文件存储的方式,当查询特定时间段的数据时,无须依赖索引即可迅速确定需要打开哪些数据文件,极大地提高了数据读取的效率。
+
+对于采集的数据,通常会有一定的保留期限,该期限由数据库参数 keep 指定。超出设定天数的数据文件将被集群自动移除,并释放相应的存储空间。
+
+当设置 duration 和 keep 两个参数后,一个处于典型工作状态的 vnode 中,总的数据文件数量应为向上取整 (keep/duration)+1 个。数据文件的总个数应保持在一个合理的范围内,不宜过多也不宜过少,通常介于 10 到 100 之间较为适宜。基于这一原则,可以合理设置 duration 参数。在本书编写时的版本中,可以调整参数 keep,但参数 duration 一旦设定,则无法更改。
+
+在每个数据文件中,表的数据是以块的形式存储的。一张表可能包含一到多个数据文件块。在一个文件块内,数据采用列式存储,占据连续的存储空间,这有助于显著提高读取度。文件块的大小由数据库参数 maxRows(每块最大记录条数)控制,默认值为 4096。这个值应适中,过大可能导致定位特定时间段数据的搜索时间变长,影响读取速度;过小则可能导致数据文件块的索引过大,压缩效率降低,同样影响读取速度。
+
+每个数据文件块(以 .data 结尾)都配有一个索引文件(以 .head 结尾),该索引文件包含每张表的各个数据文件块的摘要信息,记录了每个数据文件块在数据文件中的偏移量、数据的起始时间和结束时间等信息,以便于快速定位所需数据。此外,每个数据文件块还有一个与之关联的 last 文件(以 .last 结尾),该文件旨在防止数据文件块在落盘时发生碎片化。如果某张表落盘的记录条数未达到数据库参数 minRows(每块最小记录条数)的要求,这些记录将首先存储在 last 文件中,待下次落盘时,新落盘的记录将与 last文件中的记录合并,然后再写入数据文件块。
+
+在数据写入硬盘的过程中,是否对数据进行压缩取决于数据库参数 comp 的设置。TDengine 提供了 3 种压缩选项—无压缩、一级压缩和二级压缩,对应的 comp 值分别为 0、1 和 2。一级压缩会根据数据类型采用相应的压缩算法,如 delta-delta 编码、simple8B 方法、zig-zag 编码、LZ4 等。二级压缩则在一级压缩的基础上进一步使用通用压缩算法,以实现更高的压缩率。
+
+### 预计算
+
+为了显著提高查询处理的效率,TDengine 在数据文件块的头部存储了该数据文件块的统计信息,包括最大值、最小值和数据总和,这些被称为预计算单元。当查询处理涉及这些计算结果时,可以直接利用这些预计算值,而无须访问数据文件块的具体内容。对于那些硬盘 I/O 成为瓶颈的查询场景,利用预计算结果可以有效减轻读取硬盘 I/O 的压力,从而提高查询速度。
+
+除了预计算功能以外,TDengine 还支持对原始数据进行多种降采样存储。一种降采样存储方式是 Rollup SMA,它能够自动对原始数据进行降采样存储,并支持 3 个不同的数据保存层级,用户可以指定每层数据的聚合周期和保存时长。这对于那些关注数据趋势的场景尤为适用,其核心目的是减少存储开销并提高查询速度。另一种降采样存储方式是 Time-Range-Wise SMA,它可以根据聚合结果进行降采样存储,非常适合于高频的 interval 查询场景。该功能采用与普通流计算相同的逻辑,并允许用户通过设置watermark 来处理延时数据,相应地,实际的查询结果也会有一定的时间延迟。
+
+### 多级存储与对象存储
+
+在默认情况下,TDengine 将所有数据存储在 /var/lib/taos 目录中。为了扩展存储容量,减少文件读取可能导致的瓶颈,并提升数据吞吐量,TDengine 允许通过配置参数dataDir,使得集群能够同时利用挂载的多块硬盘。
+
+此外,TDengine 还提供了数据分级存储的功能,允许用户将不同时间段的数据存储在不同存储设备的目录中,以此实现将“热”数据和“冷”数据分开存储。这样做可以充分利用各种存储资源,同时节约成本。例如,对于最新采集且需要频繁访问的数据,由于其读取性能要求较高,用户可以配置将这些数据存储在高性能的固态硬盘上。而对于超过一定期限、查询需求较低的数据,则可以将其存储在成本相对较低的机械硬盘上。
+
+为了进一步降低存储成本,TDengine 还支持将时序数据存储在对象存储系统中。通过其创新性的设计,在大多数情况下,从对象存储系统中查询时序数据的性能接近本地硬盘的一半,而在某些场景下,性能甚至可以与本地硬盘相媲美。同时,TDengine 还允许用户对存储在对象存储中的时序数据执行删除和更新操作。
\ No newline at end of file
diff --git a/docs/zh/10-tdinternal/03-storage.md b/docs/zh/10-tdinternal/03-storage.md
new file mode 100644
index 0000000000..f65f06e85b
--- /dev/null
+++ b/docs/zh/10-tdinternal/03-storage.md
@@ -0,0 +1,124 @@
+---
+sidebar_label: 存储引擎
+title: 存储引擎
+toc_max_heading_level: 4
+description: TDengine 存储引擎
+---
+
+TDengine 的核心竞争力在于其卓越的写入和查询性能。相较于传统的通用型数据库,TDengine 在诞生之初便专注于深入挖掘时序数据场景的独特性。它充分利用了时序数据的时间有序性、连续性和高并发特点,自主研发了一套专为时序数据定制的写入及存储算法。
+
+这套算法针对时序数据的特性进行了精心的预处理和压缩,不仅大幅提高了数据的写入速度,还显著降低了存储空间的占用。这种优化设计确保了在面对大量实时数据持续涌入的场景时,TDengine 仍能保持超高的吞吐能力和极快的响应速度。
+
+## 行列格式
+
+行列格式是 TDengine 中用来表示数据的最重要的数据结构之一。业内已经有许多开源的标准化的行列格式库,如 Apache Arrow 等。但 TDengine 面临的场景更加聚焦,且对于性能的要求也更高。因此,设计并实现自己的行列格式库有助于 TDengine 充分利用场景特点,实现高性能、低空间占用的行列格式数据结构。行列格式的需求有以下几点。
+- 支持未指定值(NONE)与空值(NULL)的区分。
+- 支持 NONE、NULL 以及有值共存的不同场景。
+- 对于稀疏数据和稠密数据的高效处理。
+
+### 行格式
+
+TDengine 中的行格式有两种编码格式—Tuple 编码格式和 Key-Value 编码格式。具体采用哪种编码格式是由数据的特征决定的,以求最高效地处理不同数据特征的场景。
+
+1. Tuple 编码格式
+
+Tuple 编码格式主要用于非稀疏数据的场景,如所有列数据全部非 None 或少量 None 的场景。Tuple 编码的行直接根据表的 schema 提供的偏移量信息访问列数据,时间复杂度为O(1),访问速度快。如下图所示:
+
+
+
+2. Key-Value 编码格式
+
+Key-Value 编码格式特别适合于稀疏数据的场景,即在表的 schema 中定义了大量列(例如数千列),但实际有值的列却非常少的情况。在这种情形下,如果采用传统的 Tuple 编码格式,会造成极大的空间浪费。相比之下,采用 Key-Value 编码格式可以显著减少行数据所占用的存储空间。如下图所示。
+
+Key-Value 编码的行数据通过一个 offset 数组来索引各列的值,虽然这种方式的访问速度相对于直接访问列数据较慢,但它能显著减少存储空间的占用。在实际编码实现中,通过引入 flag 选项,进一步优化了空间占用。具体来说,当所有 offset 值均小于 256 时,Key-Value 编码行的 offset 数组采用 uint8_t 类型;若所有 offset 值均小于 65 536 时,则使用 uint16_t 类型;在其他情况下,则使用 uint32_t 类型。这样的设计使得空间利用率得到进一步提升。
+
+
+
+### 列格式
+
+在 TDengine 中,列格式的定长数据可以被视为数组,但由于存在 NONE、NULL和有值的并存情况,列格式中还需要一个 bitmap 来标识各个索引位置的值是 NONE、NULL 还是有值。而对于变长类型的数据,列格式则有所不同。除了数据数组以外,变长类型的数据列格式还包含一个 offset 数组,用于索引变长数据的起始位置。变长数据的长度可以通过两个相邻 offset 值之差来获得。这种设计使得数据的存储和访问更加高效,如下图所示:
+
+
+
+## vnode 存储
+
+### vnode 存储架构
+
+vnode 是 TDengine 中数据存储、查询以及备份的基本单元。每个 vnode 中都存储了部分表的元数据信息以及属于这些表的全部时序数据。表在 vnode 上的分布是由一致性哈希决定的。每个 vnode 都可以被看作一个单机数据库。vnode 的存储可以分为如下 3 部分,如下图所示。
+- WAL 文件的存储。
+- 元数据的存储。
+- 时序数据的存储。
+
+
+
+当 vnode 收到写入数据请求时,首先会对请求进行预处理,以确保多副本上的数据保持一致。预处理的目的在于确保数据的安全性和一致性。在预处理完成后,数据会被写入到 WAL 文件中,以确保数据的持久性。接着,数据会被写入 vnode 的内存池中。当内存池的空间占用达到一定阈值时,后台线程会将写入的数据刷新到硬盘上(META 和TSDB),以便持久化。同时,标记内存中对应的 WAL 编号为已落盘。此外,TSDB 采用了 LSM(Log-Structured Merge-Tree,日志结构合并树)存储结构,这种结构在打开数据库的多表低频参数时,后台还会对 TSDB 的数据文件进行合并,以减少文件数量并提高查询性能。这种设计使得数据的存储和访问更加高效。
+
+### 元数据的存储
+
+vnode 中存储的元数据主要涉及表的元数据信息,包括超级表的名称、超级表的schema 定义、标签 schema 的定义、子表的名称、子表的标签信息以及标签的索引等。由于元数据的查询操作远多于写入操作,因此 TDengine 采用 B+Tree 作为元数据的存储结构。B+Tree 以其高效的查询性能和稳定的插入、删除操作,非常适合于处理这类读多
+写少的场景,确保了元数据管理的效率和稳定性。元数据的写入过程如下图所示:
+
+
+
+当 META 模块接收到元数据写入请求时,它会生成多个 Key-Value 数据对,并将这些数据对存储在底层的 TDB 存储引擎中。TDB 是 TDengine 根据自身需求研发的 B+Tree存储引擎,它由 3 个主要部分组成——内置 Cache、TDB 存储主文件和 TDB 的日志文件。数据在写入 TDB 时,首先被写入内置 Cache,如果 Cache 内存不足,系统会向 vnode的内存池请求额外的内存分配。如果写入操作涉及已有数据页的更改,系统会在修改数据页之前,先将未更改的数据页写入 TDB 的日志文件,作为备份。这样做可以在断电或其他故障发生时,通过日志文件回滚到原始数据,确保数据更新的原子性和数据完整性。
+
+由于 vnode 存储了各种元数据信息,并且元数据的查询需求多样化,vnode 内部会创建多个 B+Tree,用于存储不同维度的索引信息。这些 B+Tree 都存储在一个共享的存储文件中,并通过一个根页编号为 1 的索引 B+Tree 来索引各个 B+Tree 的根页编号,如下图所示:
+
+
+
+B+ Tree 的页结构如下图所示:
+
+
+
+在 TDB 中,Key 和 Value 都具有变长的特性。为了处理超长 Key 或 Value 的情况,当它们超过文件页的大小时,TDB 采用了溢出页的设计来容纳超出部分的数据。此外,为了有效控制 B+Tree 的高度,TDB 限制了非溢出页中 Key 和 Value 的最大长度,确保B+Tree 的扇出度至少为 4。
+
+### 时序数据的存储
+
+时序数据在 vnode 中是通过 TSDB 引擎进行存储的。鉴于时序数据的海量特性及其持续的写入流量,若使用传统的 B+Tree 结构来存储,随着数据量的增长,树的高度会迅速增加,这将导致查询和写入性能的急剧下降,最终可能使引擎变得不可用。鉴于此,TDengine 选择了 LSM 存储结构来处理时序数据。LSM 通过日志结构的存储方式,优化了数据的写入性能,并通过后台合并操作来减少存储空间的占用和提高查询效率,从而确保了时序数据的存储和访问性能。TSDB 引擎的写入流程如下图所示:
+
+
+
+在 MemTable 中,数据采用了 Red-Black Tree(红黑树)和 SkipList 相结合的索引方式。不同表的数据索引存储在 Red-Black Tree 中,而同一张表的数据索引则存储在SkipList 中。这种设计方式充分利用了时序数据的特点,提高了数据的存储和访问效率。
+
+Red-Black Tree 是一种自平衡的二叉树,它通过对节点进行着色和旋转操作来保持树的平衡,从而确保了查询、插入和删除操作的时间复杂度为 O(log n)。在 MemTable 中,Red-Black Tree 用于存储不同表
+
+SkipList 是一种基于有序链表的数据结构,它通过在链表的基础上添加多级索引来实现快速查找。SkipList 的查询、插入和删除操作的时间复杂度为 O(log n),与 Red-Black Tree 相当。在 MemTable 中,SkipList 用于存储同一张表的数据索引,这样可以快速定位到特定时间范围内的数据,为时序数据的查询和写入提供高效支持。
+
+通过将 Red-Black Tree 和 SkipList 相结合,TDengine 在 MemTable 中实现了一种高效的数据索引方式,既能够快速定位到不同表的数据,又能够快速定位到同一张表中特定时间范围内的数据。SkipList 索引如下图所示:
+
+
+
+在 TSDB 引擎中,无论是在内存中还是数据文件中,数据都按照(ts, version)元组进行排序。为了更好地管理和组织这些按时间排序的数据,TSDB 引擎将数据文件按照时间范围切分为多个数据文件组。每个数据文件组覆盖一定时间范围的数据,这样可以确保数据的连续性和完整性,同时也便于对数据进行分片和分区操作。通过将数据按时间范围划分为多个文件组,TSDB 引擎可以更有效地管理和访问存储在硬盘上的数据。文件组如下图所示:
+
+
+
+在查询数据时,根据查询数据的时间范围,可以快速计算文件组编号,从而快速定位所要查询的数据文件组。这种设计方式可以显著提高查询性能,因为它可以减少不必要的文件扫描和数据加载,直接定位到包含所需数据的文件组。接下来分别介绍数据文件组包含的文件:
+
+#### head 文件
+head 文件是时序数据存储文件(data 文件)的 BRIN(Block Range Index,块范围索引)文件,其中存储了每个数据块的时间范围、偏移量(offset)和长度等信息。
+
+查询引擎根据 head 文件中的信息,可以高效地过滤要查询的数据块所包含的时间范围,并获取这些数据块的位置信息。
+
+head 文件中存储了多个 BRIN 记录块及其索引。BRIN 记录块采用列存压缩的方式,这种方式可以大大减少空间占用,同时保持较高的查询性能。BRIN 索引结构如下图所示:
+
+
+
+#### data 文件
+
+data 文件是实际存储时序数据的文件。在 data 文件中,时序数据以数据块的形式进行存储,每个数据块包含了一定量数据的列式存储。根据数据类型和压缩配置,数据块采用了不同的压缩算法进行压缩,以减少存储空间的占用并提高数据传输的效率。
+
+与 stt 文件不同,每个数据块在 data 文件中独立存储,代表了一张表在特定时间范围内的数据。这种设计方式使得数据的管理和查询更加灵活和高效。通过将数据按块存储,并结合列式存储和压缩技术,TSDB 引擎可以更有效地处理和访问时序数据,从而满足大数据量和高速查询的需求。
+
+#### sma 文件
+
+预计算文件,用于存储各个数据块中每列数据的预计算结果。这些预计算结果包括每列数据的总和(sum)、最小值(min)、最大值(max)等统计信息。通过预先计算并存储这些信息,查询引擎可以在执行某些查询时直接利用这些预计算结果,从而避免了读取原始数据的需要。
+
+#### tomb 文件
+
+用于存储删除记录的文件。存储记录为(suid, uid, start_timestamp, end_timestamp, version)元组。
+
+#### stt 文件
+
+在少表高频的场景下,系统仅维护一个 stt 文件。该文件专门用于存储每次数据落盘后剩余的碎片数据。这样,在下一次数据落盘时,这些碎片数据可以与内存中的新数据合并,形成较大的数据块,随后一并写入 data 文件中。这种机制有效地避免了数据文件的碎片化,确保了数据存储的连续性和高效性。
+
+对于多表低频的场景,建议配置多个 stt 文件。这种场景下的核心思想是,尽管单张表每次落盘的数据量可能不大,但同一超级表下的所有子表累积的数据量却相当可观。通过合并这些数据,可以生成较大的数据块,从而减少数据块的碎片化。这不仅提升了数据的写入效率,还能显著提高查询性能,因为连续的数据存储更有利于快速的数据检索和访问。
\ No newline at end of file
diff --git a/docs/zh/10-tdinternal/05-query.md b/docs/zh/10-tdinternal/05-query.md
new file mode 100644
index 0000000000..9b5f9e042a
--- /dev/null
+++ b/docs/zh/10-tdinternal/05-query.md
@@ -0,0 +1,132 @@
+---
+sidebar_label: 查询引擎
+title: 查询引擎
+toc_max_heading_level: 4
+---
+
+TDengine 作为一个高性能的时序大数据平台,其查询与计算功能是核心组件之一。该平台提供了丰富的查询处理功能,不仅包括常规的聚合查询,还涵盖了时序数据的窗口查询、统计聚合等高级功能。这些查询计算任务需要 taosc、vnode、qnode 和 mnode 之间的紧密协作。在一个复杂的超级表聚合查询场景中,可能需要多个 vnode 和 qnode 共同承担查询和计算的职责。关于 vnode、qnode、mnode 的定义和介绍,请参考[系统架构](../系统架构)
+
+## 各模块在查询计算中的职责
+
+### taosc
+
+taosc 负责解析和执行 SQL。对于 insert 类型的 SQL,taosc 采用流式读取解析策略,以提高处理效率。而对于其他类型的 SQL,taosc 首先使用语法解析器将其分解为抽象语法树(Abstract Syntax Tree,AST),在解析过程中对 SQL 进行初步的语法校验。如果发现语法错误,taosc 会直接返回错误信息,并附上错误的具体位置,以帮助用户快速定位和修复问题。
+
+解析完成的 AST 被进一步转换为逻辑查询计划,逻辑查询计划经过优化后进一步转换为物理查询计划。接着,taosc 的调度器将物理查询计划转换为查询执行的任务,并将任务发送到选定的 vnode 或 qnode 执行。在得到查询结果准备好的通知后,taosc 将查询结果从相应的 vnode 或 qnode 取回,最终返回给用户。
+
+taosc 的执行过程可以简要总结为:解析 SQL 为 AST,生成逻辑查询计划并优化后转为物理查询计划,调度查询任务到 vnode 或 qnode 执行,获取查询结果。
+
+### mnode
+
+在 TDengine 集群中,超级表的信息和元数据库的基础信息都得到妥善管理。mnode作 为元数据服务器,负责响应 taosc 的元数据查询请求。当 taosc 需要获取 vgroup 等元数据信息时,它会向 mnode 发送请求。mnode 在收到请求后,会迅速返回所需的信息,确保 taosc 能够顺利执行其操作。
+
+此外,mnode 还负责接收 taosc 发送的心跳信息。这些心跳信息有助于维持 aosc 与 mnode 之间的连接状态,确保两者之间的通信畅通无阻。
+
+### vnode
+
+在 TDengine 集群中,vnode 作为虚拟节点,扮演着关键的角色。它通过任务队列的方式接收来自物理节点分发的查询请求,并执行相应的查询处理过程。每个 vnode 都拥
+有独立的任务队列,用于管理和调度查询请求。
+
+当 vnode 收到查询请求时,它会从任务队列中取出请求,并进行处理。处理完成后,vnode 会将查询结果返回给下级物理节点中处于阻塞状态的查询队列工作线程,或者是直接返回给 taosc。
+
+### 执行器
+
+执行器模块负责实现各种查询算子,这些算子通过调用 TSDB 的数据读取 API 来读取数据内容。数据内容以数据块的形式返回给执行器模块。TSDB 是一个时序数据库,负责从内存或硬盘中读取所需的信息,包括数据块、数据块元数据、数据块统计数据等多种类型的信息。
+
+TSDB 屏蔽了下层存储层(硬盘和内存缓冲区)的实现细节和机制,使得执行器模块可以专注于面向列模式的数据块进行查询处理。这种设计使得执行器模块能够高效地处理各种查询请求,同时简化数据访问和管理的复杂性。
+
+### UDF Daemon
+
+在分布式数据库系统中,执行 UDF 的计算节点负责处理涉及 UDF 的查询请求。当查询中使用了 UDF 时,查询模块会负责调度 UDF Daemon 完成对 UDF 的计算,并获取
+计算结果。
+
+UDF Daemon 是一个独立的计算组件,负责执行用户自定义的函数。它可以处理各种类型的数据,包括时序数据、表格数据等。通过将 UDF 的计算任务分发给 UDF Daemon,查询模块能够将计算负载从主查询处理流程中分离出来,提高系统的整体性能和可扩展性。
+
+在执行 UDF 的过程中,查询模块会与 UDF Daemon 紧密协作,确保计算任务的正确执行和结果的及时返回。
+
+## 查询策略
+
+为了更好地满足用户的需求,TDengine 集群提供了查询策略配置项 queryPolicy,以便用户根据自己的需求选择查询执行框架。这个配置项位于 taosc 的配置文件,每个配置项仅对单个 taosc 有效,可以在一个集群的不同 taosc 中混合使用不同的策略。
+
+queryPolicy 的值及其含义如下。
+- 1:表示所有查询只使用 vnode(默认值)。
+- 2:表示混合使用 vnode/qnode(混合模式)。
+- 3:表示查询中除了扫表功能使用 vnode 以外,其他查询计算功能只使用 qnode。
+- 4:表示使用客户端聚合模式。
+
+通过选择合适的查询策略,用户可以灵活地分配控制查询资源在不同节点的占用情况,从而实现存算分离、追求极致性能等目的。
+
+## SQL 说明
+
+TDengine 通过采用 SQL 作为查询语言,显著降低了用户的学习成本。在遵循标准SQL 的基础上,结合时序数据库的特点进行了一系列扩展,以更好地支持时序数据库的特色查询需求。
+- 分组功能扩展:TDengine 对标准 SQL 的分组功能进行了扩展,引入了 partition by 子句。用户可以根据自定义维度对输入数据进行切分,并在每个分组内进行任意
+形式的查询运算,如常量、聚合、标量、表达式等。
+- 限制功能扩展:针对分组查询中存在输出个数限制的需求,TDengine 引入了 slimit 和 soffset 子句,用于限制分组个数。当 limit 与 partition by 子句共用时,其含义转换为分组内的输出限制,而非全局限制。
+- 标签查询支持:TDengine 扩展支持了标签查询。标签作为子表属性,可以在查询中作为子表的伪列使用。针对仅查询标签列而不关注时序数据的场景,TDengine 引入了标签关键字加速查询,避免了对时序数据的扫描。
+- 窗口查询支持:TDengine 支持多种窗口查询,包括时间窗口、状态窗口、会话窗口、事件窗口、计数窗口等。未来还将支持用户自定义的更灵活的窗口查询。
+- 关联查询扩展:除了传统的 Inner、Outer、Semi、Anti-Semi Join 以外,TDengine 还支持时序数据库中特有的 ASOF Join 和 Window Join。这些扩展使得用户可以更加方便灵活地进行所需的关联查询。
+
+## 查询流程
+
+完整的查询流程如下。
+- 第 1 步,taosc 解析 SQL 并生成 AST。元数据管理模块(Catalog)根据需要向 vnode 或 mnode 请求查询中指定表的元数据信息。然后,根据元数据信息对其进行权限检查、语法校验和合法性校验。
+- 第 2 步,完成合法性校验之后生成逻辑查询计划。依次应用全部的优化策略,扫描执行计划,进行执行计划的改写和优化。根据元数据信息中的 vgroup 数量和 qnode 数量信息,基于逻辑查询计划生成相应的物理查询计划。
+- 第 3 步,客户端内的查询调度器开始进行任务调度处理。一个查询子任务会根据其数据亲缘关系或负载信息调度到某个 vnode 或 qnode 所属的 dnode 进行处理。
+- 第 4 步,dnode 接收到查询任务后,识别出该查询请求指向的 vnode 或 qnode,将消息转发到 vnode 或 qnode 的查询执行队列。
+- 第 5 步,vnode 或 qnode 的查询执行线程从查询队列获得任务信息,建立基础的查询执行环境,并立即执行该查询。在得到部分可获取的查询结果后,通知客户端调度器。
+- 第 6 步,客户端调度器依照执行计划依次完成所有任务的调度。在用户 API 的驱动下,向最上游算子所在的查询执行节点发送数据获取请求,读取数据请求结果。
+- 第 7 步,算子依据其父子关系依次从下游算子获取数据并返回。
+- 第 8 步,taosc 将所有获取的查询结果返回给上层应用程序。
+
+## 多表聚合查询流程
+
+TDengine 为了解决实际应用中对不同数据采集点数据进行高效聚合的问题,引入了超级表的概念。超级表是一种特殊的表结构,用于代表一类具有相同数据模式的数据采集点。超级表实际上是一个包含多张表的表集合,每张表都具有相同的字段定义,但每张表都带有独特的静态标签。这些标签可以有多个,并且可以随时增加、删除和修改。
+
+通过超级表,应用程序可以通过指定标签的过滤条件,轻松地对一个超级表下的全部或部分表进行聚合或统计操作。这种设计大大简化了应用程序的开发过程,提高了数据处理的效率和灵活性。TDengine 的多表聚合查询流程如下图所示:
+
+
+
+具体步骤说明如下。
+第 1 步,taosc 从 mnode 获取库和表的元数据信息。
+第 2 步,mnode 返回请求的元数据信息。
+第 3 步,taosc 向超级表所属的每个 vnode 发送查询请求。
+第 4 步,vnode 启动本地查询,在获得查询结果后返回查询响应。
+第 5 步,taosc 向聚合节点(在本例中为 qnode)发送查询请求。
+第 6 步,qnode 向每个 vnode 节点发送数据请求消息来拉取数据。
+第 7 步,vnode 返回本节点的查询计算结果。
+第 8 步,qnode 完成多节点数据聚合后将最终查询结果返回给客户端。
+
+TDengine 为了提升聚合计算速度,在 vnode 内实现了标签数据与时序数据的分离存储。首先,系统会在内存中过滤标签数据,以确定需要参与聚合操作的表的集合。这样做可以显著减少需要扫描的数据集,从而大幅提高聚合计算的速度。
+
+此外,得益于数据分布在多个 vnode 中,聚合计算操作可以在多个 vnode 中并发进行。这种分布式处理方式进一步提高了聚合的速度,使得 TDengine 能够更高效地处理大规模时序数据。
+
+值得注意的是,对普通表的聚合查询以及绝大部分操作同样适用于超级表,且语法完全一致。具体请查询参考手册。
+
+## 查询缓存
+
+为了提升查询和计算的效率,缓存技术在其中扮演着至关重要的角色。TDengine 在查询和计算的整个过程中充分利用了缓存技术,以优化系统性能。
+
+在 TDengine 中,缓存被广泛应用于各个阶段,包括数据存储、查询优化、执行计划生成以及数据检索等。通过缓存热点数据和计算结果,TDengine 能够显著减少对底层存储系统的访问次数,降低计算开销,从而提高整体查询和计算效率。
+
+此外,TDengine 的缓存机制还具备智能化的特点,能够根据数据访问模式和系统负载情况动态调整缓存策略。这使得 TDengine 在面对复杂多变的查询需求时,仍能保持良好的性能表现。
+
+### 缓存的数据类型
+
+缓存的数据类型分为如下 4 种。
+- 元数据(database、table meta、stable vgroup)。
+- 连接数据(rpc session、http session)。
+- 时序数据(buffer pool、multilevel storage)。
+- 最新数据(last、last_row)。
+
+### 缓存方案
+
+TDengine 针对不同类型的缓存对象采用了相应的缓存管理策略。对于元数据、RPC 对象和查询对象,TDengine 采用了哈希缓存的方式进行管理。这种缓存管理方式通过一个列表来管理,列表中的每个元素都是一个缓存结构,包含了缓存信息、哈希表、垃圾回收链表、统计信息、锁和刷新频率等关键信息。
+
+为了确保缓存的有效性和系统性能,TDengine 还通过刷新线程定时检测缓存列表中的过期数据,并将过期数据删除。这种定期清理机制有助于避免缓存中存储过多无用数据,降低系统资源消耗,同时保持缓存数据的实时性和准确性。缓存方案下图所示:
+
+
+
+- 元数据缓存(meta data):包括数据库、超级表、用户、节点、视图、虚拟节点等信息,以及表的 schema 和其所在虚拟节点的映射关系。通过在 taosc 缓存元数据可以避免频繁地向 mnode/vnode 请求元数据。taosc 对元数据的缓存采用固定大小的缓存空间,先到先得,直到缓存空间用完。当缓存空间用完时,缓存会被进行部分淘汰处理,用来缓存新进请求所需要的元数据。
+- 时序数据缓存(time series data):时序数据首先被缓存在 vnode 的内存中,以SkipList 形式组织,当达到落盘条件后,将时序数据进行压缩,写入数据存储文件
+中,并从缓存中清除。
+- 最新数据缓存(last/last_row):对时序数据中的最新数据进行缓存,可以提高最新数据的查询效率。最新数据以子表为单元组织成 KV 形式,其中,K 是子表 ID,V 是该子表中每列的最后一个非 NULL 以及最新的一行数据。
\ No newline at end of file
diff --git a/docs/zh/10-tdinternal/07-topic.md b/docs/zh/10-tdinternal/07-topic.md
new file mode 100644
index 0000000000..3fe12c943d
--- /dev/null
+++ b/docs/zh/10-tdinternal/07-topic.md
@@ -0,0 +1,104 @@
+---
+sidebar_label: 数据订阅
+title: 数据订阅
+toc_max_heading_level: 4
+---
+
+数据订阅作为 TDengine 的一个核心功能,为用户提供了灵活获取所需数据的能力。通过深入了解其内部原理,用户可以更加有效地利用这一功能,满足各种实时数据处理和监控需求。
+
+## 基本概念
+
+### 主题
+
+与 Kafka 一样,使用 TDengine 数据订阅需要定义主题。TDengine 的主题可以是数据库、超级表,或者一个查询语句。数据库订阅和超级表订阅主要用于数据迁移,可以把整个库或超级表在另一个集群还原出来。查询语句订阅是 TDengine 数据订阅的一大亮点,它提供了更大的灵活性,因为数据过滤与预处理是由 TDengine 而不是应用程序完成的,所以这种方式可以有效地减少传输数据量与应用程序的复杂度。
+
+如下图所示,每个主题涉及的数据表分布在多个 vnode(相当于 Kafka 的 partition)上,每个 vnode 的数据保存在 WAL 文件中,WAL 文件中的数据是顺序写入的。由于 WAL 文件中存储的不只有数据,还有元数据、写入消息等,因此数据的版本号不是连续的。
+
+
+
+TDengine 会为 WAL 文件自动创建索引以支持快速随机访问。通过灵活可配置的文件切换与保留机制,用户可以按需指定 WAL 文件保留的时间以及大小。通过以上方式,WAL 被改造成一个保留事件到达顺序的、可持久化的存储引擎。
+
+对于查询语句订阅,在消费时,TDengine 根据当前消费进度从 WAL 文件直接读取数据,并使用统一的查询引擎实现过滤、变换等操作,然后将数据推送给消费者。
+
+### 生产者
+
+生产者是与订阅主题相关联的数据表的数据写入应用程序。生产者可以通过多种方式产生数据,并将数据写入数据表所在的 vnode 的 WAL 文件中。这些方式包括 SQL、Stmt、Schemaless、CSV、流计算等。
+
+### 消费者
+
+消费者负责从主题中获取数据。在订阅主题之后,消费者可以消费分配给该消费者的 vnode 中的所有数据。为了实现高效、有序的数据获取,消费者采用了推拉(push 和poll)相结合的方式。
+
+当 vnode 中存在大量未被消费的数据时,消费者会按照顺序向 vnode 发送推送请求,以便一次性拉取大量数据。同时,消费者会在本地记录每个 vnode 的消费位置,确保所有数据都能被顺序地推送。
+
+当 vnode 中没有待消费的数据时,消费者将处于等待状态。一旦 vnode 中有新数据写入,系统会立即通过推送方式将数据推送给消费者,确保数据的实时性。
+
+### 消费组
+
+在创建消费者时,需要为其指定一个消费组。同一消费组内的消费者将共享消费进度,确保数据在消费者之间均匀分配。正如前面所述,一个主题的数据会被分布在多个vnode 中。为了提高消费速度和实现多线程、分布式地消费数据,可以在同一消费组中添加多个消费者。这些消费者首先会均分 vnode,然后分别对分配给自己的 vnode 进行消费。例如,假设数据分布在 4 个 vnode 上:
+- 当有 2 个消费者时,每个消费者将消费 2 个 vnode;
+- 当有 3 个消费者时,其中 2 个消费者各消费 1 个 vnode,而剩下的 1 个消费者将消费剩余的 2 个 vnode;
+- 当有 5 个消费者时,其中 4 个消费者各分配 1 个 vnode,而剩下的 1 个消费者则不参与消费。
+
+
+
+在一个消费组中新增一个消费者后,系统会通过再平衡(rebalance)机制自动完成消费者的重新分配。这一过程对用户来说是透明的,无须手动干预。再平衡机制能够确保数据在消费者之间重新分配,从而实现负载均衡。
+
+此外,一个消费者可以订阅多个主题,以满足不同场景下的数据处理需求。TDengine 的数据订阅功能在面临宕机、重启等复杂环境时,依然能够保证至少一次消费,确保数据的完整性和可靠性。
+
+### 消费进度
+
+消费组在 vnode 中记录消费进度,以便在消费者重启或故障恢复时能够准确地恢复消费位置。消费者在消费数据的同时,可以提交消费进度,即 vnode 上 WAL 的版本号(对应于 Kafka 中的 offset)。消费进度的提交既可以通过手动方式进行,也可以通过参数设置实现周期性自动提交。
+
+当消费者首次消费数据时,可以通过订阅参数来确定消费位置,也就是消费最新的数据还是最旧的数据。对于同一个主题及其任意一个消费组,每个 vnode 的消费进度都是唯一的。因此,当某个 vnode 的消费者提交消费进度并退出后,该消费组中的其他消费者将继续消费这个 vnode,并从之前消费者提交的进度开始继续消费。若之前的消费者未提交消费进度,新消费者将根据订阅参数设置值来确定起始消费位置。
+
+值得注意的是,不同消费组中的消费者即使消费同一个主题,它们之间也不会共享消费进度。这种设计确保了各个消费组之间的独立性,使得它们可以独立地处理数据,而不会相互干扰。下图清晰地展示了这一过程。
+
+
+
+## 数据订阅架构
+
+数据订阅系统在逻辑上可划分为客户端和服务器两大核心模块。客户端承担消费者的创建任务,获取专属于这些消费者的 vnode 列表,并从服务器检索所需数据,同时维护必要的状态信息。而服务器则专注于管理主题和消费者的相关信息,处理来自客户端的订阅请求。它通过实施再平衡机制来动态分配消费节点,确保消费过程的连续性和数据的一致性,同时跟踪和管理消费进度。数据订阅架构如下图所示:
+
+
+
+在客户端成功建立与服务器的连接之后,用户须首先指定消费组和主题,以创建相应的消费者实例。随后,客户端便会向服务器提交订阅请求。此刻,消费者的状态被标记为 modify,表示正处于配置阶段。消费者随后会定期向服务器发送请求,以检索并获取待消费的 vnode 列表,直至服务器为其分配相应的 vnode。一旦分配完成,消费者的状态便更新为 ready,标志着订阅流程的成功完成。此刻,客户端便可正式启动向 vnode 发送消费数据请求的过程。
+
+在消费数据的过程中,消费者会不断地向每个分配到的 vnode 发送请求,以尝试获取新的数据。一旦收到数据,消费者在完成消费后会继续向该 vnode 发送请求,以便持续消费。若在预设时间内未收到任何数据,消费者便会在 vnode 上注册一个消费 handle。这样一来,一旦 vnode 上有新数据产生,便会立即推送给消费者,从而确保数据消费的即时性,并有效减少消费者频繁主动拉取数据所导致的性能损耗。因此,可以看出,消费者从 vnode 获取数据的方式是一种拉取(pull)与推送(push)相结合的高效模式。
+
+消费者在收到数据时,会同时收到数据的版本号,并将其记录为当前在每个 vnode上的消费进度。这一进度仅在消费者内部以内存形式存储,确保仅对该消费者有效。这种设计保证了消费者在每次启动时能够从上次的消费中断处继续,避免了数据的重复处理。然而,若消费者需要退出并希望在之后恢复上次的消费进度,就必须在退出前将消费进度提交至服务器,执行所谓的 commit 操作。这一操作会将消费进度在服务器进行持久化存储,支持自动提交或手动提交两种方式。
+
+此外,为了维持消费者的活跃状态,客户端还实施了心跳保活机制。通过定期向服务器发送心跳信号,消费者能够向服务器证明自己仍然在线。若服务器在一定时间内未收到消费者的心跳,便会将其标记为 lost 状态,即认为消费者已离线。服务器依赖心跳机制来监控所有消费者的状态,进而有效地管理整个消费者群体。
+
+mnode 主要负责处理订阅过程中的控制消息,包括创建和删除主题、订阅消息、查询 endpoint 消息以及心跳消息等。vnode 则专注于处理消费消息和 commit 消息。当mnode 收到消费者的订阅消息时,如果该消费者尚未订阅过,其状态将被设置为 modify。如果消费者已经订阅过,但订阅的主题发生变更,消费者的状态同样会被设置为 modify。等待再平衡的计时器到来时,mnode 会对 modify 状态的消费者执行再平衡操作,将心跳超过固定时间的消费者设置为 lost 状态,并对关闭或 lost 状态超过一定时间的消费者进行删除操作。
+
+消费者会定期向 mnode 发送查询 endpoint 消息,以获取再平衡后的最新 vnode 分配结果。同时,消费者还会定期发送心跳消息,通知 mnode 自身处于活跃状态。此外,消费者的一些信息也会通过心跳消息上报至 mnode,用户可以查询 mnode 上的这些信息以监测各个消费者的状态。这种设计有助于实现对消费者的有效管理和监控。
+
+## 再平衡过程
+
+每个主题的数据可能分散在多个 vnode 上。服务器通过执行再平衡过程,将这些vnode 合理地分配给各个消费者,确保数据的均匀分布和高效消费。
+
+如下图所示,c1 表示消费者 1,c2 表示消费者 2,g1 表示消费组 1。起初 g1 中只有 c1 消费数据,c1 发送订阅信息到 mnode,mnode 把数据所在的所有 4 个vnode 分配给 c1。当 c2 增加到 g1 后,c2 将订阅信息发送给 mnode,mnode 将在下一次再平衡计时器到来时检测到这个 g1 需要重新分配,就会启动再平衡过程,随后 c2 分得其中两个 vnode 消费。分配信息还会通过 mnode 发送给 vnode,同时 c1 和 c2 也会获取自己消费的 vnode 信息并开始消费。
+
+
+
+再平衡计时器每 2s 检测一次是否需要再平衡。在再平衡过程中,如果消费者获取的状态是 not ready,则不能进行消费。只有再平衡正常结束后,消费者获取分配 vnode 的offset 后才可正常消费,否则消费者会重试指定次数后报错。
+
+## 消费者状态处理
+
+消费者的状态转换过程如下图所示。初始状态下,刚发起订阅的消费者处于modify 状态,此时客户端获取的消费者状态为 not ready,表明消费者尚未准备好进行数据消费。一旦 mnode 在再平衡计时器中检测到处于 modify 状态的消费者,便会启动再平衡过程。再平衡成功后,消费者的状态将转变为 ready,表示消费者已准备就绪。随后,当消费者通过定时的查询 endpoint 消息获取自身的 ready 状态以及分配的 vnode 列表后,便能正式开始消费数据。
+
+
+
+若消费者的心跳丢失时间超过 12s,经过再平衡过程,其状态将被更新为 lost,表明消费者被认为已离线。如果心跳丢失时间超过 1 天,消费者的状态将进一步转变为 clear,此时消费者将被系统删除。然而,如果在上述过程中消费者重新发送心跳信号,其状态将恢复为 modify,并重新进入下一轮的再平衡过程。
+
+当消费者主动退出时,会发送 unsubscribe 消息。该消息将清除消费者订阅的所有主题,并将消费者的状态设置为 modify。随后,在再平衡过程中,一旦消费者的状态变为ready 且无订阅的主题,mnode 将在再平衡的计时器中检测到此状态变化,并据此删除该消费者。这一系列措施确保了消费者退出的有序性和系统的稳定性。
+
+## 消费数据
+
+时序数据都存储在 vnode 上,消费的本质就是从 vnode 上的 WAL 文件中读取数据。WAL 文件相当于一个消息队列,消费者通过记录 WAL 数据的版本号,实际上就是记录消费的进度。WAL 文件中的数据包含 data 数据和 meta 数据(如建表、改表操作),订阅根据主题的类型和参数获取相应的数据。如果订阅涉及带有过滤条件的查询,订阅逻辑会通过通用的查询引擎过滤不符合条件的数据。
+
+如下图所示,vnode 可以通过设置参数自动提交消费进度,也可以在客户端确定处理数据后手动提交消费进度。如果消费进度被存储在 vnode 中,那么在相同消费组的不同消费者发生更换时,仍然会继续之前的进度消费。否则,根据配置参数,消费者可以选择消费最旧的数据或最新的数据。
+
+
+
+earliest 参数表示消费者从 WAL 文件中最旧的数据开始消费,而 latest 参数表示从WAL 文件中最新的数据(即新写入的数据)开始消费。这两个参数仅在消费者首次消费数据时或者没有提交消费进度时生效。如果在消费过程中提交了消费进度,例如在消费到 WAL 文件中的第 3 条数据时提交一次进度(即 commit offset=3),那么下次在相同的 vnode 上,相同的消费组和主题的新消费者将从第 4 条数据开始消费。这种设计确保了消费者能够根据需求灵活地选择消费数据的起始位置,同时保持了消费进度的持久化和消费者之间的同步。
\ No newline at end of file
diff --git a/docs/zh/10-tdinternal/09-stream.md b/docs/zh/10-tdinternal/09-stream.md
new file mode 100644
index 0000000000..41dad74cd4
--- /dev/null
+++ b/docs/zh/10-tdinternal/09-stream.md
@@ -0,0 +1,126 @@
+---
+sidebar_label: 流计算引擎
+title: 流计算引擎
+toc_max_heading_level: 4
+---
+
+## 流计算架构
+
+TDengine 流计算的架构如下图所示。当用户输入用于创建流的 SQL 后,首先,该 SQL 将在客户端进行解析,并生成流计算执行所需的逻辑执行计划及其相关属性信息。其次,客户端将这些信息发送至 mnode。mnode 利用来自数据源(超级)表所在数据库的 vgroups 信息,将逻辑执行计划动态转换为物理执行计划,并进一步生成流任务的有向无环图(Directed Acyclic Graph,DAG)。最后,mnode 启动分布式事务,将任务分发至每个 vgroup,从而启动整个流计算流程。
+
+
+
+mnode 包含与流计算相关的如下 4 个逻辑模块。
+- 任务调度,负责将逻辑执行计划转化为物理执行计划,并下发到每个 vnode。
+- meta store,负责存储流计算任务的元数据信息以及流任务相应的 DAG 信息。
+- 检查点调度,负责定期生成检查点(checkpoint)事务,并下发到各 source task(源
+任务)。
+- exec 监控,负责接收上报的心跳、更新 mnode 中各任务的执行状态,以及定期监控检查点执行状态和 DAG 变动信息。
+
+此外,mnode 还承担着向流计算任务下发控制命令的重要角色,这些命令包括但不限于暂停、恢复执行、删除流任务及更新流任务的上下游信息等。
+
+在每个 vnode 上,至少部署两个流任务:一个是 source task,它负责从 WAL(在必要时也会从 TSDB)中读取数据,以供后续任务处理,并将处理结果分发给下游任务;另一个是 sink task(写回任务),它的职责是将收到的数据写入所在的 vnode。为了确保数据流的稳定性和系统的可扩展性,每个 sink task 都配备了流量控制功能,以便根据实际情况调整数据写入速度。
+
+## 基本概念
+
+### 有状态的流计算
+
+流计算引擎具备强大的标量函数计算能力,它处理的数据在时间序列上相互独立,无须保留计算的中间状态。这意味着,对于所有输入数据,引擎可以执行固定的变换操
+作,如简单的数值加法,并直接输出结果。
+
+同时,流计算引擎也支持对数据进行聚合计算,这类计算需要在执行过程中维护中间状态。以统计设备的日运行时间为例,由于统计周期可能跨越多天,应用程序必须持续追踪并更新当前的运行状态,直至统计周期结束,才能得出准确的结果。这正是有状态的流计算的一个典型应用场景,它要求引擎在执行过程中保持对中间状态的跟踪和管理,以确保最终结果的准确性。
+
+### 预写日志
+
+当数据写入 TDengine 时,首先会被存储在 WAL 文件中。每个 vnode 都拥有自己的 WAL 文件,并按照时序数据到达的顺序进行保存。由于 WAL 文件保留了数据到达的顺序,因此它成为流计算的重要数据来源。此外,WAL 文件具有自己的数据保留策略,通过数据库的参数进行控制,超过保留时长的数据将会被从 WAL 文件中清除。这种设计确保了数据的完整性和系统的可靠性,同时为流计算提供了稳定的数据来源。
+
+### 事件驱动
+
+事件在系统中指的是状态的变化或转换。在流计算架构中,触发流计算流程的事件是(超级)表数据的写入消息。在这一阶段,数据可能尚未完全写入 TSDB,而是在多个副本之间进行协商并最终达成一致。
+
+流计算采用事件驱动的模式执行,其数据源并非直接来自 TSDB,而是 WAL。数据一旦写入 WAL 文件,就会被提取出来并加入待处理的队列中,等待流计算任务的进一步处理。这种数据写入后立即触发流计算引擎执行的方式,确保数据一旦到达就能得到及时处理,并能够在最短时间内将处理结果存储到目标表中。
+
+### 时间
+
+在流计算领域,时间是一个至关重要的概念。TDengine 的流计算中涉及 3 个关键的时间概念,分别是事件时间、写入时间和处理时间。
+- 事件时间(Event Time):这是时序数据中每条记录的主时间戳(也称为 Primary Timestamp),通常由生成数据的传感器或上报数据的网关提供,用以精确标记记录的生成时刻。事件时间是流计算结果更新和推送策略的决定性因素。
+- 写入时间(Ingestion Time):指的是记录被写入数据库的时刻。写入时间与事件时间通常是独立的,一般情况下,写入时间晚于或等于事件时间(除非出于特定目的,用户写入了未来时刻的数据)。
+- 处理时间(Processing Time):这是流计算引擎开始处理写入 WAL 文件中数据的时间点。对于那些设置了 max_delay 选项以控制流计算结果返回策略的场景,处理时间直接决定了结果返回的时间。值得注意的是,在 at_once 和 window_close 这两种计算触发模式下,数据一旦到达 WAL 文件,就会立即被写入 source task 的输入队列并开始计算。
+
+这些时间概念的区分确保了流计算能够准确地处理时间序列数据,并根据不同时间点的特性采取相应的处理策略
+
+### 时间窗口聚合
+
+TDengine 的流计算功能允许根据记录的事件时间将数据划分到不同的时间窗口中。通过应用指定的聚合函数,计算出每个时间窗口内的聚合结果。当窗口中有新的记录到达时,系统会触发对应窗口的聚合结果更新,并根据预先设定的推送策略,将更新后的结果传递给下游流计算任务。
+
+当聚合结果需要写入预设的超级表时,系统首先会根据分组规则生成相应的子表名称,然后将结果写入对应的子表中。值得一提的是,流计算中的时间窗口划分策略与批量查询中的窗口生成与划分策略保持一致,确保了数据处理的一致性和效率。
+
+### 乱序处理
+
+在网络传输和数据路由等复杂因素的影响下,写入数据库的数据可能无法维持事件时间的单调递增特性。这种现象,即在写入过程中出现的非单调递增数据,被称为乱序写入。
+
+乱序写入是否会影响相应时间窗口的流计算结果,取决于创建流计算任务时设置的 watermark(水位线)参数以及是否忽略 ignore expired(过期数据)参数的配置。这两个参数共同作用于确定是丢弃这些乱序数据,还是将其纳入并增量更新所属时间窗口的计算结果。通过这种方式,系统能够在保持流计算结果准确性的同时,灵活处理乱序数据,确保数据的完整性和一致性。
+
+## 流计算任务
+
+每个激活的流计算实例都是由分布在不同 vnode 上的多个流任务组成的。这些流任务在整体架构上呈现出相似性,均包含一个全内存驻留的输入队列和输出队列,用于执行时序数据的执行器系统,以及用于存储本地状态的存储系统,如下图所示。这种设计确保了流计算任务的高性能和低延迟,同时提供了良好的可扩展性和容错性。
+
+
+
+按照流任务承担任务的不同,可将其划分为 3 个类别—source task(源任务)、agg task(聚合任务)和 sink task(写回任务)。
+
+### source task
+
+流计算的数据处理始于本地 WAL 文件中的数据读取,这些数据随后在本地节点上进行局部计算。source task 遵循数据到达的自然顺序,依次扫描 WAL 文件,并从中筛选出符合特定要求的数据。随后,source task 对这些时序数据进行顺序处理。因此,流计算的数据源(超级)表无论分布在多少个 vnode 上,集群中都会相应地部署同等数量的源任务。这种分布式的处理方式确保了数据的并行处理和高效利用集群资源。
+
+### agg task
+
+source task 的下游任务是接收源任务聚合后的结果,并对这些结果进行进一步的汇总以生成最终输出。在集群中配置 snode 的情况下,agg task 会被优先安排在 snode 上执行,以利用其存储和处理能力。如果集群中没有 snode,mnode 则会随机选择一个vnode,在该 vnode 上调度执行 agg task。值得注意的是,agg task 并非在所有情况下都是必需的。对于那些不涉及窗口聚合的流计算场景(例如,仅包含标量运算的流计算,或者在数据库只有一个 vnode 时的聚合流计算),就不会出现 agg task。在这种情况下,流计算的拓扑结构将简化为仅包含两级流计算任务,即 source task 和直接输出结果的下游任务。
+
+### sink task
+
+sink task 承担着接收 agg task 或 source task 输出结果的重任,并将其妥善写入本地 vnode,以此完成数据的写回过程。与 source task 类似,每个结果(超级)表所分布的 vnode 都将配备一个专门的 sink task。用户可以通过配置参数来调节 sink task 的吞吐量,以满足不同的性能需求。
+
+上述 3 类任务在流计算架构中各司其职,分布在不同的层级。显然,source task 的数量直接取决于 vnode 的数量,每个 source task 独立负责处理各自 vnode 中的数据,与其他 source task 互不干扰,不存在顺序性的约束。然而,值得指出的是,如果最终的流计算结果汇聚到一张表中,那么在该表所在的 vnode 上只会部署一个 sink task。这 3 种类型的任务之间的协作关系如下图所示,共同构成了流计算任务的完整执行流程。
+
+
+
+## 流计算节点
+
+snode 是一个专为流计算服务的独立 taosd 进程,它专门用于部署 agg task。snode 不仅具备本地状态管理能力,还内置了远程备份数据的功能。这使得 snode 能够收集并存储分散在各个 vgroup 中的检查点数据,并在需要时,将这些数据远程下载到重新启动流计算的节点上,从而确保流计算状态的一致性和数据的完整性。
+
+## 状态与容错处理
+
+### 检查点
+
+在流计算过程中,系统采用分布式检查点机制来定期(默认为每 3min)保存计算过程中各个任务内部算子的状态。这些状态的快照即检查点(checkpoint)。生成检查点的操作仅与处理时间相关联,与事件时间无关。
+
+在假定所有流任务均正常运行的前提下,mnode 会定期发起生成检查点的事务,并将这些事务分发至每个流的最顶层任务。负责处理这些事务的消息随后会进入数据处理队列。
+
+TDengine 中的检查点生成方式与业界主流的流计算引擎保持一致,每次生成的检查点都包含完整的算子状态信息。对于每个任务,检查点数据仅在任务运行的节点上保留一份副本,与时序数据存储引擎的副本设置完全独立。值得注意的是,流任务的元数据信息也采用了多副本保存机制,并被纳入时序数据存储引擎的管理范畴。因此,在多副本集群上执行流计算任务时,其元数据信息也将实现多副本冗余。
+
+为确保检查点数据的可靠性,TDengine 流计算引擎提供了远程备份检查点数据的功能,支持将检查点数据异步上传至远程存储系统。这样一来,即便本地保留的检查点数据受损,也能从远程存储系统下载相应数据,并在全新的节点上重启流计算,继续执行计算任务。这一措施进一步增强了流计算系统的容错能力和数据安全性。
+
+### 状态存储后端
+
+流任务中算子的计算状态信息以文件的方式持久化存储在本地硬盘中。
+
+## 内存管理
+
+每个非 sink task 都配备有相应的输入队列和输出队列,而 sink task 则只有输入队列,不设输出队列。这两种队列的数据容量上限均设定为 60MB,它们根据实际需求动态占用存储空间,当队列为空时,不会占用任何存储空间。此外,agg task 在内部保存计算状态时也会消耗一定的内存空间。这一内存占用可以通过设置参数 streamBufferSize 进行调整,该参数用于控制内存中窗口状态缓存的大小,默认值为 128MB。而参数 maxStreamBackendCache 用于限制后端存储在内存中的最大占用存储空间,默认同样为 128MB,用户可以根据需要将其调整为 16MB 至 1024MB 之间的任意值。
+
+## 流量控制
+
+流计算引擎在 sink task 中实现了流量控制机制,以优化数据写入性能并防止资源过度消耗。该机制主要通过以下两个指标来控制流量。
+- 每秒写入操作调用次数:sink task 负责将处理结果写入其所属的 vnode。该指标的上限被固定为每秒 50 次,以确保写入操作的稳定性和系统资源的合理分配。
+- 每秒写入数据吞吐量:通过配置参数 streamSinkDataRate,用户可以控制每秒写入的数据量,该参数的可调范围是 0.1MB/s 至 5MB/s,默认值为 2MB/s。这意味着对于单个 vnode,每个 sink task 每秒最多可以写入 2MB 的数据。
+
+sink task 的流量控制机制不仅能够防止在多副本场景下因高频率写入导致的同步协商缓冲区溢出,还能避免写入队列中数据堆积过多而消耗大量内存空间。这样做可以有效减少输入队列的内存占用。得益于整体计算框架中应用的反压机制,sink task 能够将流量控制的效果直接反馈给最上层的任务,从而降低流计算任务对设备计算资源的占用,避免过度消耗资源,确保系统整体的稳定性和效率。
+
+## 反压机制
+
+TDengine 的流计算框架部署在多个计算节点上,为了协调这些节点上的任务执行进度并防止上游任务的数据持续涌入导致下游任务过载,系统在任务内部以及上下游任务之间均实施了反压机制。
+
+在任务内部,反压机制通过监控输出队列的满载情况来实现。一旦任务的输出队列达到存储上限,当前计算任务便会进入等待状态,暂停处理新数据,直至输出队列有足够空间容纳新的计算结果,然后恢复数据处理流程。
+
+而在上下游任务之间,反压机制则是通过消息传递来触发的。当下游任务的输入队列达到存储上限时(即流入下游的数据量持续超过下游任务的最大处理能力),上游任务将接收到下游任务发出的输入队列满载信号。此时,上游任务将适时暂停其计算处理,直到下游任务处理完毕并允许数据继续分发,上游任务才会重新开始计算。这种机制有效地平衡了任务间的数据流动,确保整个流计算系统的稳定性和高效性。
\ No newline at end of file
diff --git a/docs/zh/10-tdinternal/11-compress.md b/docs/zh/10-tdinternal/11-compress.md
new file mode 100644
index 0000000000..05ad2d60f6
--- /dev/null
+++ b/docs/zh/10-tdinternal/11-compress.md
@@ -0,0 +1,61 @@
+---
+sidebar_label: 数据压缩
+title: 数据压缩
+toc_max_heading_level: 4
+---
+
+## 概述
+
+数据压缩是一种在不损失数据有效信息的前提下,利用特定算法对数据进行重新组织和处理,以减少数据占用的存储空间和提高数据传输效率的技术。TDengine 在数据的存储和传输过程中均采用了这一技术,旨在优化存储资源的使用并加快数据交换的速度。
+
+
+## 存储压缩
+
+TDengine 在存储架构上采用了列式存储技术,这意味着在存储介质中,数据是以列为单位进行连续存储的。这与传统的行式存储不同,后者在存储介质中是以行为单位进行连续存储的。列式存储与时序数据的特性相结合,尤其适合处理平稳变化的时序数据。
+
+为了进一步提高存储效率,TDengine 采用了差值编码技术。这种技术通过计算相邻数据点之间的差异来存储数据,而不是直接存储原始值,从而大幅度减少存储所需的信息量。在差值编码之后,TDengine 还会使用通用的压缩技术对数据进行二次压缩,以实现更高的压缩率。
+
+对于设备采集的稳定时序数据,TDengine 的压缩效果尤为显著,压缩率通常可以达到 10% 以内,甚至在某些情况下更高。这种高效的压缩技术为用户节约了大量的存储成本,同时也提高了数据的存储和访问效率。
+
+### 一级压缩
+
+时序数据自设备采集后,遵循 TDengine 的数据建模规则,每台采集设备会被构建为一张子表。如此,一台设备产生的所有时序数据均记录在同一张子表中。在数据存储过程中,数据是以块为单位进行分块存储的,每个数据块仅包含一张子表的数据。压缩操作也是以块为单位进行的,对子表中的每一列数据分别进行压缩,压缩后的数据仍然按
+块存储至硬盘。
+
+时序数据的平稳性是其主要特征之一,例如采集的大气温度、水温等,通常在一定范围内波动。利用这一特性,可以对数据进行重编码,并且根据不同的数据类型采用
+应的编码技术,以实现最高的压缩效率。接下来将介绍各种数据类型的压缩方法。
+
+- 时间戳类型:由于时间戳列通常记录设备连续采集数据的时刻,且采集频率固定,因此只须记录相邻时间点的差值。由于差值通常较小,这种方法比直接存储原始
+时间戳更能节省存储空间。
+- 布尔类型:布尔类型通过一个比特位表示一个布尔值,一个字节可以存储 8 个布尔值。通过紧凑的编码方式,可以显著减少存储空间。
+- 数值类型:物联网设备产生的数值数据,如温度、湿度、气压、车速、油耗等,通常数值不大且在一定范围内波动。对于这类数据,统一采用 zigzag 编码技术。该技术将有符号整数映射为无符号整数,并将整数的补码最高位移动到低位,负数除了符号位以外的其他位取反,正数保持不变。这样做可以将有效数据位集中,同时增加前导零的数量,从而在后续压缩步骤中获得更佳的压缩效果。
+- 浮点数类型:对于 float 和 double 两种浮点数类型,采用 delta-delta 编码方法。
+- 字符串类型:字符串类型数据采用字典压缩算法,通过短的标识符替换原字符串中频繁出现的长字符串,从而减少存储的信息长度。
+
+### 二级压缩
+
+在完成针对特定数据类型的专用压缩之后,TDengine 进一步采用通用的压缩技术,将数据视为无差别的二进制数据进行二次压缩。与一级压缩相比,二级压缩的侧重点在于消除数据块之间的信息冗余。这种双重压缩技术,一方面专注于局部数据的精简,另一方面着眼于整体数据的重叠消除,二者相辅相成,共同实现了 TDengine 中的超高压缩率。
+
+TDengine 支持多种压缩算法,包括 LZ4、ZLIB、ZSTD、XZ 等,用户可以根据具体的应用场景和需求,在压缩率和写入速度之间进行灵活权衡,选择最适合的压缩方案。
+
+### 有损压缩
+
+TDengine 引擎为浮点数类型数据提供了无损压缩和有损压缩两种模式。浮点数的精度通常由其小数点后的位数决定。在某些情况下,设备采集的浮点数精度较高,但实际应用中关注的精度却较低,此时采用有损压缩可以有效地节约存储空间。TDengine 的有损压缩算法基于预测模型,其核心思想是利用前序数据点的趋势来预测后续数据点的走势。这种算法能够显著提高压缩率,相比之下,其压缩效果远超无损压缩。有损压缩算法的名称为 TSZ。
+
+## 传输压缩
+
+TDengine 在数据传输过程中提供了压缩功能,以减少网络带宽的消耗。使用原生连接从客户端(如 taosc)向服务器传输数据时,可以通过配置压缩传输来节省带宽。在配置文件 taos.cfg 中,可以设置 compressMsgSize 选项来实现这一目标。可配置的值有以下3 个。
+- 0:表示禁用压缩传输。
+- 1:表示启用压缩传输,但仅对大于 1KB 的数据包进行压缩。
+- 2:表示启用压缩传输,对所有数据包进行压缩。
+
+在使用 RESTful 和 WebSocket 连接与 taosAdapter 通信时,taosAdapter 支持行业标准的压缩协议,允许连接端根据行业标准协议开启或关闭传输过程中的压缩。以下是具体的实现方式:
+- RESTful 接口使用压缩:客户端在 HTTP 请求头部指定 Accept-Encoding 来告知服务器可接受的压缩类型,如 gzip、deflate 等。服务器在返回结果时,会在 ContentEncoding 头部中指定所使用的压缩算法,并返回压缩过的数据。
+- WebSocket 接口使用压缩:可以参考 WebSocket 协议标准文档 RFC7692,了解如何在 WebSocket 连接中实现压缩。
+- 数据备份迁移工具 taosX 与 taosX Agent 之间的通信也可以开启压缩传输。在agent.toml 配置文件中,设置压缩开关选项 compression=true 即可启用压缩功能。
+
+## 压缩流程
+
+下图展示了 TDengine 引擎在时序数据的整个传输及存储过程中的压缩及解压过程,以更好地理解整个处理过程。
+
+
\ No newline at end of file
diff --git a/docs/zh/21-tdinternal/_category_.yml b/docs/zh/10-tdinternal/_category_.yml
similarity index 100%
rename from docs/zh/21-tdinternal/_category_.yml
rename to docs/zh/10-tdinternal/_category_.yml
diff --git a/docs/zh/10-tdinternal/aggquery.png b/docs/zh/10-tdinternal/aggquery.png
new file mode 100644
index 0000000000..8e2094eb8c
Binary files /dev/null and b/docs/zh/10-tdinternal/aggquery.png differ
diff --git a/docs/zh/10-tdinternal/brin.png b/docs/zh/10-tdinternal/brin.png
new file mode 100644
index 0000000000..49a91944c8
Binary files /dev/null and b/docs/zh/10-tdinternal/brin.png differ
diff --git a/docs/zh/10-tdinternal/btree.png b/docs/zh/10-tdinternal/btree.png
new file mode 100644
index 0000000000..d310929b31
Binary files /dev/null and b/docs/zh/10-tdinternal/btree.png differ
diff --git a/docs/zh/10-tdinternal/btreepage.png b/docs/zh/10-tdinternal/btreepage.png
new file mode 100644
index 0000000000..7c82e017e9
Binary files /dev/null and b/docs/zh/10-tdinternal/btreepage.png differ
diff --git a/docs/zh/10-tdinternal/cache.png b/docs/zh/10-tdinternal/cache.png
new file mode 100644
index 0000000000..a5ff851a78
Binary files /dev/null and b/docs/zh/10-tdinternal/cache.png differ
diff --git a/docs/zh/10-tdinternal/column.png b/docs/zh/10-tdinternal/column.png
new file mode 100644
index 0000000000..cd7b42fae3
Binary files /dev/null and b/docs/zh/10-tdinternal/column.png differ
diff --git a/docs/zh/10-tdinternal/compression.png b/docs/zh/10-tdinternal/compression.png
new file mode 100644
index 0000000000..80f027ffd2
Binary files /dev/null and b/docs/zh/10-tdinternal/compression.png differ
diff --git a/docs/zh/10-tdinternal/consumer.png b/docs/zh/10-tdinternal/consumer.png
new file mode 100644
index 0000000000..cc996a431a
Binary files /dev/null and b/docs/zh/10-tdinternal/consumer.png differ
diff --git a/docs/zh/10-tdinternal/consuming.png b/docs/zh/10-tdinternal/consuming.png
new file mode 100644
index 0000000000..6cd1670b64
Binary files /dev/null and b/docs/zh/10-tdinternal/consuming.png differ
diff --git a/docs/zh/21-tdinternal/dnode.webp b/docs/zh/10-tdinternal/dnode.webp
similarity index 100%
rename from docs/zh/21-tdinternal/dnode.webp
rename to docs/zh/10-tdinternal/dnode.webp
diff --git a/docs/zh/10-tdinternal/fileset.png b/docs/zh/10-tdinternal/fileset.png
new file mode 100644
index 0000000000..c6b90adc63
Binary files /dev/null and b/docs/zh/10-tdinternal/fileset.png differ
diff --git a/docs/zh/21-tdinternal/index.md b/docs/zh/10-tdinternal/index.md
similarity index 100%
rename from docs/zh/21-tdinternal/index.md
rename to docs/zh/10-tdinternal/index.md
diff --git a/docs/zh/10-tdinternal/key-value.png b/docs/zh/10-tdinternal/key-value.png
new file mode 100644
index 0000000000..c057b50881
Binary files /dev/null and b/docs/zh/10-tdinternal/key-value.png differ
diff --git a/docs/zh/21-tdinternal/message.webp b/docs/zh/10-tdinternal/message.webp
similarity index 100%
rename from docs/zh/21-tdinternal/message.webp
rename to docs/zh/10-tdinternal/message.webp
diff --git a/docs/zh/10-tdinternal/meta.png b/docs/zh/10-tdinternal/meta.png
new file mode 100644
index 0000000000..609057bd4f
Binary files /dev/null and b/docs/zh/10-tdinternal/meta.png differ
diff --git a/docs/zh/21-tdinternal/modules.webp b/docs/zh/10-tdinternal/modules.webp
similarity index 100%
rename from docs/zh/21-tdinternal/modules.webp
rename to docs/zh/10-tdinternal/modules.webp
diff --git a/docs/zh/21-tdinternal/multi_tables.webp b/docs/zh/10-tdinternal/multi_tables.webp
similarity index 100%
rename from docs/zh/21-tdinternal/multi_tables.webp
rename to docs/zh/10-tdinternal/multi_tables.webp
diff --git a/docs/zh/10-tdinternal/offset.png b/docs/zh/10-tdinternal/offset.png
new file mode 100644
index 0000000000..d8146b8d50
Binary files /dev/null and b/docs/zh/10-tdinternal/offset.png differ
diff --git a/docs/zh/10-tdinternal/rebalance.png b/docs/zh/10-tdinternal/rebalance.png
new file mode 100644
index 0000000000..216ba5ec3d
Binary files /dev/null and b/docs/zh/10-tdinternal/rebalance.png differ
diff --git a/docs/zh/21-tdinternal/replica-forward.webp b/docs/zh/10-tdinternal/replica-forward.webp
similarity index 100%
rename from docs/zh/21-tdinternal/replica-forward.webp
rename to docs/zh/10-tdinternal/replica-forward.webp
diff --git a/docs/zh/21-tdinternal/replica-master.webp b/docs/zh/10-tdinternal/replica-master.webp
similarity index 100%
rename from docs/zh/21-tdinternal/replica-master.webp
rename to docs/zh/10-tdinternal/replica-master.webp
diff --git a/docs/zh/21-tdinternal/replica-restore.webp b/docs/zh/10-tdinternal/replica-restore.webp
similarity index 100%
rename from docs/zh/21-tdinternal/replica-restore.webp
rename to docs/zh/10-tdinternal/replica-restore.webp
diff --git a/docs/zh/10-tdinternal/skiplist.png b/docs/zh/10-tdinternal/skiplist.png
new file mode 100644
index 0000000000..9660d52320
Binary files /dev/null and b/docs/zh/10-tdinternal/skiplist.png differ
diff --git a/docs/zh/10-tdinternal/statetransition.png b/docs/zh/10-tdinternal/statetransition.png
new file mode 100644
index 0000000000..1ec8ae22f7
Binary files /dev/null and b/docs/zh/10-tdinternal/statetransition.png differ
diff --git a/docs/zh/10-tdinternal/streamarch.png b/docs/zh/10-tdinternal/streamarch.png
new file mode 100644
index 0000000000..92a2b61d39
Binary files /dev/null and b/docs/zh/10-tdinternal/streamarch.png differ
diff --git a/docs/zh/10-tdinternal/streamtask.png b/docs/zh/10-tdinternal/streamtask.png
new file mode 100644
index 0000000000..fc132c5c76
Binary files /dev/null and b/docs/zh/10-tdinternal/streamtask.png differ
diff --git a/docs/zh/21-tdinternal/structure.webp b/docs/zh/10-tdinternal/structure.webp
similarity index 100%
rename from docs/zh/21-tdinternal/structure.webp
rename to docs/zh/10-tdinternal/structure.webp
diff --git a/docs/zh/10-tdinternal/taskarch.png b/docs/zh/10-tdinternal/taskarch.png
new file mode 100644
index 0000000000..d9fae4908d
Binary files /dev/null and b/docs/zh/10-tdinternal/taskarch.png differ
diff --git a/docs/zh/10-tdinternal/topic.png b/docs/zh/10-tdinternal/topic.png
new file mode 100644
index 0000000000..82f3df6b73
Binary files /dev/null and b/docs/zh/10-tdinternal/topic.png differ
diff --git a/docs/zh/10-tdinternal/topicarch.png b/docs/zh/10-tdinternal/topicarch.png
new file mode 100644
index 0000000000..2442158ebb
Binary files /dev/null and b/docs/zh/10-tdinternal/topicarch.png differ
diff --git a/docs/zh/10-tdinternal/tsdb.png b/docs/zh/10-tdinternal/tsdb.png
new file mode 100644
index 0000000000..eda4080f8c
Binary files /dev/null and b/docs/zh/10-tdinternal/tsdb.png differ
diff --git a/docs/zh/10-tdinternal/tuple.png b/docs/zh/10-tdinternal/tuple.png
new file mode 100644
index 0000000000..666612df1d
Binary files /dev/null and b/docs/zh/10-tdinternal/tuple.png differ
diff --git a/docs/zh/10-tdinternal/vnode.png b/docs/zh/10-tdinternal/vnode.png
new file mode 100644
index 0000000000..61aa8bc208
Binary files /dev/null and b/docs/zh/10-tdinternal/vnode.png differ
diff --git a/docs/zh/21-tdinternal/vnode.webp b/docs/zh/10-tdinternal/vnode.webp
similarity index 100%
rename from docs/zh/21-tdinternal/vnode.webp
rename to docs/zh/10-tdinternal/vnode.webp
diff --git a/docs/zh/21-tdinternal/write_follower.webp b/docs/zh/10-tdinternal/write_follower.webp
similarity index 100%
rename from docs/zh/21-tdinternal/write_follower.webp
rename to docs/zh/10-tdinternal/write_follower.webp
diff --git a/docs/zh/21-tdinternal/write_leader.webp b/docs/zh/10-tdinternal/write_leader.webp
similarity index 100%
rename from docs/zh/21-tdinternal/write_leader.webp
rename to docs/zh/10-tdinternal/write_leader.webp
diff --git a/docs/zh/14-reference/01-components/01-taosd.md b/docs/zh/14-reference/01-components/01-taosd.md
new file mode 100644
index 0000000000..0e9c4eb926
--- /dev/null
+++ b/docs/zh/14-reference/01-components/01-taosd.md
@@ -0,0 +1,225 @@
+---
+title: "taosd 参考手册"
+sidebar_label: "taosd"
+toc_max_heading_level: 4
+---
+
+taosd 是 TDengine 数据库引擎的核心服务,其配置文件默认是 `/etc/taos/taos.cfg` 但也可以指定不同路径的配置文件。本节详细介绍 taosd 的命令行参数及配置文件中的配置参数。
+
+## 命令行参数
+
+taosd 命令行参数如下
+- -a ``:指定一个 JSON 文件,其中包含服务启动时的各项配置参数,其格式形如 `{"fqdn":"td1"}`,关于配置参数的细节请参考下一节
+- -c ``:指定配置文件所在目录
+- -s:打印 SDB 信息
+- -C: 打印配置信息
+- -e: 指定环境变量,其格式形如 `-e 'TAOS_FQDN=td1'`
+- -k: 获取机器码
+- -dm: 启用内存调度
+- -V: 打印版本信息
+
+## 配置参数
+
+:::note
+配置文件参数修改后,需要重启*taosd*服务,或客户端应用才能生效。
+
+:::
+
+### 连接相关
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|firstEp | taosd 启动时,主动连接的集群中首个 dnode 的 end point,缺省值:localhost:6030 |
+|secondEp | taosd 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,缺省值:无|
+|fqdn | 启动 taosd 后所监听的服务地址,缺省值:所在服务器上配置的第一个 hostname |
+|serverPort | 启动 taosd 后所监听的端口,缺省值:6030 |
+|maxShellConns | 一个 dnode 容许的连接数,取值范围为 10-5000000,缺省值:5000 |
+|numOfRpcSessions | 允许一个客户端能创建的最大连接数,取值范围 100-100000,缺省值:30000 |
+|timeToGetAvailableConn | 获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,缺省值:500000 |
+
+### 监控相关
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|monitor | 是否收集监控数据并上报,0: 关闭;1:打开;缺省值:0 |
+|monitorFqdn | taosKeeper 服务所在服务器的 FQDN,缺省值:无 |
+|monitorPort | taosKeeper 服务所监听的端口号,缺省值:6043 |
+|monitorInternal | 监控数据库记录系统参数(CPU/内存)的时间间隔,单位是秒,取值范围 1-200000 ,缺省值:30|
+|telemetryReporting | 是否上传 telemetry,0: 不上传,1:上传,缺省值:1 |
+|crashReporting | 是否上传 crash 信息;0: 不上传,1: 上传;缺省值: 1|
+
+### 查询相关
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|queryPolicy | 查询策略,1: 只使用 vnode,不使用 qnode; 2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行; 3: vnode 只运行扫描算子,其余算子均在 qnode 执行 ;缺省值:1 |
+|maxNumOfDistinctRes | 允许返回的 distinct 结果最大行数,默认值 10 万,最大允许值 1 亿 |
+|countAlwaysReturnValue | ount/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值,0: 返回空行,1: 返回;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了TSMA时, 且相应的组或窗口内数据为空或者NULL, 对应的组或窗口将不返回查询结果. 注意此参数客户端和服务端值应保持一致.|
+
+
+### 区域相关
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|timezone | 时区,缺省值:当前服务器所配置的时区 |
+|locale | 系统区位信息及编码格式 ,缺省值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过 API 设置 |
+|charset | 字符集编码,缺省值:系统自动获取 |
+
+:::info
+1. 为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix 时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。
+
+在 Linux/macOS 中,客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如:
+
+```
+timezone UTC-8
+timezone GMT-8
+timezone Asia/Shanghai
+```
+
+均是合法的设置东八区时区的格式。但需注意,Windows 下并不支持 `timezone Asia/Shanghai` 这样的写法,而必须写成 `timezone UTC-8`。
+
+时区的设置对于查询和写入 SQL 语句中非 Unix 时间戳的内容(时间戳字符串、关键词 now 的解析)产生影响。例如:
+
+```sql
+SELECT count(*) FROM table_name WHERE TS<'2019-04-11 12:01:08';
+```
+
+在东八区,SQL 语句等效于
+
+```sql
+SELECT count(*) FROM table_name WHERE TS<1554955268000;
+```
+
+在 UTC 时区,SQL 语句等效于
+
+```sql
+SELECT count(*) FROM table_name WHERE TS<1554984068000;
+```
+
+为了避免使用字符串时间格式带来的不确定性,也可以直接使用 Unix 时间戳。此外,还可以在 SQL 语句中使用带有时区的时间戳字符串,例如:RFC3339 格式的时间戳字符串,2013-04-12T15:52:01.123+08:00 或者 ISO-8601 格式时间戳字符串 2013-04-12T15:52:01.123+0800。上述两个字符串转化为 Unix 时间戳不受系统所在时区的影响。
+
+
+2. TDengine 为存储中文、日文、韩文等非 ASCII 编码的宽字符,提供一种专门的字段类型 nchar。写入 nchar 字段的数据将统一采用 UCS4-LE 格式进行编码并发送到服务器。需要注意的是,编码正确性是客户端来保证。因此,如果用户想要正常使用 nchar 字段来存储诸如中文、日文、韩文等非 ASCII 字符,需要正确设置客户端的编码格式。
+
+客户端的输入的字符均采用操作系统当前默认的编码格式,在 Linux/macOS 系统上多为 UTF-8,部分中文系统编码则可能是 GB18030 或 GBK 等。在 docker 环境中默认的编码是 POSIX。在中文版 Windows 系统中,编码则是 CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证 nchar 中的数据正确转换为 UCS4-LE 编码格式。
+
+在 Linux/macOS 中 locale 的命名规则为: \<语言>_\<地区>.\<字符集编码> 如:zh_CN.UTF-8,zh 代表中文,CN 代表大陆地区,UTF-8 表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux/macOS 可以通过设置 locale 来确定系统的字符编码,由于 Windows 使用的 locale 中不是 POSIX 标准的 locale 格式,因此在 Windows 下需要采用另一个配置参数 charset 来指定字符编码。在 Linux/macOS 中也可以使用 charset 来指定字符编码。
+
+
+3. 如果配置文件中不设置 charset,在 Linux/macOS 中,taos 在启动时候,自动读取系统当前的 locale 信息,并从 locale 信息中解析提取 charset 编码格式。如果自动读取 locale 信息失败,则尝试读取 charset 配置,如果读取 charset 配置也失败,则中断启动过程。
+
+在 Linux/macOS 中,locale 信息包含了字符编码信息,因此正确设置了 Linux/macOS 的 locale 以后可以不用再单独设置 charset。例如:
+
+```
+locale zh_CN.UTF-8
+```
+
+在 Windows 系统中,无法从 locale 获取系统当前编码。如果无法从配置文件中读取字符串编码信息,taos 默认设置为字符编码为 CP936。其等效在配置文件中添加如下配置:
+
+```
+charset CP936
+```
+
+如果需要调整字符编码,请查阅当前操作系统使用的编码,并在配置文件中正确设置。
+
+在 Linux/macOS 中,如果用户同时设置了 locale 和字符集编码 charset,并且 locale 和 charset 的不一致,后设置的值将覆盖前面设置的值。
+
+```
+locale zh_CN.UTF-8
+charset GBK
+```
+
+则 charset 的有效值是 GBK。
+
+```
+charset GBK
+locale zh_CN.UTF-8
+```
+
+charset 的有效值是 UTF-8。
+
+:::
+
+### 存储相关
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|dataDir | 数据文件目录,所有的数据文件都将写入该目录,缺省值:/var/lib |
+|tempDir | 指定所有系统运行过程中的临时文件生成的目录,缺省值:/tmp |
+|minimalTmpDirGB | tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,缺省值: 1|
+|minimalDataDirGB | dataDir 指定的时序数据存储目录所需要保留的最小空间,单位 GB,缺省值: 2 |
+
+### 集群相关
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|supportVnodes | dnode 支持的最大 vnode 数目,取值范围:0-4096,缺省值: CPU 核数的 2 倍 + 5 |
+
+### 性能调优
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|numOfCommitThreads | 写入线程的最大数量,取值范围 0-1024,缺省值为 4 |
+
+### 日志相关
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|logDir | 日志文件目录,运行日志将写入该目录,缺省值:/var/log/taos |
+|minimalLogDirGB | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位GB,缺省值:1|
+|numOfLogLines | 单个日志文件允许的最大行数,缺省值:10,000,000 |
+|asyncLog | 日志写入模式,0: 同步,1: 异步,缺省值: 1 |
+|logKeepDays | 日志文件的最长保存时间 ,单位:天,缺省值:0,意味着无限保存;当设置为大于0 的值时,日志文件会被重命名为 taosdlog.xxx,其中 xxx 为日志文件最后修改的时间戳。 |
+|slowLogThreshold | 慢查询门限值,大于等于门限值认为是慢查询,单位秒,默认值: 3 |
+|slowLogScope | 定启动记录哪些类型的慢查询,可选值:ALL, QUERY, INSERT, OHTERS, NONE; 默认值:ALL |
+|debugFlag | 运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志); 默认值:131 或 135 (取决于不同模块)|
+|tmrDebugFlag | 定时器模块的日志开关,取值范围同上 |
+|uDebugFlag | 共用功能模块的日志开关,取值范围同上 |
+|rpcDebugFlag | rpc 模块的日志开关,取值范围同上 |
+|jniDebugFlag | jni 模块的日志开关,取值范围同上 |
+|qDebugFlag | query 模块的日志开关,取值范围同上 |
+|dDebugFlag | dnode 模块的日志开关,取值范围同上,缺省值 135 |
+|vDebugFlag | vnode 模块的日志开关,取值范围同上 |
+|mDebugFlag | mnode 模块的日志开关,取值范围同上 |
+|wDebugFlag | wal 模块的日志开关,取值范围同上 |
+|sDebugFlag | sync 模块的日志开关,取值范围同上 |
+|tsdbDebugFlag | tsdb 模块的日志开关,取值范围同上 |
+|tqDebugFlag | tq 模块的日志开关,取值范围同上 |
+|fsDebugFlag | fs 模块的日志开关,取值范围同上 |
+|udfDebugFlag | udf 模块的日志开关,取值范围同上 |
+|smaDebugFlag | sma 模块的日志开关,取值范围同上 |
+|idxDebugFlag | index 模块的日志开关,取值范围同上 |
+|tdbDebugFlag | tdb 模块的日志开关,取值范围同上 |
+
+### 压缩参数
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+| compressMsgSize | 是否对 RPC 消息进行压缩;-1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩;缺省值 -1 |
+| fPrecision | 设置 float 类型浮点数压缩精度 ,取值范围:0.1 ~ 0.00000001 ,默认值 0.00000001 , 小于此值的浮点数尾数部分将被截断 |
+|dPrecision | 设置 double 类型浮点数压缩精度 , 取值范围:0.1 ~ 0.0000000000000001 , 缺省值 0.0000000000000001 , 小于此值的浮点数尾数部分将被截取 |
+|lossyColumn | 对 float 和/或 double 类型启用 TSZ 有损压缩;取值范围: float, double, none;缺省值: none,表示关闭无损压缩 |
+|ifAdtFse | 在启用 TSZ 有损压缩时,使用 FSE 算法替换 HUFFMAN 算法, FSE 算法压缩速度更快,但解压稍慢,追求压缩速度可选用此算法; 0: 关闭,1:打开;默认值为 0 |
+
+
+**补充说明**
+1. 在 3.2.0.0 ~ 3.3.0.0(不包含)版本生效,启用该参数后不能回退到升级前的版本
+2. TSZ 压缩算法是通过数据预测技术完成的压缩,所以更适合有规律变化的数据
+3. TSZ 压缩时间会更长一些,如果您的服务器 CPU 空闲多,存储空间小的情况下适合选用
+4. 示例:对 float 和 double 类型都启用有损压缩
+```shell
+lossyColumns float|double
+```
+5. 配置需重启服务生效,重启如果在 taosd 日志中看到以下内容,表明配置已生效:
+```sql
+ 02/22 10:49:27.607990 00002933 UTL lossyColumns float|double
+```
+
+### 其他参数
+
+| 参数名称 | 参数说明 |
+|:-------------:|:----------------------------------------------------------------:|
+|enableCoreFile | crash 时是否生成 core 文件;0: 不生成,1:生成;默认值 为 1; 不同的启动方式,生成 core 文件的目录如下:1、systemctl start taosd 启动:生成的 core 在根目录下
2、手动启动,就在 taosd 执行目录下。|
+|udf | 是否启动 UDF 服务;0: 不启动,1:启动;默认值 为 0 |
+|ttlChangeOnWrite | ttl 到期时间是否伴随表的修改操作改变; 0: 不改变,1:改变 ;默认值 为 |
+| tmqMaxTopicNum| 订阅最多可建立的 topic 数量; 取值范围 1-10000;缺省值 为20 |
+|maxTsmaNum | 集群内可创建的TSMA个数;取值范围:0-3;缺省值: 3|
\ No newline at end of file
diff --git a/docs/zh/14-reference/01-components/02-taosc.md b/docs/zh/14-reference/01-components/02-taosc.md
new file mode 100644
index 0000000000..96d108e8c8
--- /dev/null
+++ b/docs/zh/14-reference/01-components/02-taosc.md
@@ -0,0 +1,44 @@
+---
+title: 客户端驱动参考手册
+sidebar_label: taosc
+toc_max_heading_level: 4
+---
+
+TDengine 客户端驱动提供了应用编程所需要的全部 API,并且在整个集群的分布式计算中扮演着重要角色。客户端驱动的行为除了 API 及其具体参数以外,也可以通过配置文件的形式进行全局控制,本节列举 TDengine 客户端可以使用的配置参数。
+
+## 配置参数
+
+| 参数名称 | 参数含义 |
+|:-----------:|:----------------------------------------------------------:|
+|firstEp | taos 启动时,主动连接的集群中首个 dnode 的 endpoint,缺省值:localhost:6030 |
+|secondEp | 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,没有缺省值 |
+|numOfRpcSessions | 一个客户端能创建的最大连接数,取值范围:10-50000000(单位为毫秒);缺省值:500000 |
+|telemetryReporting | 是否上传 telemetry,0: 不上传,1: 上传;缺省值:1 |
+|crashReporting | 是否上传 telemetry,0: 不上传,1: 上传;缺省值:1 |
+|queryPolicy | 查询语句的执行策略,1: 只使用 vnode,不使用 qnode; 2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行; 3: vnode 只运行扫描算子,其余算子均在 qnode 执行 ;缺省值:1 |
+|querySmaOptimize | sma index 的优化策略,0: 表示不使用 sma index,永远从原始数据进行查询; 1: 表示使用 sma index,对符合的语句,直接从预计算的结果进行查询;缺省值:0 |
+|keepColumnName | Last、First、LastRow 函数查询且未指定别名时,自动设置别名为列名(不含函数名),因此 order by 子句如果引用了该列名将自动引用该列对应的函数; 1: 表示自动设置别名为列名(不包含函数名), 0: 表示不自动设置别名; 缺省值: 0 |
+|countAlwaysReturnValue | ount/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值; 0:返回空行,1:返回; 缺省值 1; 该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了TSMA时, 且相应的组或窗口内数据为空或者NULL, 对应的组或窗口将不返回查询结果. 注意此参数客户端和服务端值应保持一致. |
+|multiResultFunctionStarReturnTags | 查询超级表时,last(\*)/last_row(\*)/first(\*) 是否返回标签列;查询普通表、子表时,不受该参数影响; 0:不返回标签列,1:返回标签列 ; 缺省值: 0; 该参数设置为 0 时,last(\*)/last_row(\*)/first(\*) 只返回超级表的普通列;为 1 时,返回超级表的普通列和标签列 |
+|maxTsmaCalcDelay| 查询时客户端可允许的tsma计算延迟, 若tsma的计算延迟大于配置值, 则该TSMA将不会被使用.; 取值范围: 600s - 86400s, 即10分钟-1小时 ; 缺省值:600 秒|
+|tsmaDataDeleteMark |TSMA计算的历史数据中间结果保存时间, 单位为毫秒; 取值范围:>= 3600000, 即大于等于1h; 缺省值: 86400000, 即1d |
+|timezone | 时区; 缺省从系统中动态获取当前的时区设置 |
+|locale | 系统区位信息及编码格式, 缺省从系统中获取 |
+|charset | 字符集编码,缺省从系统中获取 |
+|metaCacheMaxSize | 指定单个客户端元数据缓存大小的最大值, 单位 MB; 缺省值 -1,表示无限制 |
+|logDir | 日志文件目录,客户端运行日志将写入该目录, 缺省值: /var/log/taos |
+|minimalLogDirGB | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志; 缺省值 1 |
+|numOfLogLines | 单个日志文件允许的最大行数; 缺省值 10,000,000 |
+|asyncLog | 是否异步写入日志,0:同步;1:异步;缺省值:1 |
+|logKeepDays | 日志文件的最长保存时间; 缺省值: 0,表示无限保存; 大于 0 时,日志文件会被重命名为 taosdlog.xxx,其中 xxx 为日志文件最后修改的时间戳|
+|smlChildTableName | schemaless 自定义的子表名的 key, 无缺省值 |
+|smlAutoChildTableNameDelimiter | schemaless tag之间的连接符,连起来作为子表名,无缺省值 |
+|smlTagName | schemaless tag 为空时默认的 tag 名字, 无缺省值 |
+|smlTsDefaultName | schemaless自动建表的时间列名字通过该配置设置, 缺省值 "_ts" |
+|enableCoreFile | crash 时是否生成 core 文件,0: 不生成, 1: 生成;缺省值:1 |
+|enableScience | 是否开启科学计数法显示浮点数; 0: 不开始, 1: 开启;缺省值:1 |
+|compressMsgSize | 是否对 RPC 消息进行压缩; -1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩; 缺省值 -1|
+
+## API
+
+请参考[连接器]
\ No newline at end of file
diff --git a/docs/zh/14-reference/04-taosadapter.md b/docs/zh/14-reference/01-components/03-taosadapter.md
similarity index 96%
rename from docs/zh/14-reference/04-taosadapter.md
rename to docs/zh/14-reference/01-components/03-taosadapter.md
index 70c4450c06..06ba4a9a07 100644
--- a/docs/zh/14-reference/04-taosadapter.md
+++ b/docs/zh/14-reference/01-components/03-taosadapter.md
@@ -1,14 +1,14 @@
---
-title: "taosAdapter"
-description: "taosAdapter 是一个 TDengine 的配套工具,是 TDengine 集群和应用程序之间的桥梁和适配器。它提供了一种易于使用和高效的方式来直接从数据收集代理软件(如 Telegraf、StatsD、collectd 等)摄取数据。它还提供了 InfluxDB/OpenTSDB 兼容的数据摄取接口,允许 InfluxDB/OpenTSDB 应用程序无缝移植到 TDengine"
+title: "taosAdapter 参考手册"
sidebar_label: "taosAdapter"
+toc_max_heading_level: 4
---
-import Prometheus from "./_prometheus.mdx"
-import CollectD from "./_collectd.mdx"
-import StatsD from "./_statsd.mdx"
-import Icinga2 from "./_icinga2.mdx"
-import TCollector from "./_tcollector.mdx"
+import Prometheus from "../_prometheus.mdx"
+import CollectD from "../_collectd.mdx"
+import StatsD from "../_statsd.mdx"
+import Icinga2 from "../_icinga2.mdx"
+import TCollector from "../_tcollector.mdx"
taosAdapter 是一个 TDengine 的配套工具,是 TDengine 集群和应用程序之间的桥梁和适配器。它提供了一种易于使用和高效的方式来直接从数据收集代理软件(如 Telegraf、StatsD、collectd 等)摄取数据。它还提供了 InfluxDB/OpenTSDB 兼容的数据摄取接口,允许 InfluxDB/OpenTSDB 应用程序无缝移植到 TDengine。
@@ -31,7 +31,7 @@ taosAdapter 提供以下功能:
### 安装 taosAdapter
-taosAdapter 是 TDengine 服务端软件 的一部分,如果您使用 TDengine server 您不需要任何额外的步骤来安装 taosAdapter。您可以从[涛思数据官方网站](https://taosdata.com/cn/all-downloads/)下载 TDengine server 安装包。如果需要将 taosAdapter 分离部署在 TDengine server 之外的服务器上,则应该在该服务器上安装完整的 TDengine 来安装 taosAdapter。如果您需要使用源代码编译生成 taosAdapter,您可以参考[构建 taosAdapter](https://github.com/taosdata/taosadapter/blob/3.0/BUILD-CN.md)文档。
+taosAdapter 是 TDengine 服务端软件 的一部分,如果您使用 TDengine server 您不需要任何额外的步骤来安装 taosAdapter。您可以从[涛思数据官方网站](https://docs.taosdata.com/releases/tdengine/)下载 TDengine server 安装包。如果需要将 taosAdapter 分离部署在 TDengine server 之外的服务器上,则应该在该服务器上安装完整的 TDengine 来安装 taosAdapter。如果您需要使用源代码编译生成 taosAdapter,您可以参考[构建 taosAdapter](https://github.com/taosdata/taosadapter/blob/3.0/BUILD-CN.md)文档。
### 启动/停止 taosAdapter
diff --git a/docs/zh/14-reference/01-components/04-taosx.md b/docs/zh/14-reference/01-components/04-taosx.md
new file mode 100644
index 0000000000..032bd58a37
--- /dev/null
+++ b/docs/zh/14-reference/01-components/04-taosx.md
@@ -0,0 +1,327 @@
+---
+title: taosX 参考手册
+sidebar_label: taosX
+---
+
+taosX 是 TDengine 中的一个核心组件,提供零代码数据接入的能力,taosX 支持两种运行模式:服务模式和命令行模式。本节讲述如何以这两种方式使用 taosX。要想使用 taosX 需要先安装 TDengine Enterprise 安装包。
+
+## 命令行模式
+
+### 命令行格式
+
+taosX 的命令行参数格式如下
+
+```shell
+taosx -f -t <其它参数>
+```
+
+taosX 的命令行参数分为三个主要部分:
+- `-f` 指定数据源,即 Source DSN
+- `-t` 指定写入目标,即Sink DSN
+- 其它参数
+
+以下参数说明及示例中若无特殊说明 `` 的格式均为占位符,使用时需要使用实际参数进行替换。
+
+### DSN (Data Source Name)
+
+taosX 命令行模式使用 DSN 来表示一个数据源(来源或目的源),典型的 DSN 如下:
+
+```bash
+# url-like
+[+]://[[:@]:][/