考虑到 ttl 和磁盘 i/o 创建 mongo 文档的最佳方式

Optimal way to create mongo documents with a ttl and disk i/o in mind

考虑到磁盘 i/o 比率,在 Mongo 数据库中使用 TTL 索引的最佳策略是什么。

前言:

我在集群 mongodb (v2.*) 基础设施上工作,其中每个节点都有大约 1TB 的硬盘。 在那里,日志信息会保存 7 天。在那之后,它们就不再需要了,应该被删除。有 6 个数据库,每个数据库有 10 个馆藏,每个馆藏超过 1000 万份文件。假设我们每天存储 100GB 的临时数据。

因此我在 createdAt 字段上创建了一个简单的索引。

  db.my_collection.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 604800, background : true });

这将删除在放入 createdAt 的时间戳后 7 天插入此集合的所有文档。这对我来说很清楚。但我不确定如何创建将保存到集合中的文档。

后台索引的 mongo 文档状态:

The background task that removes expired documents runs every 60 seconds.

问题:

在考虑将来删除的同时,创建该 TTL 索引的最佳方法是什么。

例如 这里有 3 种方法可以创建要保存的对象。我使用的语法是 php 但这并不重要。

选项 1:

   'createdAt' => new MongoDate(strtotime(date('Y-m-d')))

此处将保存今天创建的所有文档,创建时间为例如“2015-04-09 00:00:00”。 这意味着所有文档都将在“2015-04-16 00:00:00”上 "expired"。

亲:

缺点:

选项 2:

   'createdAt' => new MongoDate(strtotime(date('Y-m-d h:i:s')))

在这里创建的所有文档都将有不同的创建时间,例如“2015-04-09 13:23:45”。 这意味着此示例文档将在“2015-04-16 13:23:45”上 "expired"。

亲:

缺点:

(选项 3):

我想这应该和选项2一样。不过我想在这里提一下。

我们还可以将索引更改为在特定时间后但在特定日期不会过期。

db.my_collection.ensureIndex( { "deleteAt": 1 }, { expireAfterSeconds: 0, background : true });

然后这样创建对象:

'deleteAt' => new MongoDate(strtotime("+7 days")),

你认为最好的可能性是什么?有没有人有过这样的经验 problem/infrastructure ?我很想从经验丰富的 mongodb 开发人员那里得到一些反馈。

免责声明:我绝不是PHP开发者,所以我不能给你任何PHP代码。

这里的问题是你想删除一天开始时的所有数据。因此,当 TTL 任务在 00:00 之后第一次运行时,它会尝试删除所有文档,正如您所写的那样

但是,您的假设并不十分准确。如果日志条目是今天 16:00 创建的,那么保留一周(604800 秒)的确切到期日期将是 2015 年 4 月 16 日星期四 16:00 .

因此,将磁盘 IO 分散到 TTL 后台进程的 1440 次运行中的最简单方法是不仅使用日期作为参考,还使用时间作为参考。

但是,您很可能只想显示 过去六天加上今天的条目。这很容易通过限制查询中的结果来实现。给定一个文档结构,如

{
  _id: <SomeObjectId>,
  entry: "Something happened!"
  createdAt: ISODate("2015-04-02T09:11:27.038Z")
}

您可以select所有相关条目就像

一样简单
db.logentries.find({createdAt:{$gt:ISODate("2015-04-03T00:00:00.000Z") } })

这将 return 从现在开始六天前的所有条目加上今天的条目。显然,在这种情况下你必须做一些日期计算。