Java8 数据库请求的流式或反应式/观察器

Java8 Stream or Reactive / Observer for Database Requests

我正在重新考虑我们的 Spring MVC 应用程序行为,是从数据库中 pull (Java8 Stream) 数据还是让数据库更好push (Reactive / Observable) 它是数据并使用背压来控制数量。


现状:

  1. User 请求 30 篇最新文章
  2. Service 执行数据库查询并将 30 个结果放入 List
  3. Jackson 遍历 List 并生成 JSON 响应

为什么要切换实现?

这非常耗费内存,因为我们一直将这 30 个对象保存在内存中。这不是必需的,因为应用程序一次处理一个对象。虽然应用程序应该能够检索一个对象、处理它、丢弃它并获取下一个对象


Java8 流? (拉)

使用 java.util.Stream 这很容易:Service 创建一个 Stream,它在后台使用数据库游标。每次 JacksonStream 的一个元素写入 JSON 字符串时,它会请求下一个,然后触发数据库游标到 return 下一个条目。


RxJava/响应式/可观察? (推)

这里我们有相反的情况:数据库必须逐个条目推送并且 Jackson 必须为每个元素创建 JSON 字符串,直到 onComplete 方法被调用.

Controller 告诉 Service给我一个 Observable<Article>。然后 Jackson 可以请求尽可能多的数据库条目。


分歧与关注:

使用 Streams 请求下一个数据库条目和检索/处理它 之间总会有一些延迟。如果网络连接速度慢或必须发出大量数据库请求才能完成响应,这可能会减慢 JSON 响应时间。

使用RxJava应该总是有数据可供处理。如果太多,我们可以使用背压来减慢从数据库到应用程序的数据传输。在最坏的情况下,buffer/queue 将包含 所有 请求的数据库条目。那么内存消耗将等于我们当前使用 List.

的解决方案

我为什么要问/我在问什么?

您似乎在谈论底层数据库引擎的提取大小。

如果将其减少到一个(一次获取和处理一行),是的,您将在请求时间内节省一些 space...

但是拥有合理的块大小通常是有意义的。 如果它太小,你将有很多昂贵的网络往返。如果块大小太大,您将面临 运行 内存不足的风险,或者每次提取都会引入过多的延迟。所以这是一种妥协,正确的 chunk/fetch 大小取决于您的具体用例。

关于反应式与否,我认为这无关紧要。与 RxJava 和 Cassandra 一样,可以从异步结果集创建一个 Observable,这取决于查询(配置)一次应该获取和推送多少项。