多级存储与对象存储
本节介绍 TDengine TSDB Enterprise 特有的多级存储功能,其作用是将较近的热度较高的数据存储在高速介质上,而时间久远热度很低的数据存储在低成本介质上,达成了以下目标:
- 降低存储成本:将数据分级存储后,海量极冷数据存入廉价存储介质带来显著经济性
- 提升写入性能:得益于每级存储可支持多个挂载点,WAL 预写日志也支持 0 级的多挂载点并行写入,极大提升写入性能(实际场景测得支持持续写入每秒 3 亿测点以上),在机械硬盘上可获得极高磁盘 IO 吞吐(实测可达 2GB/s)
- 方便维护:配置好各级存储挂载点后,系统数据迁移等工作,无需人工干预;存储扩容更灵活、方便
- 对 SQL 透明:无论查询的数据是否跨级,一条 SQL 可返回所有数据,简单高效
多级存储所涉及的各层存储介质都是本地存储设备。除了本地存储设备之外,TDengine TSDB Enterprise 还支持使用对象存储,将最冷的一批数据保存在最廉价的介质上,以进一步降低存储成本,并在必要时仍然可以进行查询,且数据存储在哪里也对 SQL 透明。
由于大多数对象存储本身已经是多副本,如果 TDengine TSDB 在其基础上再叠加一个多副本,无疑将会浪费大量的存储资源并增加存储成本,所以,TDengine TSDB 进一步将对象存储优化为了共享存储,共享存储中的数据在逻辑上只有一份,并在 TDengine TSDB 集群节点之间共享。
共享存储在 3.3.7.0 版本中首次发布,它是对 3.3.0.0 版本开始支持的对象存储(S3)功能的增强。但需要注意,二者并不兼容,如果已经使用了之前版本的对象存储功能,升级到 3.3.7.0 时需要进行一些手工处理。
多级存储
配置方式
多级存储支持 3 级,每级最多可配置 128 个挂载点。
Tips 典型的配置方案有:0 级配置多个挂载点,每个挂载点对应单块 SAS 硬盘;1 级配置多个挂载点,每个挂载点对应单块或多块 SATA 硬盘;2 级可配置 S3 存储或其他廉价网络存储。
TDengine TSDB 多级存储配置方式如下(在配置文件/etc/taos/taos.cfg 中):
dataDir [path] <level> <primary>
- path: 挂载点的文件夹路径。
- level:介质存储等级,取值为 0、1、2。0 级存储最新的数据,1 级存储次新的数据,2 级存储最老的数据,省略默认为 0。各级存储之间的数据流向:0 级存储 -> 1 级存储 -> 2 级存储。同一存储等级可挂载多个硬盘,同一存储等级上的数据文件分布在该存储等级的所有硬盘上。需要说明的是,数据在不同级别的存储介质上的移动,是由系统自动完成的,用户无需干预。
- primary:是否为主挂载点,0(否)或 1(是),省略默认为 1。
在配置中,只允许一个主挂载点的存在(level=0,primary=1),例如采用如下的配置方式:
dataDir /mnt/data1 0 1
dataDir /mnt/data2 0 0
dataDir /mnt/data3 1 0
dataDir /mnt/data4 1 0
dataDir /mnt/data5 2 0
dataDir /mnt/data6 2 0
注意
- 多级存储不允许跨级配置,合法的配置方案有:仅 0 级、仅 0 级 + 1 级、以及 0 级 + 1 级 + 2 级。而不允许只配置 level=0 和 level=2,而不配置 level=1。
- 禁止手动移除使用中的挂载盘,挂载盘目前不支持非本地的网络盘。
负载均衡
在多级存储中,有且只有一个主挂载点,主挂载点承担了系统中最重要的元数据存储,同时各个 vnode 的主目录均存在于当前 dnode 主挂载点上,从而导致该 dnode 的写入性能受限于单个磁盘的 IO 吞吐能力。
从 TDengine TSDB 3.1.0.0 开始,如果一个 dnode 配置了多个 0 级挂载点,我们将该 dnode 上所有 vnode 的主目录均衡分布在所有的 0 级挂载点上,由这些 0 级挂载点共同承担写入负荷。
在网络 I/O 及其它处理资源不成为瓶颈的情况下,通过优化集群配置,测试结果证明整个系统的写入能力和 0 级挂载点的数量呈现线性关系,即随着 0 级挂载点数量的增加,整个系统的写入能力也成倍增加。
同级挂载点选择策略
一般情况下,当 TDengine TSDB 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。
为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 minDiskFreeSize,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,若配置值大于 2GB,则会跳过可用空间小于 2GB 的挂载点。
从 3.3.2.0 版本开始,引入了一个新的配置 disable_create_new_file,用于控制在某个挂载点上禁止生成新文件,其缺省值为 false,即每个挂载点上默认都可以生成新文件。
共享存储
本节介绍在 TDengine TSDB Enterprise 版本中如何使用共享存储功能,TDengine 支持使用 Amazon S3、Azure Blob Storage、华为 OBS、腾讯云 COS、阿里云 OSS、MinIO 等对象存储服务或挂载到本地的 NAS、SAN 等作为共享存储设备。
注意 在配合多级存储使用时,每一级存储介质上保存的数据都有可能被按规则备份到远程共享存储中并删除本地数据文件。
共享存储相关的配置参数保存在 /etc/taos/taos.cfg 中,如下表所示:
| 参数名称 | 参数含义 |
|---|---|
| ssEnabled | 是否启用共享存储,默认值为 0,表示禁用共享存储。 1 表示启用共享存储,但仅支持数据的手动迁移。 2 表示启用共享存储且支持自动迁移。 |
| ssAccessString | 一个包含各种共享存储访问选项的字符串,格式为 <device-type>:<option-name>=<option-value>;<option-name>=<option-value>;...根据存储设备的不同,此参数的具体选项与存储设备类型相关,下一节会分别详细说明。 |
| ssUploadDelaySec | data 文件持续多长时间不再变动后上传至共享存储,单位:秒。 最小值:1;最大值:2592000(30 天),默认值 60 秒。 |
| ssPageCacheSize | 共享存储 page cache 缓存页数目,单位:页。 最小值:4;最大值:102410241024。 ,默认值 4096。 |
| ssAutoMigrateIntervalSec | 本地数据文件自动上传共享存储的触发周期,单位为秒。 最小值:600;最大值:100000。默认值 3600。 |
存储设备的连接参数
配置参数 ssAccessString 中可使用的选项与具体存储设备类型相关。
S3 对象存储
本功能基于通用 S3 SDK 实现,对各个 S3 兼容平台的访问参数进行了兼容适配,通过适当的参数配置,可以支持大部分 S3 兼容服务。
当使用 S3 兼容服务作为存储设备时,ssAccessString 中的 device-type 必须是 s3,可以使用的选项如下:
| 名称 | 含义 |
|---|---|
| endpoint | 对象存储服务的机器名或 IP 地址,可以包含可选的端口号。 |
| bucket | 存储桶的名字。 |
| protocol | https 或 http,默认是 https。 |
| uriStyle | virtualHost 或 path,默认是 virtualHost。注意,部分对象存储仅支持其中之一。 |
| region | 对象存储服务所在区域,此参数可选。 |
| accessKeyId | 用于访问对象存储的 access key id。 |
| secretAccessKey | 上述 access key id 对应的密钥。 |
| chunkSize | 以 MB 为单位的数据片大小,默认值是 64,超过此大小的文件,将使用 multipart 方式上传。 |
| maxChunks | 单个数据文件的最大分片数量,默认值为 10000。 |
| maxRetry | 访问对象存储时出现可重试错误时的最大重试次数,默认值是 3,负值表示一直重试直到成功为止。 |
| verifyPeer | 是否校验对方(服务器)的证书,仅在 protocol 是 https 时有效,默认值是 false。 |
例如:
ssAccessString s3:endpoint=s3.amazonaws.com;bucket=mybucket;uriStyle=path;protocol=https;accessKeyId=AKMYACCESSKEY;secretAccessKey=MYSECRETACCESSKEY;region=us-east-2;chunkSize=64;maxChunks=10000;maxRetry=3
挂载到本地的存储设备
对 TDengine 来说,网络存储设备挂载到本地后等同于本地磁盘,当使用此类设备作为共享存储时,ssAccessString 的 device-type 必须是 fs,可以使用的选项如下:
| 名称 | 含义 |
|---|---|
| baseDir | 一个路径,TDengine 将使用其对应的目录作为共享存储。 |
例如:
ssAccessString fs:baseDir=/var/taos/ss
检查配置参数可用性
在 taos.cfg 中完成对共享存储的配置后,通过 taosd 命令的 checkss 参数可以检查所配置的共享存储服务是否可用:
taosd --checkss
如果配置的共享存储服务无法访问,此命令会在运行过程中输出相应的错误信息。
创建使用共享存储的数据库
完成配置后,即可启动 TDengine TSDB 集群,创建使用共享存储的数据库,比如:
create database demo_db duration 1d ss_keeplocal 3d;
数据库 demo_db 中写入时序数据后,3 天之前的时序数据会自动分块存放到共享存储中。
如果 ssEnabled 是 2,mnode 每小时会下发数据迁移检查的指令,如果有时序数据需要迁移,则自动分块存放到共享存储中,也可以使用 SQL 命令手动触发,由用户触发这一操作,语法如下:
ssmigrate database <db_name>;
如果 ssEnabled 是 1,mnode 不会自动下发迁移指令,用户必须自己手动触发迁移。
详细的 DB 参数见下表:
| # | 参数 | 默认值 | 最小值 | 最大值 | 描述 |
|---|---|---|---|---|---|
| 1 | ss_keeplocal | 365 | 1 | 365000 | 数据在本地保留的天数,即 data 文件在本地磁盘保留多长时间后可以上传到共享存储。默认单位:天,支持 m(分钟)、h(小时)和 d(天)三个单位 |
| 2 | ss_chunkpages | 131072 | 131072 | 1048576 | 上传对象的大小阈值,与 tsdb_pagesize 参数一样,不可修改,单位为 TSDB 页 |
| 3 | ss_compact | 1 | 0 | 1 | TSDB 文件组首次上传共享存储时,是否自动进行 compact 操作 |
对象存储读写次数估算
对象存储服务的使用成本与存储的数据量及请求次数相关,下面分别介绍数据的上传及下载过程。
数据迁移
当 TSDB 时序数据超过 ss_keeplocal 参数指定的时间,主节点(vnode)会将数据文件切分成多个文件块,除了最后一块,每个文件块的默认大小都是 512M 字节 (ss_chunkpages * tsdb_pagesize)。所有文件快都会被上传到共享存储,除了最后一个文件块,其他文件上传完成后都会从本地文件系统删除。
在创建数据库时,可以通过 ss_chunkpages 参数调整每个文件块的大小,从而控制每个数据文件的上传次数。
其它类型的文件如 head, stt, sma 等也会被上传到共享存储,但会保留本地文件以加速预计算相关查询。
所有文件上传完成后,主节点还会在共享存储中自动创建一个 manifests 文件,用于记录上传信息。
之后,从节点会读取 manifests 文件,然后根据其中的信息,将数据文件的最后一块和所有其他文件下载到本地。
所以,迁移过程中的读写次数约为:
读写次数 = 数据文件总块数 + (其他文件的总数 + 2)✖ 集群节点数
数据下载
在查询操作中,如果需要访问对象存储中的数据,TSDB 不会下载整个数据文件,而是计算所需数据在文件中的位置,只下载相应的数据到 TSDB 页缓存中,然后将数据返回给查询执行引擎。后续查询首先检查页缓存,查看数据是否已被缓存。如果数据已缓存,则直接使用缓存中的数据,而无需重复从对象存储下载,从而有效降低从对象存储下载数据的次数。
相邻的多个数据页会作为一个数据块从对象存储下载一次,以减少从对象存储下载的次数。每个数据页的大小,在创建数据库时,通过 tsdb_pagesize 参数指定,默认 4K 字节。
下载次数 = 查询需要的数据块数量 - 已缓存的数据块数量
页缓存是内存缓存,节点重启后,再次查询需要重新下载数据。缓存采用 LRU (Least Recently Used) 策略,当缓存空间不足时,最近最少使用的数据将被淘汰。缓存的大小可以通过 ssPageCacheSize 参数进行调整,通常来说,缓存越大,下载次数越少。
Azure Blob 存储
共享存储对 Azure Blob 的支持将在后续版本提供,如果已经在 TDengine TSDB 3.3.7.0 之前的版本中使用了 Azure Blob,请暂缓升级。







