【问题标题】:large amount of inserts per seconds causing massive CPU load每秒大量插入导致大量 CPU 负载
【发布时间】:2012-02-17 15:15:30
【问题描述】:

我有一个 PHP 脚本,在每次运行时,都会向 Mysql 数据库插入一个新行(数据量相对较少..) 我每秒有超过 20 个请求,这导致我的 CPU 尖叫着寻求帮助..

我正在使用带有 MyISAM 引擎的 sql INSERT DELAYED 方法(尽管我只是注意到 INSERT DELAYED 不适用于 MyISAM)。

我主要关心的是我的 CPU 负载,我开始寻找使用对 CPU 更友好的解决方案来存储这些数据的方法。

我的第一个想法是将这些数据写入每小时一次的日志文件,然后每小时一次从日志中检索数据并立即将其插入数据库。

也许一个更好的主意是使用 NoSQL DB 而不是日志文件,然后每小时一次将数据从 NoSQL 插入到 Mysql..

我还没有测试任何这些想法,所以我真的不知道这是否会减少我的 CPU 负载。我想问是否有人可以帮助我找到对我的 CPU 影响最小的正确解决方案。

【问题讨论】:

    标签: php mysql performance nosql


    【解决方案1】:

    我最近遇到了一个非常相似的问题,我的解决方案是简单地批处理请求。由于 mysql 连接的开销减少以及重新索引的数量大大减少,这加快了大约 50 倍的速度。将它们存储到一个文件中,然后一次执行一个更大的(100-300 个单独的插入)语句可能是一个好主意。为了加快速度,使用

    在插入期间关闭索引
    ALTER TABLE tablename DISABLE KEYS
    insert statement
    ALTER TABLE tablename ENABLE KEYS
    

    进行批量插入会减少php脚本运行的实例数,会减少当前打开的mysql句柄的数量(很大的改进),也会减少索引量。

    【讨论】:

    • 如果其他进程同时写入数据库,这可能不是一个好主意。
    • 关于“减少 mysql 连接的开销”——我希望你并没有真正为每个插入打开一个新连接?
    【解决方案2】:

    好的,我设法通过 APC 缓存显着降低 CPU 负载

    我是这样做的:

    使用 APC-cache 将数据存储在内存中,TTL 为 70 秒:

    apc_store('prfx_SOME_UNIQUE_STRING', $data, 70);
    

    我每分钟循环一次缓存中的所有记录:

    $apc_list=apc_cache_info('user');
    
    foreach($apc_list['cache_list'] as $apc){
        if((substr($apc['info'],0,5)=='prfx_') && ($val=apc_fetch($apc['info']))){
            $values[]=$val;
            apc_delete($apc['info']);
        }
    }
    

    $values 插入数据库

    CPU 继续微笑..

    享受

    【讨论】:

      【解决方案3】:

      我会插入一个 sleep(1);函数在 PHP 脚本的顶部,在循环顶部的每个插入之前,其中 1 = 1 秒。这只允许循环每秒循环一次。

      通过这种方式,它将稍微调节 CPU 的负载量,假设您在每次运行中只写入少量记录,这将是理想的。

      您可以在此处阅读有关睡眠功能的更多信息:http://php.net/manual/en/function.sleep.php

      【讨论】:

      • 感谢您的回答。该脚本在每次运行中仅插入 1 条记录,问题是我有 20 个新用户每秒运行此脚本..
      【解决方案4】:

      如果不对这两种方法进行分析就很难判断,如果您先写入日志文件,最终可能会使操作数从 N 变为 N*2 时变得更糟。通过将其全部写入文件并执行批量插入,您可以获得一点优势,但请记住,随着日志文件填满,它的加载/写入时间会增加。

      为了减少数据库负载,如果您还没有使用内存缓存进行数据库读取,请查看。

      总而言之,尽管您最好同时尝试两者并查看更快的方法。

      【讨论】:

        【解决方案5】:

        由于您正在尝试 INSERT DELAYED,因此我认为您最多不需要第二个数据。如果你想坚持使用 MySQL,你可以尝试使用复制和 BLACKHOLE 表类型。通过在一台服务器上将表声明为 BLACKHOLE 类型,然后将其复制到另一台服务器上的 MyISAM 或其他表类型,您可以消除 CPU 和 io 峰值。 BLACKHOLE 实际上只是一个复制日志文件,因此“插入”到其中非常快速且对系统来说很轻。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-09
          相关资源
          最近更新 更多