【问题标题】:Prevent 'too many connections'(ConnectionPool is not the answer, looking for mysql server side solution)防止“连接过多”(ConnectionPool 不是答案,正在寻找 mysql 服务器端解决方案)
【发布时间】:2012-07-20 06:24:27
【问题描述】:

几周前,我发布了一个关于排队数据库访问请求的问题,以防止在发生大量并发数据库请求时出现“连接过多”错误。人们告诉我 ConnectionPool 是我当时同意的正确方法。但是,我终于意识到这不是解决方案,尤其是当有很多不同的客户端通过网络访问 mysql 服务器时,因为连接池在客户端,它不能防止所有客户端的连接总和超过最大连接数mysql服务器。

我认为mysql服务器上应该有一些中间件作为队列或池工作,有人熟悉吗?谢谢。

我知道这个问题被广泛询问,我也很惊讶,好像没有完整的解决方案。

【问题讨论】:

  • 可能的解决方案是在服务器上编写一个代理来创建连接池并将其传递给客户端
  • 我想知道这些巨头网络公司是如何使用mysql的。我知道 twitter 是基于 mysql 服务器的。我无法想象他们会正确设置客户端应用程序的连接数,以保证总数小于 mysql 服务器的最大连接数。这不是一种可扩展的方式,因为您无法立即启动更多客户端,因为客户端连接的总和可能会炸毁 mysql 服务器。
  • 您通过 HTTP 而不是 SQL 与 twitter 交谈。这意味着应用服务器,它可以平衡许多 MySQL 实例之间的负载。在此之前,HTTP 本身在应用服务器之间是平衡的。

标签: mysql database connection


【解决方案1】:

HAProxy 应该为您执行 TCP 级别的排队。不过,在中间构建一个应用程序服务器会比 TCP 更有意识地处理传入流。这可能需要重写服务器和客户端,但可以让您更好地控制正在发生的事情。

【讨论】:

  • 除了HAProxy,难道没有一些现成的中间件可以用于此目的吗?我的意思是 mysql 服务器的专用中间件,而不是一般的负载均衡器
  • 您对这个中间件有什么期望?.. 缓存 SQL 结果?.. 您的客户端-服务器协议与 TCP 上的 SQL 一样低,您似乎正在寻找解决最大连接数限制的方法MySQL 服务器实例。顺便说一句,您可以配置您的 MySQL 实例以处理更多连接(购买更多 RAM,减少线程占用)。
  • 基本上我希望中间件对来自客户端的访问进行排队,以避免“连接过多”异常。我想知道处理数百万并发访问的系统的设计是什么?
  • 这是“可扩展的高负载网络架构”领域,谷歌为它:) 基本思想如下:你有很多盒子,每个盒子只处理部分负载。您在多个级别上拆分负载,从 DNS 解析到不同客户端的不同 IP,然后将客户端指向不同的 CPU 密集型应用程序服务器,这些应用程序服务器正在与不同的内存缓存服务器进行通信,并且可能与不同的数据库实例进行通信。数据库实例可以被复制和/或分片。
  • 另外,如果您每秒能够处理 10 个请求,并且每秒再排队 100 个请求,这样做是否正确? :)
【解决方案2】:

你问的其实是一个相当复杂的问题。

首先您需要确定数据中的错位是否可以接受,例如:如果您在数据库中存储收到的 Likes 的数量,并且您在 12:00:00 询问这个数字,并且在DB是500,有人在12:00:01发了LIKE,你在12:00:02再次查询;是否可以再次收到“500”,即使正确的数字应该是 501,只要过一会儿答案“501”就出来了吗?

如果这是可以接受的(YouTube 中臭名昭著的“301 错误”),那么您可能会开始缓存一些 SELECT 响应。

您甚至可以将它们缓存在中间件中,即有一个特殊的进程连续运行并占用一个与 MySQL 的连接,并在队列中回答请求。您可以在服务器内部将其作为 8001 端口上的 Web 服务器运行,并使用 Apache ReverseProxy、HAproxy、磅或 NginX 位置在外部代理它。

您可以对特殊的 UPDATE/DELETE 查询执行相同的操作,即使它比较棘手。

最好先缓存通过 AJAX 异步运行的查询(如果有的话),因为使用代理序列化查询可能会明显降低应用程序的速度。

你有一个三重目标:

  • 尽可能快地在 MySQL 上运行查询(查看索引和 MySQL 缓存),以释放 ConnectionPool 并使其负载尽可能轻。
  • 重构应用程序以便从查询中提取所有信息(例如,具有特定属性的行数以及作为数据的行通常使用两个查询来检索,但通过适当的管理,您只需要一个和一个 SQLNumRows()调用。此外,通常会运行具有不同信息的类似查询,当单个查询可能一次返回所有信息时:通常,一个查询用于检查用户/密码,另一个查询用于获取完整的用户配置文件。
  • 将尽可能多的调用转移到根本没有(NginX、中间件)或轻微(排队进程)绑定到 MySQL 的东西上;在后一种情况下,使用已知数量的连接以可预测地运行。

不幸的是,没有简单的“灵丹妙药”来解决这个问题(当然除了增加连接数,可能会在多个作为主从运行的主机上复制数据库。虽然不是真正的灵丹妙药,但设计起来更容易并实施)。

【讨论】:

  • 感谢您的回复。为了减少 mysql 查询,我正在考虑使用 lucene 来缓存选择结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-13
  • 2017-08-26
  • 1970-01-01
  • 2019-01-16
相关资源
最近更新 更多