【问题标题】:Handle very large throughput with external database使用外部数据库处理非常大的吞吐量
【发布时间】:2019-07-04 03:11:58
【问题描述】:

我正在寻找构建一个 Java11 Spring 启动应用程序。该应用程序用于处理非常大的吞吐量(会有高峰和低流量)

应用程序的快乐路径如下所示。

从概念上讲,它相当简单。步骤大致是这样的

  • 接受传入的 POST 请求。保存端点处的 DTO 对象。
  • 然后应用程序将验证 DTO 并在它无效时返回相关的错误消息。
  • 转换为数据库实体对象
  • 将实体保存到 Postgres 数据库。

我们对这个应用程序的潜在问题是它会为每个请求进行数据库保存,它会保存很多单独的保存。数据库连接池可以快速用完更多的连接。

我的替代方法如下所示

一旦传入的 DTO 通过验证并在内存队列中排队,我希望返回状态 200。
这里没有外部阻塞,如果数据库出现故障 - 这意味着内部队列将提供一些冗余。

所以一些问题/想法

  • 这看起来像一个好方法吗,我应该有什么陷阱吗? 密切注意,提防,小心?
  • 也许您已经以更好的方式解决了类似的问题 / 不同的方法?
  • 反应式流是否有帮助?
  • 我应该为此使用哪些内部 Java 库?我的 是否考虑使用 Java 的 LinkedList Queue<SomeDto> myQ = new LinkedList<SomeDto>(); ) 进行内部排队?

【问题讨论】:

  • 您的整个前提是基于您的连接池连接不足。您是否挑战了这个前提或证实了这确实发生了?数据库通常每秒能够处理多个事务,具体取决于您使用的硬件。此外,如果没有可用的连接,像 Hikari 这样的连接池将默认等待最多 30 秒。如果你不依赖长事务,你应该问问自己增加的复杂性是否值得。

标签: java spring-boot queue high-volume


【解决方案1】:

如果应用因内部队列中的数据而失败,会发生什么?或者如果内存中保存操作溢出?

如果您想构建更健壮的东西,您可以考虑使用消费者填充数据库的事件日志解决方案(例如基于 Kafka)(Kafka 将取代您的内部队列)。

但是,这里很难真正回答您的问题,因为必须考虑许多其他因素。

我建议您阅读像 Designing Data-Intensive Applications 这样的书:它绝对是一个宝贵的资源,它将帮助您根据您的需求和您的背景设计一个可靠的解决方案。

【讨论】:

    【解决方案2】:

    更好的解决方案是拥有一个冗余数据库,以便在其中一个系统出现故障或不可用的情况下,您可以继续使用第二个数据库。

    将数据保留在内存中是我不建议的解决方案。您说您正在预期一个相对较高的峰值。如果您的数据库在高峰期不可用,我无法相信您能够将所有请求在内存中排队必要的时间长度。如果它们在内存中,那么任何类型的应用程序服务器(或影响您的应用程序服务器的硬件问题)都会导致您的所有排队请求完全丢失。这意味着您的 REST 接口对其调用者撒谎。你返回说你已经成功地持久化了数据,而你却没有因为你的数据库和你的应用程序都崩溃了。

    您要么需要一个冗余数据库,要么需要一个持久的外部排队系统。如果您选择外部队列系统(这也可以是冗余的以防止中断),那么您可以简单地将所有持久请求推送到外部队列中。那么您只需要支持一种机制/工作流程。

    【讨论】:

      【解决方案3】:

      如果您正在打一个休息电话,我认为您不能将所有请求保存在同一个链接列表中。您可以使用 RabbitMQ 进行排队。验证成功后,您可以将对象推送到队列并返回 200

      【讨论】:

      • 但是直接将其保存到数据库中没有同样的问题吗?即它需要等待网络上较慢的 TCP 流量?
      • 由于不能依赖内部内存队列,最好使用rabbitMQ或其他任何消息服务。我不确定,但是如果它是一个大对象,我认为发布到 rabbitMQ 比实际保存到数据库要快。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 2017-12-01
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      相关资源
      最近更新 更多