基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

MongoDB的TTL 索引 (Time-To-Live Index)?

知识点图片

MongoDB 的 TTL 索引 (Time-To-Live Index) 是一种特殊的单字段索引,主要用于在指定时间后自动从集合中删除文档

这对于处理临时数据(如日志、会话信息、验证码等)非常有用,无需开发人员编写额外的定时任务(Cron Job)来清理数据。

以下是关于 TTL 索引的详细指南:


1. 核心原理

  • 基于时间字段: TTL 索引必须创建在包含 Date (BSON Date) 类型值的字段上。
  • 后台线程: MongoDB 有一个后台线程(TTL Monitor),默认每 60 秒运行一次。它会扫描 TTL 索引,将文档中的时间字段值与当前时间进行比较,如果过期则删除该文档。

2. 如何创建 TTL 索引

TTL 索引主要有两种使用模式:

模式 A:在创建后的固定时间段后过期

这是最常见的用法。例如,你希望文档在创建后 1 小时(3600秒)自动删除。

步骤:

  1. 文档中需要有一个字段记录创建时间(例如 createdAt)。
  2. 创建索引时指定 expireAfterSeconds 参数。
javascript
// 1. 插入数据时,createdAt 必须是 Date 类型
db.logs.insert({
    "msg": "user login",
    "createdAt": new Date() 
})

// 2. 创建 TTL 索引,指定 3600 秒后过期
db.logs.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

结果:文档将在 createdAt 时间 + 3600 秒后被删除。

模式 B:在指定的具体时间点过期

如果你希望每个文档的过期时间都不一样(例如:优惠券 A 明天过期,优惠券 B 下个月过期)。

步骤:

  1. 文档中包含一个字段表示“过期时间点”(例如 expireAt)。
  2. 创建索引时将 expireAfterSeconds 设置为 0
javascript
// 1. 创建索引,设置 expireAfterSeconds 为 0
db.coupons.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

// 2. 插入数据时,直接指定该文档应该被删除的具体时间
db.coupons.insert({
    "code": "XYZ123",
    "expireAt": new Date("2023-12-31T23:59:59Z") // 在这个时间点删除
})

结果:当当前时间超过 expireAt 字段的值时,文档被删除。


3. 重要限制与注意事项

在使用 TTL 索引前,必须了解以下限制:

  1. 字段类型限制: 索引字段的值必须是 BSON Date 类型(或者是包含 Date 的数组)。如果字段是字符串(String)、数字(Number)或不存在,文档不会被删除。
  2. 单字段索引: TTL 属性通常用于单字段索引。虽然可以在复合索引中使用,但 TTL 属性只对该复合索引中的前导字段(且该字段必须是 Date)生效,这通常不推荐,容易混淆。
  3. 主键限制: 不能在 _id 字段上创建 TTL 索引。
  4. Capped Collections(固定集合): 不能在固定集合上创建 TTL 索引,因为固定集合是根据大小或插入顺序自动覆盖旧数据的。
  5. 删除延迟(非实时):
    • TTL 线程每 60 秒运行一次。
    • 如果数据库负载很高,删除操作可能会排队。
    • 结论: 文档过期后,可能还会保留在数据库中一小段时间(通常是几秒到几分钟)。不要依赖 TTL 索引来实现秒级精度的业务逻辑。

4. 修改过期时间

如果你已经创建了 TTL 索引,但想修改过期时间(例如从 1 小时改为 24 小时),不需要删除重建索引,可以使用 collMod 命令:

javascript
// 将 logs 集合中 createdAt 索引的过期时间修改为 86400 秒 (24小时)
db.runCommand({
  collMod: "logs",
  index: {
    keyPattern: { createdAt: 1 },
    expireAfterSeconds: 86400
  }
})

5. 常见应用场景

  • 用户 Session/Token: 用户登录后 Token 有效期为 7 天,过期自动清理。
  • 短信验证码 (OTP): 验证码 5 分钟内有效,过期自动作废。
  • 临时日志/监控数据: 只保留最近 30 天的系统日志,节省磁盘空间。
  • 购物车数据: 未结账的购物车保留 24 小时。

总结

MongoDB TTL 索引是管理数据生命周期的神器,它简单、自动化且高效。只要记住必须使用 Date 类型以及删除存在一定延迟这两个关键点,就能很好地利用它。

00:00
00:00