即使在使用连接池后如何处理过多的并发连接?

How to handle too many concurrent connections even after using a connection pool?

场景

假设您有一个拥有大量流量的网站或应用程序。即使使用数据库连接池,性能也会受到真正的打击(site/app 甚至可能会崩溃),因为并发连接太多了。

问题

处理这个问题的人有哪些选择?

我的想法

我在想有这个问题的人可以创建多个数据库(可能在不同的机器上,虽然我不确定是否有必要),每个数据库都具有相同的信息并同时更新,这将授予多个单个数据库的原始连接数。但如果数据库很大,这似乎不是一个非常可行的解决方案。

如果您还没有这样做,您可以尝试 运行 在应用程序服务器上使用您的应用程序——在您的应用程序后面获取一些中间件。大多数应用程序服务器都会做自己的连接池(因为从 Web 应用程序到数据库连接池的连接仍然非常昂贵)。此外,您应该能够将您的应用程序服务器配置为使用共享连接——顾名思义,这将允许尽可能共享连接。

简而言之,使用应用服务器。如果您已经是,也许可以提及您使用的是哪一个,我们可以从那里着眼于优化服务器配置。

对于这个问题,您应该调查很多事情。
- 有多少同时连接。您始终可以增加内存并增加最大连接数。 MySQL 可以支持百万级连接。

-确保您的应用正在关闭连接。即使有池,应用程序也必须 return 连接到池。

-运行 数据库在单独的服务器上。

-确保您已优化查询。一个长 运行ning 查询会降低系统速度。

-如果其他方法失败,最后使用 MySQL 集群。对于高流量站点,您可能需要考虑这一点以避免单点故障。

这是一个典型的应用扩展问题,已经设计了许多解决方案 - 例如 Google 大 Table 和 Amazon Elastic 产品。 如果迁移到云中并利用它们都提供的自动缩放选项不是一个选项,那么您将需要创建自己的设置。看一下 Postgres and MySQL 的文档,你会发现这些想法非常相似,包括

的概念
  • 分片:将您的客户端数据分散到多个数据库中,并将客户端请求路由到正确的数据库实例。

  • 负载平衡:将您的应用程序部署在多个服务器上,并使用中间件根据服务器上的负载路由请求。它需要某种数据库同步工具,如 SymmetricDS 来保持数据库同步。

这绝不是所有选项的全面概述,但可能会帮助您入门。

主干不够具体,无法给出坚定的建议,但可以完成的工作的完整列表如下:

  • 数据库集群:适用于不想改变应用层,数据库就是你的情况。您可以从数据库集群中获得多少是有限制的。如果您的请求量持续增长,此解决方案最终也会失败。但好消息是,您已经拥有普通单实例中已有的所有功能 MySQL.
  • Sharding:由于您的问题被标记为 MySQL,并且它本身不支持分片,如果您想使用此解决方案,您需要实施它在你的应用层。在此解决方案中,您将在逻辑上将数据分散到多个数据库(最好是在单独硬件上的多个 MySQL 实例中)。您有责任找到保存您指定数据的适当数据库。这是有史以来最有效的解决方案之一,但并不总是可行的。它最大的缺陷是分散在两个或多个数据库中的数据不能包含在一个事务中。
  • Replication:根据您的情况,您可能能够合并数据库复制并在其中拥有数据副本。这样您就可以连接到它们而不是 master 数据库并减少它的负载。默认的复制定义是 master/slave 场景,其中数据流是单向的,从 master 到 slave。因此,您可能对从服务器所做的更改将应用​​于从服务器,它们不会影响主服务器。但是还有一种 master/master 复制配置,其中数据双向流动。然而,您不能假设两个主控之间并发数据更改的原子完整性。最后,如果您打算在 master/slave 模式下使用它并使用从属设备进行只读访问,则此解决方案最有效。
  • 缓存:也许这个解决方案不应该包含在这里,但是因为你的词干不拒绝它,所以就在这里。减少数据库负载的方法之一是在提取数据后对其进行缓存。如果提取数据的成本很高,则此解决方案特别有用。那里有很多缓存服务器,比如 memcached or redis。这样你就可以省略这么多的数据库连接,而只是为了提取数据。
  • 其他存储引擎:如果您当前的存储引擎不能满足您的需求,您可以随时切换到性能更高的引擎。当然,这只有在您的需求允许的情况下才可行。现在有 NoSQL 引擎,比 RDBMS 性能更高,它本身支持分片,你可以用最小的努力线性扩展它们。还有基于 Lucene 的解决方案,具有强大的全文搜索功能,可为您提供相同的自动分片。事实上,您应该使用传统 RDBMS 的唯一原因是事务的原子行为。但是如果事务不是必须的,那么有比 RDBMS 更好的解决方案。

Replication -- 主节点加上任意数量的从节点。这为您提供 "unlimited" 读取缩放。

Disconnect -- 连接不应保持连接打开的时间超过必要的时间。

Unix,不是 Windows -- 需要我详细说明吗?

InnoDB -- 使用 InnoDB,不使用 MyISAM。

SlowLog -- 将 long_query_time 设置为 1 并观察前几个查询;优化它们。请参阅 pt-query-digest 以获取有关总结 slowlog 的帮助。

我 运行 遇到了类似的问题,即使该应用程序应该关闭它的连接,我也可以看到它们在 SQL 中堆叠为休眠连接。检查问题后,我将以下内容添加到 webconfig 中的连接字符串中,并使用以下内容进行测试:

Connection Lifetime=600

这应该会在 10 分钟后终止所有休眠连接 - 但它并没有...

经过进一步审查,我的网络服务器和 SQL 服务器上都有待处理的 windows 更新。奇迹般地,问题消失了!

我希望我能为您提供更具体的答案,但在添加 "Connection Lifetime" 和让我的网络和 SQL 服务器更新补丁之间的某个地方完全消除了我的问题。我已经干净 3 周了,没问题。

在我们的案例中,当 mysql 并发连接达到 100 时,我们也面临同样的问题。

最后,我们找到了一个很棒的 npm express-myconnection 模块 (https://www.npmjs.com/package/express-myconnection)。完成后它会自动释放连接。它支持 SinglePool 连接策略。

它工作正常。