【MongoDB】数据的自动过期,TTL索引

文章目录

1. 前言

在近期的工作中,使用了MongoDB来保存了一些日志数据,但是这些日志数据具有一定的时效性,也就是按照业务的需要,保存xx天即可,在超过了这个时间之后,需要删除过时的日志。

按照之前的做法,可以使用定时任务,例如:Spring的定时器,xxl-job等工具,在每天凌晨的时候删除数据,这种方法虽然可行,但是需要额外的编码工作。

那有没有一种方式能够简单的搞定过期数据的清理呢?

当然,MongoDB提供了一种TTL索引的机制,可以非常方便的处理这种需求,下面是官方文档,有阅读能力的同学可以直接看这个文档。
《Expire Data from Collections by Setting TTL》

2.概念与使用

TTL的全称为 "Time To Live ",就是存活时间的意思,这是计算机中一个非常常见的概念,经常用于一些需要延时处理的任务,熟悉消息队列的同学肯定知道,延时队列实际上也是TTL的一种实践方式。

结合这个概念,MongoDB通过给数据创建TTL Index 也就是TTL索引的方式,在完成数据的过期和清理的任务。

2.1.使用方式

TTL Index 的使用方法的非常简单,只需要找到一个 日期类型 字段,给这个字段创建索引,并指定存活时间(expireAfterSeconds)就可以了。

我这里使用的MongoDB版本是最新的7.0.6,可以通过db.version();查看当前的版本号,太低的版本可能不支持这个功能。


先准备一条数据,然后创建索引:

js 复制代码
db.log_test.insertOne({
   "createTime": new Date(),
   "msg": "Success!"
})

db.log_test.find();
js 复制代码
db.log_test.createIndex({ "createTime": 1 }, { expireAfterSeconds: 10 });

db.log_test.getIndexes();

这里的expireAfterSeconds设置的是存活时间,单位:秒,在设置完成后,createTime与当前系统时间的差值大于 10s 的数据,将会被清理掉。是不是非常简单。

2.2.数组中包含日期字段

在上面已经创建索引的基础上, 看一下下面这个语句:

js 复制代码
db.log_test.insertOne({
   "createTime": [new Date(),'asdf',111],
   "msg": "Success!"
});

猜一下,这样的数据还能够被自动清理吗?

实际上,这种数据会可以被自动清理的,即使字段值是一个数组,但它包含了日期类型的字段,TTL索引都能够生效。

那再进一步,如果数组中包含了多个日期字段呢?该使用哪一个日期呢?例如:

js 复制代码
db.log_test.insertOne({
   "createTime": [new Date,ISODate("2024-04-20T13:48:18.428Z")],
   "msg": "Success!"
});

这种情况,数据也会在10秒后被删除掉。无关乎日期的大小,只要有任意一个日期满足过期的要求,就可以被删掉。

2.3.设置具体的过期时间点

上面说的都是设置一个数据的存活时间,不是固定的过期时间,如果想要设置固定的过期时间也非常简单,只需要把索引做一下变换。

js 复制代码
db.log_test.createIndex({ "expireTime": 1 }, { expireAfterSeconds: 0 });

expireAfterSeconds设置为0,然后在expireTime字段上设置具体的时间就可以了。

2.4.额外的过滤条件

上述的情况都是针对全量的数据做过期处理,但可能有的时候我们可能想保留有些有价值的数据,这部分数据不加入自动过期的逻辑。这个时候可以在创建索引的时候加入部分过滤条件,如下:

js 复制代码
db.log_test.createIndex(
    {"createTime": 1},
    {
        name:"canExpireDataTTL",
        partialFilterExpression:{"canExpire":true}, // canExpire=true的字段会过期自动清理
        expireAfterSeconds: 10
    }
);

接下来插入两条数据:

js 复制代码
db.log_test.insertOne({
   "createTime": [new Date()],
   "msg": "Success!",
   "canExpire":true
});

db.log_test.insertOne({
   "createTime": [new Date()],
   "msg": "Success!",
   "canExpire":false
});

按照预期,在10秒后,canExpiretrue的数据将会被清理,false的数据将会保留。验证结果如下:

3.总结

TTL索引可以在不添加新的代码逻辑的情况下,非常简单清理已过期的数据,只需要在日期类型的字段上创建TTL Index就可以了,即使这个字段是数组,只要数组中有日期也可能生效。

需要注意的是:过期数据的清理工作是由MongoDB的后台线程周期性执行的,一般这个周期是60s执行一次 ,如果发现上述的数据在 10秒后还没有被删除的话也不用惊慌,数据将会在60s的周期内被清理掉。

相关推荐
vvvae123421 分钟前
分布式数据库
数据库
雪域迷影41 分钟前
PostgreSQL Docker Error – 5432: 地址已被占用
数据库·docker·postgresql
bug菌¹1 小时前
滚雪球学Oracle[4.2讲]:PL/SQL基础语法
数据库·oracle
逸巽散人2 小时前
SQL基础教程
数据库·sql·oracle
月空MoonSky2 小时前
Oracle中TRUNC()函数详解
数据库·sql·oracle
momo小菜pa2 小时前
【MySQL 06】表的增删查改
数据库·mysql
向上的车轮3 小时前
Django学习笔记二:数据库操作详解
数据库·django
编程老船长3 小时前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
全栈师4 小时前
SQL Server中关于个性化需求批量删除表的做法
数据库·oracle
Data 3174 小时前
Hive数仓操作(十七)
大数据·数据库·数据仓库·hive·hadoop