C# 如何在同一集合的多个MongoDB观察程序之间分配工作负载?

C# 如何在同一集合的多个MongoDB观察程序之间分配工作负载?,c#,mongodb,C#,Mongodb,我想知道是否可以为一个集合启动多个观察者 在我的例子中,我启动了多个线程来监视一个集合,但是mongo会将相同的文档返回给所有观察者 如何让MongoDB在这些已启动的线程之间拆分文档负载 螺纹起动器: for (var i = 0; i < 4; i++) { ThreadMongoDB thWork = new ThreadMongoDB(_config, _serviceProvider); thWork

我想知道是否可以为一个集合启动多个观察者

在我的例子中,我启动了多个线程来监视一个集合,但是mongo会将相同的文档返回给所有观察者

如何让MongoDB在这些已启动的线程之间拆分文档负载

螺纹起动器:

    for (var i = 0; i < 4; i++)
    {
                ThreadMongoDB thWork = new ThreadMongoDB(_config, _serviceProvider);
                thWork.ThreadName = "TH-" + i.ToString();

                Thread th = new Thread(thWork.Process);

                await Task.Run(() =>
                {
                    th.Start();
                });
    }
for(变量i=0;i<4;i++)
{
ThreadMongoDB thWork=新的ThreadMongoDB(_config,_serviceProvider);
thWork.ThreadName=“TH-”+i.ToString();
螺纹th=新螺纹(thWork.Process);
等待任务。运行(()=>
{
th.Start();
});
}
ThreadMongoDB类中的代码:

public class ThreadMongoDB
    {
        readonly IMongoDatabase _db;
        readonly Executer _exec;

        public string ThreadName { get; set; }


        public ThreadMongoDB(IConfiguration iconfig, IServiceProvider serviceProvider)
        {
            var typeConn = iconfig["TypeConn"];
            var client = new MongoClient(iconfig[$"{typeConn}:cnnMain"]);
            _db = client.GetDatabase(iconfig[$"{typeConn}:dbMain"]);

            _exec = new Executer(iconfig, serviceProvider);
        }

        public void Process()
        {
            var options = new ChangeStreamOptions() { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup };

            var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<WorkerQueue>>()
                .Match("{ operationType: { $in: [ 'replace', 'insert', 'update' ] }}");
                //.Match("{ $or: [ {operationType: 'replace' }, { operationType: 'insert' }, { operationType: 'update' } ] }");

            using (var pilotQueueStream = _db.GetCollection<WorkerQueue>("one_queue_pilot")
                .Watch(pipeline, options).ToEnumerable().GetEnumerator())
            {
                while (true)
                {
                    pilotQueueStream.MoveNext();

                    WorkerQueue currentReg = pilotQueueStream.Current.FullDocument;

                    if (currentReg != null)
                    {
                        if (!currentReg.boolDone)
                        {
                           _exec.Execute(ThreadName, currentReg);
                        }
                    }
                }
            }
        }
    }
}
公共类ThreadMongoDB
{
只读IMongoDatabase_db;
只读执行器_exec;
公共字符串ThreadName{get;set;}
public ThreadMongoDB(IConfiguration iconfig,IServiceProvider服务提供商)
{
var typeConn=iconfig[“typeConn”];
var client=newmongoclient(iconfig[$”{typeConn}:cnnMain“]);
_db=client.GetDatabase(iconfig[$”{typeConn}:dbMain“]);
_exec=新的执行器(iconfig,serviceProvider);
}
公共程序()
{
var options=new ChangeStreamOptions(){FullDocument=ChangeStreamFullDocumentOption.UpdateLookup};
var pipeline=new EmptyPipelineDefinition()
.Match(“{operationType:{$in:['replace','insert','update']}”);
//.Match(“{$or:[{operationType:'replace'},{operationType:'insert'},{operationType:'update'}]}”);
使用(var pilotqueestream=\u db.GetCollection(“一个队列\u导频”)
.Watch(管道,选项).ToEnumerable().GetEnumerator())
{
while(true)
{
pilotQueueStream.MoveNext();
WorkerQueue currentReg=pilotQueueStream.Current.FullDocument;
如果(currentReg!=null)
{
如果(!currentReg.boolDone)
{
_exec.Execute(ThreadName,currentReg);
}
}
}
}
}
}
}
我想知道是否可以为一个集合启动多个观察者

在我的例子中,我启动了多个线程来监视一个集合,但是mongo会将相同的文档返回给所有观察者

这是预期的结果:您可以有多个变更流处于活动状态,但每个流都是独立的,并且观察者之间没有协调。观看相同的流将导致相同的事件

如何让MongoDB在这些已启动的线程之间拆分文档负载

此要求必须在您的应用程序中处理

如果观察者正在为更改流事件做重要的处理,并且希望分配工作负载,则需要考虑的一些方法是:

  • 让变更流观察者将事件推送到中心,以便多个工作线程可以声明和处理队列中的作业。这是一种典型的批处理模式

  • 让每个观察者包括一个
    $match
    阶段,该阶段过滤要处理的变更流事件的不同子集。这种方法需要一些计划来确保事件不会重叠,并且如果某些事件类型需要比其他类型更多的工作人员,那么这种方法的可伸缩性就会降低


在实施这两种方法之前,肯定值得确认您的工作负载需要更多的工作人员/线程。

谢谢您的回答。在实现watcher之前,我正在使用find()阅读这个工作队列。第一个命令有多个线程,但后来我发现这些监视程序将触发进程,而不必将集合集中起来。因此,我将保留一个观察者,如果卷增加,我将返回到使用多个线程读取集合。非常感谢你。