Какова наилучшая стратегия использования индекса TTL в БД Mongo с учетом соотношения дискового ввода-вывода.
Я работаю в кластерной инфраструктуре mongodb (v2. *), Где каждый узел имеет около 1 ТБ жесткого диска.
Там информация о регистрации сохраняется в течение 7 дней. По истечении этого времени они не нужны и должны быть удалены. Существует 6 баз данных с 10 коллекциями в каждой и более 10 миллионов документов на коллекцию. Давайте предположим, что мы храним 100 ГБ временных данных каждый день.
Поэтому я создал простой индекс в поле createAt.
db.my_collection.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 604800, background : true });
Это удалит все документы, вставленные в эту коллекцию, через 7 дней после отметки времени, которая была введена в createdAt
, Это ясно для меня. Но я не уверен, как создавать документы, которые будут сохранены в коллекции.
Документы Монго для фоновых индексов гласят:
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».
Pro:
Минусы:
Вариант 2:
'createdAt' => new MongoDate(strtotime(date('Y-m-d h:i:s')))
Здесь все созданные документы будут иметь разное время создания, например, «2015-04-09 13:23:45».
Это означает, что срок действия этого образца документа будет истек «2015-04-16 13:23:45».
Pro:
Минусы:
(Вариант 3):
Я думаю, что это должно быть так же, как вариант 2. Тем не менее, я хотел бы упомянуть об этом здесь.
Мы также можем изменить индекс так, чтобы он не истекал через определенное время, а на определенную дату.
db.my_collection.ensureIndex( { "deleteAt": 1 }, { expireAfterSeconds: 0, background : true });
А затем создайте объект следующим образом:
'deleteAt' => new MongoDate(strtotime("+7 days")),
Как вы думаете, это лучшая возможность? У кого-нибудь был опыт с такой проблемой / инфраструктурой? Я хотел бы получить отзывы от опытных разработчиков mongodb.
отказЯ ни в коем случае не разработчик PHP, поэтому я не могу дать вам никакого кода PHP.
Проблема здесь в том, что вы хотите удалить все данные в начале дня. Поэтому, когда задача TTL запускается впервые после 00:00, она пытается удалить все документы, как вы написали
Однако ваши предположения не совсем точны. Если запись в журнале была сделана сегодня в 16:00, точной датой истечения срока хранения с недельным хранением (604800 секунд) будет четверг, 16 апреля 2015 г. в 16:00.
Таким образом, самый простой способ распределить дисковый ввод-вывод в течение 1440 запусков фонового процесса TTL — это использовать не только дату в качестве ссылки, но и время.
Тем не менее, вполне возможно, что вы хотите дисплей только записи за последние шесть дней плюс сегодняшние. Это легко достижимо с помощью ограничения результатов в запросах. Учитывая структуру документа, как
{
_id: <SomeObjectId>,
entry: "Something happened!"createdAt: ISODate("2015-04-02T09:11:27.038Z")
}
Вы сможете выбрать все соответствующие записи так же просто, как
db.logentries.find({createdAt:{$gt:ISODate("2015-04-03T00:00:00.000Z") } })
который будет возвращать все записи шесть дней назад с сегодняшнего дня плюс сегодня. Очевидно, что в этом случае вы должны сделать некоторые вычисления даты.
Других решений пока нет …