考虑到磁盘 i/o 比率,在 Mongo DB 中使用 TTL 索引的最佳策略是什么。
前言:
我在集群 mongodb (v2.*) 基础架构上工作,其中每个节点都有大约 1TB 的硬盘。在那里,日志信息会保存 7 天。在那之后,它们不再需要并且应该被删除。有 6 个数据库,每个数据库有 10 个集合,每个集合超过 1000 万个文档。假设我们每天要存储 100GB 的临时数据。
因此,我在 createdAt 字段上创建了一个简单的索引。
db.my_collection.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 604800, background : true });
这将在时间戳记 7 天后删除所有插入此集合的文档createdAt
。这对我来说很清楚。但我不确定如何创建将保存到集合中的文档。
背景索引的 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”“过期”。
临:
- 每天午夜后不久,磁盘使用量应减少 100GB。
- 您可以轻松查看是否存在错误。如果磁盘使用量没有下降,就会出现问题。
缺点:
- 删除 100GB 的数据将导致巨大的磁盘 io 并可能减慢其他进程。
- 由于缺少小时和分钟,这些文件的保存时间不到 7 天。
选项 2:
'createdAt' => new MongoDate(strtotime(date('Y-m-d h:i:s')))
在这里,所有创建的文档都有不同的创建时间,例如“2015-04-09 13:23:45”。这意味着此示例文档将在“2015-04-16 13:23:45”“过期”。
临:
- 文档将准确保存 7 天。
- 磁盘 io 将在一整天内几乎保持不变。干扰其他进程的可能性较小。
缺点:
- 查看是否有错误不像选项 1 那样容易,因为文档将在一天中被删除。磁盘使用量不会有很大的跳跃。
(选项 3):
我认为这应该与选项 2 相同。不过我想在这里提一下。
我们还可以将索引更改为在特定时间后但在特定日期不过期。
db.my_collection.ensureIndex( { "deleteAt": 1 }, { expireAfterSeconds: 0, background : true });
然后以这种方式创建对象:
'deleteAt' => new MongoDate(strtotime("+7 days")),
你认为最好的可能性是什么?有没有人遇到过这样的问题/基础设施?我很想从经验丰富的 mongodb 开发人员那里得到一些反馈。