Spring Data MongoDB Reactive - 如何处理大量文档的findAll查询?

3
假设我有一个定义如下的ReactiveMongoRepository

```

@Repository
interface MyRepo extends ReactiveMongoRepository<MyDTO, String> {}

假设仓库中包含大量MyData文档(至少数十万个),您执行一个简单的"findAll()",然后进行删除:

myRepo.findAll()
      .doOnNext( myDto -> {
            System.out.println(myDto.message);
      })
      .flatMap( myDto -> {
            myRepo.deleteById(myDto.id);
      })

这将大致每月执行一次。

在流式处理大数据集时,使用Spring Data / MongoDB是否安全?或者建议使用某种批处理或分页来避免游标等问题?

1个回答

1
一般来说,这要看情况而定,但在我看来,至少不是以你提出的方式。首先,我认为对于所有集合进行查找操作是没有多大意义的。我假设很难找到需要处理数十万个数据的用例,假设你已经实现了一个数据摄取管道,你可以处理无限的数据流,但对于这种用例,我建议使用更适合的架构,比如使用Spring Cloud Stream和Kafka进行流式处理。问题不在于能否处理很多数据,因为MongoDB的响应式驱动非常高效,通过调整反向压力机制,你应该可以保护好你的服务器,但如果你要在流中重复使用find all,那么这样的数据流太大了,几乎不可行。如果你要处理数据流,使用Spring Cloud Stream等消息中间件可能是最好的选择,想象一下你发起了一个find all请求,你的服务器和Mogno可能会很好地完成,但是你的用户将等待很长时间,直到请求完成,否则,如果用例是离线过程,如前所述,用于处理无限数据流的Spring Cloud Stream可能是最佳选择。
更新:考虑到每月运行一次的批处理用例,情况变化很大。

阅读Spring数据响应式mongo的代码,我发现:

@NoRepositoryBean
public interface ReactiveMongoRepository<T, ID> extends ReactiveSortingRepository<T, ID>, ReactiveQueryByExampleExecutor<T> {
....
}

代替

@NoRepositoryBean
public interface MongoRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
...
}

注意的关键点在于响应式版本的仓库实际上没有分页功能,事实上基础接口的名称中也不包含Paging这个词,这里关键的是技术类型。
在阻塞IO中,分页对于模型每个请求一个线程是必要的,因此阻塞模式对于数据库应用程序和繁忙的连接和客户端查询都很危险,容易出现超时、负载等问题,而将查询分页可以帮助减轻系统负担。但在非阻塞IO中,行为是不同的,您正在连接到数据流,驱动程序是非阻塞驱动程序,您不使用传统的mongo驱动程序,Spring Data使用专门的反应式mongo驱动程序,它是针对这项工作进行了优化,并基于事件循环模型。
说到这里的关键点是,对于离线处理而言,使用一个io密集型模型可能并不那么有用,我是指,使用反应式模型对于主要是io绑定和高流量的软件是有用的,该模型支持高并发。但是,如果您的用例是每月一次的干净收集,我想使用反应式编程可能是安全的,因为它被设计用于支持io密集型用例,但在这种情况下,传统的批量阻塞io模型与分页是更合适的方法。关键点是我认为驱动程序应该是安全的,它被设计用于管理高流量和流媒体用例中的大量数据,但在批量用例中使用这种方法是无用的。

希望能对您有所帮助


也许我应该补充说明,这是每月一次的操作,并且在读取每个文档后(例如在控制台上打印)它将被删除。 - Johan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接