我们目前正在探索MongoDB中的Capped Collections和Tailable Cursors来创建一个通知排队系统.但是,在创建一个简单的
LinqPad测试(下面的代码)后,我们注意到在运行时,Mongo不断分配内存,直到没有更多可用资源,即使我们没有插入任何记录.这种分配一直持续到使用所有系统RAM为止,此时Mongo只是停止响应.
由于我们是Capped Collections和Tailable Cursors的新手,我想确保在提交错误之前我们没有错过任何明显的东西.
>平台:Windows Server 2012 64位
> MongoDB:版本2.4.8 64位
>司机:官方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; } }
解决方法
看来我找到了问题的解决方案!!
Query.EQ("PROCESSED",false)
当我删除它并用基于文档ID的查询替换它时,内存消耗问题消失了.在进一步思考时,查询中不需要这个“PROCESSED”属性作为cursor.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",{ "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["X"].AsString ).Dump(); } else if(cursor.IsDead) { "DONE".Dump(); break; } }