Если вы молоды и энергичны интересуетесь mongoDb, хотите подискутировать на тему перевода слова tailable на русский, и вас интересует откуда взята пикрелейтед — добро пожаловать под кат.
Некоторое время назад, делая админку для одного небольшого проекта, я подумал, что неплохо бы выводить в ней лог некоторых значимых событий. Память услужливо напомнила об одной из возможностей MongoDb, о которой я слышал, но ни разу не применял на практике — хвостовые (tailable) курсоры.
Что за зверь?
По умолчанию монго автоматически закрывает соединение, после того как клиент получит все доступные курсору данные. Для ограниченных (capped) коллекций возможно дополнительное поведение, так называемые хвостовые курсоры.
Хвостовые курсоры остаются открытыми и продолжают получать новые данные, удовлетворяющие поисковому критерию. Их действие напоминает хорошо всем знакомый tail -f. Монго использует хвостовые курсоры для слежения за opplog`ом.
То что надо, подумал я
new Thread(new Runnable() {
@Override
public void run() {
DBCollection collection=MongoConnector.getInstance().getCollection("events");
//Магия в addOption
DBCursor cur= collection.find().addOption(Bytes.QUERYOPTION_TAILABLE).addOption(Bytes.QUERYOPTION_AWAITDATA);
while (cur.hasNext()) {
//Посылаем сообщение всем браузерам, с которыми установлено соединение, там его обработает клиентский JS
wsConnection.broadcast((String) cur.next().get("message"));
}
}
}).start();
Кстати как показала практика — задержка между вставкой нового документа и получением его клиентом по хвостовому курсору, настолько незначительна, что ее впринципе можно и не учитывать.
Ложка дегтя
Официальная документация подсказывает, что использование хвостовых курсоров на коллекциях, с большим количеством операций записи может стать весьма затратным. Если запрос строится по полям, для которых имеется индекс, в случае большого количества записей, лучше использовать обычный курсор, периодически запрашивая новые документы
Как это работает?
Помните выше я написал работа хвостовых курсорами смахивает на работу tail -f? На самом деле сходства тут даже больше чем кажется на первый взгляд.
Когда вы устанавливаете хвостовой курсор и читаете из него данные, дойдя до последнего документа, монго оставляет курсор на нем и следит за дескриптором коллекции, если появляется новый элемент, удовлетворяющий, запросу курсор сдвигается на него.
Для обычных (не ограниченных) коллекций такое поведение невозможно, так как в них порядок хранения документов на диске не всегда соответствует порядку вставки данных.
4 факта о хвостовых курсорах, которые потрясли мир
1)Хвостовые курсоры не используют индексы и возвращают документы том порядке в котором они хранятся на диске. Для ограниченных коллекций порядок размещения всегда совпадает с порядком вставки документов.
2)Поскольку индексы не используются, в начале запроса придется прочитать все записи в коллекции- что при больших объемах данных, может быть весьма затратно. После того как мы уже получили имеющиеся данные, отсеивание не удовлетворяющих запросу вновь добавленных документов не накладно.
3)Хвостовой курсор может стать не валидным (слежения за коллекцией не будет) если
Ни один документ не удовлетворил первоначальному поисковому запросу.
Последний документ был удален, в тот момент когда курсор указывал на него
4) Дохлый курсор имеет ид 0
Автор: sl4mmer