乐趣区

关于mongodb:通过mongodb-TTL机制让集合中的数据自动过期删除

MongoDB 的汇合有衣蛾 TTL (即 time to live,即生存的工夫) 的个性。TTL 能够让 mongodb 主动移除过期了的数据,(咦,这岂不是正好合乎日志类的数据诉求)。这种机制便比拟适宜一些 日志数据 机器产生的事件数据 甚至能够用来做 session 会话

MongoDB 通过一个 TTL 索引来实现这种所谓的 TTL 汇合。该个性的实现机制是:mongod 通过一个后盾线程去一直的读取汇合中某个日期类型的索引,并且移除掉满足过期条件的文档 documents。

上面咱们来看如何实操:

创立 TTL 索引

咱们是通过 db.collection.createIndex() 命令配合 expireAfterSeconds 选项来对汇合中某个字段做 TTL 索引。这个字段必须是 date 类型或者是一个蕴含 date 类型值的数组字段。

创立 TTL 过期规定的话,有 2 种模式:

  • 一种是相似于前端的 maxAge 模式,即设置一个时长,当 mongodb 发现以后工夫与工夫索引字段的时差超过了 maxAge,则认为过期
  • 另一种是相似前端的 expireTime 模式。即设置一个过期工夫点,当 mongodb 发现以后零碎工夫曾经超过那个工夫点,则认为记录过期

上面咱们别离看下两种模式的设置形式。

在一个特定的时长之后删除文档

如果咱们 db 中有一个 logs 的汇合,其中的记录格局为:

{
    "_id": "5f43d5c00b34962beb026aad",
    "createdAt": Date(),
    "requestTime": 1598281152423,
    "reportId": "1598281152423-6245975993217447",
}

接下来,咱们针对 createdAt 这个字段建设一个 TTL 索引:

db.logs.createIndex({"createdAt": 1}, {expireAfterSeconds: 3600})

其中 createdAt: 1 示意对 createdAt 字段建设正序的索引。选项 expireAfterSeconds 示意 3600 秒(即 1 小时) 之后过期。其含意是,在 createdAt 字段的值的时刻根底上,再加上 3600 秒 之后的那个工夫过期。

测试一把。我让过期工夫是 10 秒,做了下测试,以下是测试后果:

在一个特定的工夫点来删除文档

有时候,咱们不心愿在文档创立时刻之后的多少秒再删除。而是心愿在每天凌晨某个时刻(例如避开用户的拜访高峰期) 进行日志删除。因而,咱们心愿给文档指定一个特定的过期工夫点。这种规定,mongodb 也是能够设置的。咱们在创立 TTL 索引时,只需把 expireAfterSeconds 配置的值设为 0 即可.

当然,为了咱们的索引字段能够 顾名思义,因而咱们从新设计一下数据源(例如咱们把这个 TTL 索引字段取名叫做 expireDeleteTime)。

数据记录的构造当初如下所示:

{
    "_id": "5f43d5c00b34962beb026aad",
    "expireDeleteTime": ISODate("2020-09-02T11:44:11.528Z"),
    "requestTime": 1598281152423,
    "reportId": "15982811524236245975993217447",
}

而后,咱们创立 expireDeleteTime 字段的 TTL 索引,办法如下:

db.logs.createIndex({"expireDeleteTime": 1}, {"expireAfterSeconds": 0})

这样咱们就把 expireDeleteTime 字段配置为 TTL 索引,其 expireAfterSeconds 是 0,因而这意味着 mongodb 将用索引字段【expireDeleteTime 里的工夫值 加 0 秒 后的工夫】作为判断根据,此时的判断根据其实就是 expireDeleteTime 字段自身。

此时,咱们向库中插入一条以后工夫的记录(这意味着该记录将会马上过期)。而后我一直的查问汇合,看到后果如下:

最终,数据记录被主动删除了。然而实际上我插入的这条数据应该在插入的那一刻就过期了(因为其 expireAfterSeconds 工夫是此刻),但能够发现 mongodb 并不是立即删除该数据的,而是在大略 60 秒之后才删除,这是因为 mongodb 后盾线程的检测距离是 60 秒。

第二种过期模式对咱们的日志数据来说,是很有价值的。咱们能够在每条记录入库的时候,就给他增加一个 expireTime 字段,用来标记该记录的过期工夫。例如咱们冀望保留日志记录 15 天,则能够借用 moment 类库这样做:

// 计算出过期工夫点
const expireTime = moment().add(15, 'days').endOf('day')

// 将过期工夫点和日志数据入库
db.insert({
    expireTime,
    ...logData
})

MongoDB 将主动删除汇合中 expireTime 字段晚于以后工夫的记录。因而,能够实现日志 15 天后主动删除的成果。

总结

  • MongoDb 能够通过创立 TTL 索引的形式实现过期数据删除
  • 当把索引配置项 expireAfterSeconds 即过期时长设置为 0 秒,也就实现了灵便设定文档的过期工夫的目标。
退出移动版