【发布时间】:2011-01-12 17:40:48
【问题描述】:
我最近一直在使用 GitHub 上的 C# 驱动程序玩 MongoDB(速度非常快)。在我正在测试的小型单线程控制台应用程序中,一切正常。我能够在运行单线程的 8 秒内添加 1,000,000 个文档(是的,百万个)。如果我在 for 循环范围之外使用连接,我只会获得这种性能。换句话说,我为每个插入保持连接打开,而不是为每个插入连接。显然这是人为的。
我想我会把它提高一个档次,看看它是如何与多线程一起工作的。我这样做是因为我需要模拟一个具有多个并发请求的网站。我在 15 到 50 个线程之间旋转,在所有情况下仍然插入总共 150,000 个文档。如果我只是让线程运行,每个线程为每个插入操作创建一个新连接,性能就会停止。
显然我需要找到一种方法来共享、锁定或池化连接。问题就在于此。连接到 MongoDB 的最佳实践是什么?连接是否应该在应用程序的整个生命周期内保持打开状态(每次操作打开和关闭 TCP 连接都有相当长的延迟)?
是否有人对 MongoDB 有任何实际或生产经验,特别是底层连接?
这是我的线程示例,它使用为插入操作而锁定的静态连接。请提供可以在网络环境中最大限度地提高性能和可靠性的建议!
private static Mongo _mongo;
private static void RunMongoThreaded()
{
_mongo = new Mongo();
_mongo.Connect();
var threadFinishEvents = new List<EventWaitHandle>();
for(var i = 0; i < 50; i++)
{
var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
threadFinishEvents.Add(threadFinish);
var thread = new Thread(delegate()
{
RunMongoThread();
threadFinish.Set();
});
thread.Start();
}
WaitHandle.WaitAll(threadFinishEvents.ToArray());
_mongo.Disconnect();
}
private static void RunMongoThread()
{
for (var i = 0; i < 3000; i++)
{
var db = _mongo.getDB("Sample");
var collection = db.GetCollection("Users");
var user = GetUser(i);
var document = new Document();
document["FirstName"] = user.FirstName;
document["LastName"] = user.LastName;
lock (_mongo) // Lock the connection - not ideal for threading, but safe and seemingly fast
{
collection.Insert(document);
}
}
}
【问题讨论】:
-
你最后做了什么决定?面临同样的问题...
-
好消息是我不必做决定。 Mongodb-csharp 和 NoRM 驱动程序都添加了对连接池的支持。这两个库都有精心设计的线程安全机制,用于针对 mongod 或 mongos 进程池连接。这两个领域也在不久的将来增加了对副本集的支持。
-
@TylerBrinks 你能举例说明如何在 8 秒内插入 1m 个文档吗?我无法在单线程上达到那个速度。
标签: c# mongodb performance connection-pooling mongodb-.net-driver