Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
慢慢CG
TDengine
提交
42441cce
T
TDengine
项目概览
慢慢CG
/
TDengine
与 Fork 源项目一致
Fork自
taosdata / TDengine
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
42441cce
编写于
8月 01, 2020
作者:
陶建辉(Jeff)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
minior changes
上级
465da4cb
变更
7
展开全部
显示空白变更内容
内联
并排
Showing
7 changed file
with
71 addition
and
62 deletion
+71
-62
documentation20/webdocs/markdowndocs/Model-ch.md
documentation20/webdocs/markdowndocs/Model-ch.md
+4
-3
documentation20/webdocs/markdowndocs/administrator-ch.md
documentation20/webdocs/markdowndocs/administrator-ch.md
+5
-5
documentation20/webdocs/markdowndocs/architecture-ch.md
documentation20/webdocs/markdowndocs/architecture-ch.md
+51
-45
documentation20/webdocs/markdowndocs/cluster-ch.md
documentation20/webdocs/markdowndocs/cluster-ch.md
+5
-3
documentation20/webdocs/markdowndocs/insert-ch.md
documentation20/webdocs/markdowndocs/insert-ch.md
+1
-1
documentation20/webdocs/markdowndocs/replica-ch.md
documentation20/webdocs/markdowndocs/replica-ch.md
+2
-2
documentation20/webdocs/markdowndocs/taosd-ch.md
documentation20/webdocs/markdowndocs/taosd-ch.md
+3
-3
未找到文件。
documentation20/webdocs/markdowndocs/Model-ch.md
浏览文件 @
42441cce
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
TDengine采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库的设计,超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。
TDengine采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库的设计,超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。
##创建库
##
创建库
不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小等等。为让各种场景下TDengine都能最大效率的工作,TDengine建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除SQL标准的选项外,应用还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小等等。为让各种场景下TDengine都能最大效率的工作,TDengine建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除SQL标准的选项外,应用还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
...
@@ -31,7 +31,7 @@ CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2);
...
@@ -31,7 +31,7 @@ CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2);
```
```
其中d1001是表名,meters是超级表的表名,后面紧跟标签Location的具体标签值”Beijing.Chaoyang",标签groupId的具体标签值2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 TAOS SQL。
其中d1001是表名,meters是超级表的表名,后面紧跟标签Location的具体标签值”Beijing.Chaoyang",标签groupId的具体标签值2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 TAOS SQL。
TDengine建议将数据采集点的全局唯一ID作为表名。但对于有的场景,并没有唯一的ID,可以将多个ID组合成一个唯一的ID。不建议将具有唯一性的ID作为标签值。
TDengine建议将数据采集点的全局唯一ID作为表名
(比如设备序列号)
。但对于有的场景,并没有唯一的ID,可以将多个ID组合成一个唯一的ID。不建议将具有唯一性的ID作为标签值。
**自动建表**
:在某些特殊场景中,用户在写数据时并不确定某个数据采集点的表是否存在,此时可在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。比如:
**自动建表**
:在某些特殊场景中,用户在写数据时并不确定某个数据采集点的表是否存在,此时可在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。比如:
...
@@ -41,3 +41,4 @@ INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 21
...
@@ -41,3 +41,4 @@ INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 21
上述SQL语句将记录(now, 10.2, 219, 0.32) 插入进表d1001。如果表d1001还未创建,则使用超级表meters做模板自动创建,同时打上标签值“Beijing.Chaoyang", 2。
上述SQL语句将记录(now, 10.2, 219, 0.32) 插入进表d1001。如果表d1001还未创建,则使用超级表meters做模板自动创建,同时打上标签值“Beijing.Chaoyang", 2。
**多列模型**
:TDengine支持多列模型,只要这些物理量是同时采集的,这些量就可以作为不同列放在同一张表里。有的数据采集点有多组采集量,每一组的数据采集时间是不一样的,这时需要对同一个采集点建多张表。但还有一种极限的设计,单列模型,无论是否同时采集,每个采集的物理量单独建表。TDengine建议,只要采集时间一致,就采用多列模型,因为插入效率以及存储效率更高。
**多列模型**
:TDengine支持多列模型,只要这些物理量是同时采集的,这些量就可以作为不同列放在同一张表里。有的数据采集点有多组采集量,每一组的数据采集时间是不一样的,这时需要对同一个采集点建多张表。但还有一种极限的设计,单列模型,无论是否同时采集,每个采集的物理量单独建表。TDengine建议,只要采集时间一致,就采用多列模型,因为插入效率以及存储效率更高。
documentation20/webdocs/markdowndocs/administrator-ch.md
浏览文件 @
42441cce
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
### 内存需求
### 内存需求
每个DB可以创建固定数目的vnode,默认与CPU核数相同,可通过maxVgroupsPerDb配置;每个vnode会占用固定大小的内存(大小与数据库的配置参数blocks和cache有关);每个Table会占用与
Tag总大小
有关的内存;此外,系统会有一些固定的内存开销。因此,每个DB需要的系统内存可通过如下公式计算:
每个DB可以创建固定数目的vnode,默认与CPU核数相同,可通过maxVgroupsPerDb配置;每个vnode会占用固定大小的内存(大小与数据库的配置参数blocks和cache有关);每个Table会占用与
标签总长度
有关的内存;此外,系统会有一些固定的内存开销。因此,每个DB需要的系统内存可通过如下公式计算:
```
```
Memory Size = maxVgroupsPerDb * (blocks * cache + 10Mb) + numOfTables * (tagSizePerTable + 0.5Kb)
Memory Size = maxVgroupsPerDb * (blocks * cache + 10Mb) + numOfTables * (tagSizePerTable + 0.5Kb)
...
@@ -22,7 +22,7 @@ Memory Size = maxVgroupsPerDb * (blocks * cache + 10Mb) + numOfTables * (tagSize
...
@@ -22,7 +22,7 @@ Memory Size = maxVgroupsPerDb * (blocks * cache + 10Mb) + numOfTables * (tagSize
CPU的需求取决于如下两方面:
CPU的需求取决于如下两方面:
-
数据插入:TDengine单核每秒能至少处理一万个插入请求。每个插入请求可以带多条记录,一次插入一条记录与插入10条记录,消耗的计算资源差别很小。因此
没
次插入,条数越大,插入效率越高。如果一个插入请求带200条以上记录,单核就能达到每秒插入100万条记录的速度。但对前端数据采集的要求越高,因为需要缓存记录,然后一批插入。
-
数据插入:TDengine单核每秒能至少处理一万个插入请求。每个插入请求可以带多条记录,一次插入一条记录与插入10条记录,消耗的计算资源差别很小。因此
每
次插入,条数越大,插入效率越高。如果一个插入请求带200条以上记录,单核就能达到每秒插入100万条记录的速度。但对前端数据采集的要求越高,因为需要缓存记录,然后一批插入。
-
查询需求:TDengine提供高效的查询,但是每个场景的查询差异很大,查询频次变化也很大,难以给出客观数字。需要用户针对自己的场景,写一些查询语句,才能确定。
-
查询需求:TDengine提供高效的查询,但是每个场景的查询差异很大,查询频次变化也很大,难以给出客观数字。需要用户针对自己的场景,写一些查询语句,才能确定。
因此仅对数据插入而言,CPU是可以估算出来的,但查询所耗的计算资源无法估算。在实际运营过程中,不建议CPU使用率超过50%,超过后,需要增加新的节点,以获得更多计算资源。
因此仅对数据插入而言,CPU是可以估算出来的,但查询所耗的计算资源无法估算。在实际运营过程中,不建议CPU使用率超过50%,超过后,需要增加新的节点,以获得更多计算资源。
...
@@ -45,7 +45,7 @@ Raw DataSize = numOfTables * rowSizePerTable * rowsPerTable
...
@@ -45,7 +45,7 @@ Raw DataSize = numOfTables * rowSizePerTable * rowsPerTable
根据上面的内存、CPU、存储的预估,就可以知道整个系统需要多少核、多少内存、多少存储空间。如果数据副本数不为1,总需求量需要再乘以副本数。
根据上面的内存、CPU、存储的预估,就可以知道整个系统需要多少核、多少内存、多少存储空间。如果数据副本数不为1,总需求量需要再乘以副本数。
因为TDengine具有很好的水平扩展能力,根据总量,再根据单个物理机或虚拟机的资源,就可以轻松决定需要购置多少台
机器
了。
因为TDengine具有很好的水平扩展能力,根据总量,再根据单个物理机或虚拟机的资源,就可以轻松决定需要购置多少台
物理机或虚拟机
了。
## 容错和灾备
## 容错和灾备
...
@@ -136,8 +136,8 @@ TDengine系统的前台交互客户端应用程序为taos,它与taosd共享同
...
@@ -136,8 +136,8 @@ TDengine系统的前台交互客户端应用程序为taos,它与taosd共享同
客户端配置参数列表及解释
客户端配置参数列表及解释
-
first: taos启动时,主动连接的集群中第一个taosd实例的end point, 缺省值为 localhost:6030。
-
first
Ep
: taos启动时,主动连接的集群中第一个taosd实例的end point, 缺省值为 localhost:6030。
-
second: taos启动时,如果first连接不上,尝试连接集群中第二个taosd实例的end point, 缺省值为空。
-
second
Ep
: taos启动时,如果first连接不上,尝试连接集群中第二个taosd实例的end point, 缺省值为空。
-
charset:字符集编码。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
-
charset:字符集编码。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
-
locale:系统区位信息及编码格式。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
-
locale:系统区位信息及编码格式。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
...
...
documentation20/webdocs/markdowndocs/architecture-ch.md
浏览文件 @
42441cce
此差异已折叠。
点击以展开。
documentation20/webdocs/markdowndocs/cluster-ch.md
浏览文件 @
42441cce
...
@@ -29,7 +29,7 @@ taos>
...
@@ -29,7 +29,7 @@ taos>
将新的节点添加到现有集群,具体有以下几步:
将新的节点添加到现有集群,具体有以下几步:
1.
按照
[
"立即开始“
](
https://www.taosdata.com/cn/getting-started/
)
一章的方法进行安装,
但不要启动taosd
1.
按照
[
"立即开始“
](
https://www.taosdata.com/cn/getting-started/
)
一章的方法进行安装,
**但不要启动taosd**
2.
如果是使用涛思数据的官方安装包进行安装,在安装结束时,会询问集群的End Port, 输入第一个节点的End Point即可。如果是源码安装,请编辑配置文件taos.cfg(缺省是在/etc/taos/目录),增加一行:
2.
如果是使用涛思数据的官方安装包进行安装,在安装结束时,会询问集群的End Port, 输入第一个节点的End Point即可。如果是源码安装,请编辑配置文件taos.cfg(缺省是在/etc/taos/目录),增加一行:
...
@@ -64,7 +64,7 @@ taos>
...
@@ -64,7 +64,7 @@ taos>
**提示:**
**提示:**
-
firstEp, secondEp这两个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
-
firstEp, secondEp这两个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
-
两个没有配置first
, second
参数的dnode启动后,会独立运行起来。这个时候,无法将其中一个节点加入到另外一个节点,形成集群。
**无法将两个独立的集群合并成为新的集群**
。
-
两个没有配置first
Ep, secondEp
参数的dnode启动后,会独立运行起来。这个时候,无法将其中一个节点加入到另外一个节点,形成集群。
**无法将两个独立的集群合并成为新的集群**
。
##节点管理
##节点管理
...
@@ -135,8 +135,10 @@ SHOW MNODES;
...
@@ -135,8 +135,10 @@ SHOW MNODES;
-
改节点离线超过一定时间(taos.cfg里配置参数offlineThreshold控制时长),系统将自动把该节点删除,产生系统报警信息,触发负载均衡流程。如果该被删除的节点重现上线时,它将无法加入集群,需要系统管理员重新将其添加进集群才会开始工作。
-
改节点离线超过一定时间(taos.cfg里配置参数offlineThreshold控制时长),系统将自动把该节点删除,产生系统报警信息,触发负载均衡流程。如果该被删除的节点重现上线时,它将无法加入集群,需要系统管理员重新将其添加进集群才会开始工作。
-
离线后,在offlineThreshold的时长内重新上线,系统将自动启动数据恢复流程,等数据完全恢复后,该节点将开始正常工作。
-
离线后,在offlineThreshold的时长内重新上线,系统将自动启动数据恢复流程,等数据完全恢复后,该节点将开始正常工作。
**注意:**
如果一个虚拟节点组(包括mnode组)里每个节点都处于离线或unsynced状态,必须等该虚拟节点组里的所有节点都上线、都能交换状态信息后,才能选出Master,该虚拟节点组才能对外提供服务。比如整个集群有3个节点,副本数为3,如果3个节点都宕机,然后2个节点重启,是无法工作的,只有等3个节点都重启成功,才能对外服务。
##Arbitrator的使用
##Arbitrator的使用
如果副本数为偶数,当一个vnode group里一半
vnode不工作时,是无法从中选出master的。同理,一半
mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
如果副本数为偶数,当一个vnode group里一半
或超过一半的vnode不工作时,是无法从中选出master的。同理,一半或超过一半的
mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
TDengine安装包里带有一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数
`-p`
可以指定其对外服务的端口号,缺省是6030。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了,当副本数为偶数数,系统将自动连接配置的arbitrator。
TDengine安装包里带有一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数
`-p`
可以指定其对外服务的端口号,缺省是6030。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了,当副本数为偶数数,系统将自动连接配置的arbitrator。
documentation20/webdocs/markdowndocs/insert-ch.md
浏览文件 @
42441cce
...
@@ -23,7 +23,7 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
...
@@ -23,7 +23,7 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
**Tips:**
**Tips:**
-
要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置)。
-
要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置)。
-
TDengine支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开20个以上的线程同时写。
-
TDengine支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开20个以上的线程同时写。
但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程切频繁切换,带来额外开销。
## Prometheus直接写入
## Prometheus直接写入
[
Prometheus
](
https://www.prometheus.io/
)
作为Cloud Native Computing Fundation毕业的项目,在性能监控以及K8S性能监控领域有着非常广泛的应用。TDengine提供一个小工具
[
Bailongma
](
https://github.com/taosdata/Bailongma
)
,只需在Prometheus做简单配置,无需任何代码,就可将Prometheus采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文
[
用Docker容器快速搭建一个Devops监控Demo
](
https://www.taosdata.com/blog/2020/02/03/1189.html
)
即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。
[
Prometheus
](
https://www.prometheus.io/
)
作为Cloud Native Computing Fundation毕业的项目,在性能监控以及K8S性能监控领域有着非常广泛的应用。TDengine提供一个小工具
[
Bailongma
](
https://github.com/taosdata/Bailongma
)
,只需在Prometheus做简单配置,无需任何代码,就可将Prometheus采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文
[
用Docker容器快速搭建一个Devops监控Demo
](
https://www.taosdata.com/blog/2020/02/03/1189.html
)
即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。
...
...
documentation20/webdocs/markdowndocs/replica-ch.md
浏览文件 @
42441cce
...
@@ -224,9 +224,9 @@ Arbitrator的程序tarbitrator.c在复制模块的同一目录, 编译整个系
...
@@ -224,9 +224,9 @@ Arbitrator的程序tarbitrator.c在复制模块的同一目录, 编译整个系
如果整个虚拟节点组全部宕机,重启,但不是所有虚拟节点都上线,这个时候TDengine是不会选出master的,因为未上线的节点有可能有最高version的数据。而RAFT协议,只要超过半数上线,就会选出Leader。
如果整个虚拟节点组全部宕机,重启,但不是所有虚拟节点都上线,这个时候TDengine是不会选出master的,因为未上线的节点有可能有最高version的数据。而RAFT协议,只要超过半数上线,就会选出Leader。
## Meta Data
数据复制问题
## Meta Data
的数据复制
TDengine里存在时序数据,也存在Meta Data。Meta Data对数据的可靠性要求更高,那么
本
设计能否满足要求呢?下面做个仔细分析
TDengine里存在时序数据,也存在Meta Data。Meta Data对数据的可靠性要求更高,那么
TDengine
设计能否满足要求呢?下面做个仔细分析
TDengine里Meta Data包括以下:
TDengine里Meta Data包括以下:
...
...
documentation20/webdocs/markdowndocs/taosd-ch.md
浏览文件 @
42441cce
...
@@ -82,9 +82,9 @@ TSDB中存储的元数据包含属于其所在的VNODE中表的类型,schema
...
@@ -82,9 +82,9 @@ TSDB中存储的元数据包含属于其所在的VNODE中表的类型,schema
该模块负责整体系统的查询处理。客户端调用该该模块进行SQL语法解析,并将查询或写入请求发送到vnode,同时负责针对超级表的查询进行二阶段的聚合操作。在Vnode端,该模块调用TSDB模块读取系统中存储的数据进行查询处理。Query模块还定义了系统能够支持的全部查询函数,查询函数的实现机制与查询框架无耦合,可以在不修改查询流程的情况下动态增加查询函数。详细的设计请参见《TDengine 2.0查询模块设计》。
该模块负责整体系统的查询处理。客户端调用该该模块进行SQL语法解析,并将查询或写入请求发送到vnode,同时负责针对超级表的查询进行二阶段的聚合操作。在Vnode端,该模块调用TSDB模块读取系统中存储的数据进行查询处理。Query模块还定义了系统能够支持的全部查询函数,查询函数的实现机制与查询框架无耦合,可以在不修改查询流程的情况下动态增加查询函数。详细的设计请参见《TDengine 2.0查询模块设计》。
## SYNC模块
## SYNC模块
该模块实现数据的多副本复制,包括vnode与mnode的数据复制,支持异步和同步两种复制方式,以满足meta data与时序数据不同复制的需求。因为它为mnode与vnode共享,系统为mnode副本预留了一个特殊的vgroup ID:1。因此vnode的ID是从2开始的。
该模块实现数据的多副本复制,包括vnode与mnode的数据复制,支持异步和同步两种复制方式,以满足meta data与时序数据不同复制的需求。因为它为mnode与vnode共享,系统为mnode副本预留了一个特殊的vgroup ID:1。因此vnode
group
的ID是从2开始的。
每个vnode/mnode模块实例会有一对应的sync模块实例,他们是一一对应的。详细设计请见
《TDengine 2.0 数据复制模块设计》
每个vnode/mnode模块实例会有一对应的sync模块实例,他们是一一对应的。详细设计请见
<a
href=
"https://www.taosdata.com/cn/documentation20/replica/"
>
TDengine 2.0 数据复制模块设计
</a>
## WAL模块
## WAL模块
该模块负责将新插入的数据写入write ahead log(WAL), 为vnode, mnode共享。以保证服务器crash或其他故障,能从WAL中恢复数据。
该模块负责将新插入的数据写入write ahead log(WAL), 为vnode, mnode共享。以保证服务器crash或其他故障,能从WAL中恢复数据。
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录