何时删?怎么删?5分钟吃透TDengine过期数据自动清除机制

515 阅读7分钟

在之前的一期内容里,我们讲到了如何利用合理的配置vnode完成TDengine的数据分片(这几个神秘参数,教你TDengine集群的正确使用方式),本期我们来继续讲讲TDengine如何从时间维度去对数据进行分区管理。

首先,先看看官网的相关描述:

“TDengine除vnode分片之外,还对时序数据按照时间段进行分区。每个数据文件只包含一个时间段的时序数据,时间段的长度由DB的配置参数days决定。这种按时间段分区的方法还便于高效实现数据的保留策略,只要数据文件超过规定的天数(系统配置参数keep),将被自动删除。而且不同的时间段可以存放于不同的路径和存储介质,以便于大数据的冷热管理,实现多级存储。

总的来说,TDengine是通过vnode以及时间两个维度,对大数据进行切分,便于并行高效的管理,实现水平扩展。”

可以看出,在这个过程中keep参数在发挥着十分重要的作用。但是同样,keep参数也算是比较典型的,容易令使用者迷惑的参数了。

官方文档关于keep的描述是这样的:“数据库中数据保留的天数,单位为天,默认值:3650”,和他一起搭配使用的还有一个days参数:“一个数据文件存储数据的时间跨度,单位为天,默认值:10”。

从使用者的角度,对于这句话的理解就是数据保留keep的天数后就不应该可以查询到数据了。但是,在实际操作的时候,经常可以看到已经超出时间范围的数据依然出现在了查询结果当中。

why?

首先,我们来简单了解一下TDengine的存储逻辑:数据写入数据库后,会先保存在内存中的缓冲区(buffer pool)当中,当到达阈值后(缓冲区1/3,或者关闭数据库服务)内存中数据就会落盘到该表所属的vnode的目录下面(默认/var/lib/taos/vnode/vnodeX/tsdb/data)。其中vnodeX中的X可以通过show vgroups命令看到。

示范如下:

测试的时候,只要随意插入一条数据,然后做一下服务重启:systemctl restart taosd,刚刚写入内存的数据现在就会落到硬盘上。

注:重启服务是一个很实用的测试操作,可以触发内存中的数据落盘——目前,只有数据落盘时才会触发自动删除机制(后续在初始化时也会增加自动删除触发)。如果该数据库后面不再有数据落盘,那么数据文件即使过期了也是不会被删除的。

现在,你就可以找到你的数据文件了,下图可以看到,在重启之前这个目录下还没有任何文件。但在重启之后,就看到了三个以1880为编号的一组文件。

从广义上来说,这三个文件都属于数据文件,后面提到的数据文件都是指他们三个形成的文件组。

接下来,我们回到实际的场景中。

想测试数据存储策略的同学对下面这个场景一定不陌生:建库的时候,我们指定keep为10,days为10。假如数据文件是1月1日生成,但是到了1月19日的时候,1月1日插入的数据却还是可以被查询到。于是,你从taos shell里退出来一看——果然,1月1日生成的数据文件居然还没有被删除。

奇怪——难道是keep参数没有生效?

想搞懂这个问题的答案,我们还需要知道的是days参数的设计:我们所说的days定义——“数据文件保留的数据时间跨度”,它是以系统时间判定的,逻辑是:数据文件第一次生成的日期为起始日期,与系统时间做计算(注:该计算只以自然日为切分,不以24小时计算)。一旦文件生成超过days天数,在下次数据落盘的时候就会生成新的数据文件。

事实上,当你发现旧数据依然可以查询的时候,99.9%的情况都不是keep不生效。最根本的原因其实是TDengine要等到数据文件里面的所有数据过期后才会删除它们。还是上面的场景(keep 10 days 10):1月1日产生的数据文件中是可能存在1月10日的数据的,所以在1月19日的时候,这部分数据还没有到10天,所以在设计上是不允许删除的。因此,就拖带着1-9日间的数据也没有被删除掉。

以上,就是文章标题的答案。

可以看出,由于数据文件是以days为单位存储在一起的,所以days越小,自动删除就会越精准。那为什么我们不干脆把days设置小一点呢?其实这样是没问题的。但是在性能上,days越小意味着意味着数据文件的数目越多,从而导致太多文件频繁开关读取增加开销。所以,默认值取days为10就是一个折中的选择。

现在,我们来到了新的问题:

1.TDengine是在什么情况下才会删除过期文件呢?

2.我们要通过什么方式来快速判断自动删除机制是否在正常工作呢?

我们可以把这两个问题融合在一个场景下进行回答:

问题一:答案只要接着上文的场景继续推进就可以得到(keep 10 days 10):时间来到1月21日时,第3批数据文件生成,此时第1批数据文件的最后1天的数据终于也超过了keep值。这个时候,keep才会正式生效并把第一组数据文件从存储中删除。现在回到TDengine里面,你就查不到这部分数据了。

问题二:答案是只要数一数vnode下面的数据文件组数就可以了:比如在上面的情况下(keep 10 days 10),vnode目录下面的数据文件数最多也就只有两组:1-10日 11-20日(时间范围),当存储21-30日的数据文件生成时,1-10日的数据文件已经被删掉了,所以最多只能保留两个,计算方式为keep/days+1。在这种情况下,只要vnode下的数据文件数小于等于keep/days+1,就可以认为自动删除机制在正常工作。

但是在keep不能被days整除的情况下,还会出现下面的情况:

我们假设keep=3 days=2。在这个配置下,第一批数据文件中存储的时间是1-2日,第二个数据文件为3-4日。可以看到,当第一个文件中的第2日数据要在第5(2+3)日结束后才会过期,所以到6日开始时,12日的数据文件才会被删掉。这样一来,在5日和6日之间的时间段内,就会出现12日,34日,5日三个文件共存的现象。

以上就是官方文档上所说的:“给定days与keep两个参数,一个典型工作状态的vnode中总的数据文件数为:向上取整(keep/days)+1个”的真正意思。

所以,只要你的vnode目录下的文件数目符合上面的两种场景的结果,那么就没必要担心自动删除机制没有正常工作。

看到这里的读者,现在你了解了TDengine的自动删除机制了吗?如果还没有,那一定是我的失职了。