Руковдство коллекции MongoDB 2.4.8 и курсор tailable использование всей памяти
в настоящее время мы изучаем ограничен коллекций и Tailable курсоры в MongoDB для создания системы массового обслуживания для уведомлений. Однако после создания простого теста LinqPad (код ниже), который мы заметили при запуске, Mongo постоянно выделяет память, пока не будет больше доступных ресурсов, даже если мы не вставляем никаких записей. Это распределение продолжается до тех пор, пока не будет использована вся системная ОЗУ, и в этот момент Монго просто перестает отвечать.
поскольку мы новички в Capped Коллекции и хвостовые курсоры, я хотел убедиться, что мы не пропустили что-то очевидное перед отправкой ошибки.
Примечание: мы попробовали код ниже с журналированием включения и выключения с теми же результатами.
- платформа: Windows Server 2012 64bit
- MongoDB: версия 2.4.8 64bit
- водитель: официальный C# 10gen v1.8.3.9
помощью linqpad скрипт
var conn = new MongoClient("mongodb://the.server.url").GetServer().GetDatabase("TestDB");
if(!conn.CollectionExists("Queue")) {
conn.CreateCollection("Queue", CollectionOptions
.SetCapped(true)
.SetMaxSize(100000)
.SetMaxDocuments(100)
);
//Insert an empty document as without this 'cursor.IsDead' is always true
var coll = conn.GetCollection("Queue");
coll.Insert(
new BsonDocument(new Dictionary<string, object> {
{ "PROCESSED", true },
}), WriteConcern.Unacknowledged
);
}
var coll = conn.GetCollection("Queue");
var query = coll.Find(Query.EQ("PROCESSED", false))
.SetFlags(QueryFlags.AwaitData | QueryFlags.NoCursorTimeout | QueryFlags.TailableCursor);
var cursor = new MongoCursorEnumerator<BsonDocument>(query);
while(true) {
if(cursor.MoveNext()) {
string.Format(
"{0:yyyy-MM-dd HH:mm:ss} - {1}",
cursor.Current["Date"].ToUniversalTime(),
cursor.Current["X"].AsString
).Dump();
coll.Update(
Query.EQ("_id", cursor.Current["_id"]),
Update.Set("PROCESSED", true),
WriteConcern.Unacknowledged
);
} else if(cursor.IsDead) {
"DONE".Dump();
break;
}
}
2 ответов
Кажется, я нашел решение проблемы!!
проблема в приведенном выше коде вращается вокруг запрос:
Query.EQ("PROCESSED", false)
когда я удалил это и заменил его запросом на основе идентификатора документа, проблема потребления памяти исчезла. При дальнейшем размышлении это" обработанное " свойство действительно не требуется в запросе в качестве курсора.MoveNext () всегда возвращает следующий новый документ (если он есть). Вот переделанный скрипт помощью linqpad на основе приведенный выше код....
var conn = new MongoClient("mongodb://the.server.url").GetServer().GetDatabase("TestDB");
if(conn.CollectionExists("Queue")) {
conn.DropCollection("Queue");
}
conn.CreateCollection("Queue", CollectionOptions
.SetCapped(true)
.SetMaxSize(100000)
.SetMaxDocuments(100)
.SetAutoIndexId(true)
);
//Insert an empty document as without this 'cursor.IsDead' is always true
var coll = conn.GetCollection("Queue");
coll.Insert(
new BsonDocument(new Dictionary<string, object> {
{ "PROCESSED", true },
{ "Date", DateTime.UtcNow },
{ "X", "test" }
}), WriteConcern.Unacknowledged
);
//Create query based on latest document id
BsonValue lastId = BsonMinKey.Value;
var query = coll.Find(Query.GT("_id", lastId))
.SetFlags(QueryFlags.AwaitData | QueryFlags.NoCursorTimeout | QueryFlags.TailableCursor);
var cursor = new MongoCursorEnumerator<BsonDocument>(query);
while(true) {
if(cursor.MoveNext()) {
string.Format(
"{0:yyyy-MM-dd HH:mm:ss} - {1}",
cursor.Current["Date"].ToUniversalTime(),
cursor.Current["X"].AsString
).Dump();
} else if(cursor.IsDead) {
"DONE".Dump();
break;
}
}
то же самое здесь - без этого дополнительного запроса.
после еще нескольких исследований (на самом деле очень много) я найденная проблема выглядит так:
Если первый MoveNext не возвращает запись, проблема существует. Неважно, какой запрос. Не имеет значения, сколько записей в коллекции.
Если вы измените запрос, возвращающий последнюю запись в качестве первой результат все работает нормально. Вы можете отбросить это, как вы знать это уже...
верхний пример успешно, потому что вы получаете изначально все записи уже в коллекции.