如何在C#中正确使用MongoClient实现跨服务器数据迁移
正确使用MongoClient实现跨MongoDB服务器数据迁移
核心原则:不同环境各自单例化MongoClient
MongoClient的单例建议是针对同一个MongoDB集群/环境而言的——它内部维护了连接池,重复创建会导致资源浪费、连接数超限。跨PROD/UAT这种不同环境时,需要为每个环境单独维护一个单例的MongoClient实例,而非全局共用一个。
优化后的迁移流程与实现
1. 单例化MongoClient实例
用懒加载方式为每个环境创建唯一的MongoClient,确保连接池只初始化一次:
public static class MongoClients { // PROD环境客户端单例 private static readonly Lazy<MongoClient> _prodClient = new Lazy<MongoClient>(() => new MongoClient(Environment.GetEnvironmentVariable("PROD_MONGO_CONN"))); // UAT环境客户端单例 private static readonly Lazy<MongoClient> _uatClient = new Lazy<MongoClient>(() => new MongoClient(Environment.GetEnvironmentVariable("UAT_MONGO_CONN"))); public static MongoClient Prod => _prodClient.Value; public static MongoClient Uat => _uatClient.Value; }
2. 高效数据迁移逻辑
避免一次性加载全量数据到内存,采用分页查询+批量Upsert的方式,降低内存占用并提升效率:
public async Task RunDataMigrationAsync(string sourceDb, string sourceColl, string targetDb, string targetColl) { var prodColl = MongoClients.Prod.GetDatabase(sourceDb).GetCollection<BsonDocument>(sourceColl); var uatColl = MongoClients.Uat.GetDatabase(targetDb).GetCollection<BsonDocument>(targetColl); const int batchSize = 1000; int skip = 0; long batchCount; do { // 分页拉取PROD数据 var dataBatch = await prodColl.Find(new BsonDocument()) .Skip(skip) .Limit(batchSize) .ToListAsync(); batchCount = dataBatch.Count; if (batchCount == 0) break; // 构造批量Upsert操作 var bulkOperations = dataBatch.Select(doc => new ReplaceOneModel<BsonDocument>( new BsonDocument("_id", doc["_id"]), doc) { IsUpsert = true }); // 执行批量写入 await uatColl.BulkWriteAsync(bulkOperations); skip += batchSize; } while (batchCount == batchSize); }
关键注意事项
- 敏感信息管理:连接字符串通过环境变量/配置文件存储,禁止硬编码
- 异常处理:添加重试机制(如Polly)处理网络波动、连接超时等问题,避免迁移中断
- 数据校验:迁移完成后可抽样对比PROD与UAT的数据,确保一致性
- 脚本场景适配:如果是一次性执行的迁移脚本,单例依然有效——初始化一次连接池比多次创建更高效,脚本退出时连接池会自动释放资源
内容的提问来源于stack exchange,提问作者Gen.L
相关产品推荐
相关产品推荐

