处理大量MySQL连接

3
我有一个JS脚本,只做一件简单的事情 - 向我的服务器发起ajax请求。在这个服务器上,我建立了一个PDO连接,执行了一条预处理语句: SELECT * FROM table WHERE param1 = :param1 AND param2 = :param2; 其中table是一个拥有5-50行、5-15列数据的表格,平均每天变化一次。
然后,我将JSON结果回显到脚本中,并对其进行一些操作,比如控制台日志记录。
问题是该脚本每秒运行约10,000次。这就意味着我会向数据库建立那么多的连接,并且我一直在服务器日志中收到“无法连接到数据库”的错误。这意味着有时它可以工作,当DB进程空闲时,有时却不行。
我该如何解决这个问题?
可能的解决方案:
1. Memcached - 它也会很慢,不适合这种用途。性能会类似或更差于数据库。 2. 在服务器上使用文件代替数据库 - 很好的解决方案,但结构会成为问题。
是否有更好的解决方案?

我猜你是想为每个请求创建一个新的数据库连接。看看PDO里的持久连接,同时如果有大量的流量,通常会使用负载均衡来分发请求并保持数据的可用性。 - georoot
另外,是否使用memcached应该取决于您的数据库结构。例如,我永远不会在身份验证中使用缓存,但肯定会在博客内容显示方面使用它,因为这对于每个人都是相同且很少更改的。 - georoot
Memcached比服务器上的文件慢,这是我所指的(说的)。 - khernik
1
你考虑过缓存输出而不是数据本身吗? 如果结果相同,没有必要重复运行相同的 PHP 脚本,只需预先生成输出并仅在需要时使用 PHP 进行身份验证(如果您确实需要)。您可以将结果存储在 RAM 磁盘上。 此外,请在问题中添加为什么在您的情况下使用 memcached/file/output cache 不好的原因,因为目前它有些模糊。 - DannyZB
1
1.) 如何在具有数据库访问权限的JS脚本中进行控制台日志记录?这不是客户端。 2.) 你使用哪个服务器? 3.) 这是Node.js吗? 4.) 如果您只有有限数量的结果,则将脚本结果缓存到常规临时文件中,放置在ramdisk或memcached上,并仅输出用户需要的正确结果。如果每秒有10,000个查询,即使对于大型结果集(即使100k个结果对于该行数的内存缓存也是微不足道的),这也是有意义的。 - DannyZB
显示剩余2条评论
3个回答

0

对于如此少量且很少更改的数据,我会将其作为普通的PHP文件处理。

一旦您以数组形式拥有数据,请使用var_export()将其转储到php文件中。然后只需包含此文件并使用简单的循环搜索数据即可。

另一个选择是使用Memcached,它专门为这种工作而创建,在具有高速网络的快速机器上,memcached可以轻松处理每秒200,000多个请求,这远高于您谦虚的10k rps。

您甚至可以从程序中删除PHP,使Nginx直接向Memcached请求存储的值,使用ngx_http_memcached_module。

如果您想坚持当前基于Mysql的解决方案,可以在mysql配置中增加max_connections数量,但是将其设置为超过200可能还需要进行一些操作系统调整。但是您不应该建立持久连接,这会使情况变得更糟。


0

你需要利用缓存。对于这种变化缓慢的数据,没有理由每次 AJAX 请求时都从数据库中获取数据。

你可以采取一些方法(甚至可以结合使用):

在应用程序和数据库之间进行缓存。这可能是 memcache 或类似的东西,它允许你执行基于哈希的查找(可能基于传递的某些参数的哈希)到存储在内存中的数据(可能是 JSON 表示或任何最终返回给客户端的数据格式)。

在客户端和应用程序之间进行缓存。这可能采用 Web 服务器提供的缓存、基于 CDN 的缓存或类似的方式,如果缓存中存在适当存储的未过期项目,则可以防止请求甚至到达您的应用程序。


0

有更好的方案吗?没有。

由于您多次输出相同的结果,明智的解决方案是缓存结果。

我猜测您的错误假设——即memcached不适用于此——是基于您计划单独存储每个记录。

我为您实现了一个简单的缓存机制:

    <?php
    $memcached_port = YOUR_MEMCACHED_PORT;

    $m = new Memcached();
    $m->addServer('localhost', $memcached_port);

    $key1 = $_GET['key1'];
    $key2 = $_GET['key2'];

    $m_key = $key1.$key2; // generate key from unique values , for large keys use MD5 to hash the unique value

    $data = false;
    if(!($data = $m->get($m_key))) {
        // fetch $data from your database
        $expire = 3600; // 1 hour, you may use a unix timestamp value if you wish to expire in a specified time of day
        $m->set($m_key,$data,$expire); // push to memcache
    }

    echo json_encode($data);

你需要做的是:
  1. 确定什么表示结果(哪个输入参数集)

  2. 将其用于memcache键(例如,如果它是一个国家和语言,则键将是$country.$language)

  3. 检查结果是否存在:

    • 如果存在,请将存储为数组的数据提取出来并输出。
    • 如果不存在或已过时:

    a.获取所需数据

    b.将数据放入数组中

    c.将数据推送到memcached中

    d.输出数据

有更高效的缓存数据的方法,但这是最简单的方法,听起来适合你的代码。

每秒10,000个请求还不足以证明创建服务器级缓存(nginx/whatever)所需的工作量。 在理想的调整世界中,拥有计算器的鸡都能运行Facebook..但谁在乎呢?(:


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