php 处理10w+20w数据

用户10万 订单20万
通过用户去匹配订单最后处理完成

1 从mysql循环查询,(cpu撑不住不可靠)
2 查询所有会员,订单,再匹配 (php内存溢出)
3 批次会员2000个,订单分3份 去匹配,处理速度慢
比如循环2000会员,去匹配第1批订单[无],
再从mysql取出第二批[有,缓存下来供后面会员使用]

现在不知道该怎么处理速度快,不会消耗很多服务器资源,

可能数据不止这些,目前遇到的就是 内存溢出 处理速度慢 占用系统资源高

阅读 5.1k
6 个回答

不是很理解你的需求,感觉 10w、20w 也不是很多,我记得以前经常弄这个规模的数据。提几个建议:

  1. 升级内存
  2. 直接在数据库里跑
  3. 不知道你缓存怎么处理的,如果只是放数据那不可能快得了
  4. 修改问题,把前因后果说清楚

现在是以缓存全部缓存,一部分内存,内存没有就去缓存里找,然后替换内存 5s完成运行
0.402562s 1 page
0.428822s 2 page
0.470299s 3 page
0.514591s 4 page
0.559493s 5 page
0.230761s 6 page
批次10万结果 总50万

我听大佬说加个索引数据库查询就会变快,要不试试

10万真的不多

用PCNTL扩展,自己模拟多进程实现.
10万条数据 切割成10份.
10个进程 每个进程处理1W条数据.
切割成多少份,随意 20也行.

sql中使用主键id,会使用到覆盖索引,没有SQL性能问题.

请看伪代码

        
        //子进程最大数量
        $pMax  = 10;
        //获取数据最大id  数据可能id不连续,使用max(id) 比使用count(*) 更合理
        $sql   = "SELECT MAX(id) as count FROM table ";
        $count = $db->fetchOne($sql, \Phalcon\Db::FETCH_ASSOC);
        $count = $count['count'];
        var_dump("数据总数:".$count);
        $limit_count = ceil($count / $pMax);
        var_dump("每个进程处理数据条数:".$limit_count);

        //$sql = " SELECT id FROM `table`  WHERE id < {$id}  ORDER BY id DESC limit {$limit} ";
        //echo "生产者sql:" . PHP_EOL;
        //echo $sql . PHP_EOL;
        //$data = $db->fetchAll($sql, \Phalcon\Db::FETCH_ASSOC);


        // 10个子进程处理任务
        $start = self::getMicroTime();
        for ($p = 1; $p <= $pMax; $p++) {

            sleep(1);
            $pid = pcntl_fork();

            if ($pid == -1) {
                die("could not fork");

            } elseif ($pid) {
                echo "父进程: $pid\n";
                //pcntl_wait($status,WNOHANG);

            } else {
                // 子进程处理
                //$func = $args[0].'Action';
                $func = '子进程执行函数名称';

                $params = [];

                //子进程参数1-当前进程需要处理的数据最大id
                $params[1] = $p*$limit_count;

                //子进程参数0-进程编号
                $params[0] = ($p-1)*$limit_count;
                //子进程参数2-进程id
                $params[2] = $p;
                //子进程参数3-数据内容
                $params[3] = $data;

                $this->$func($params);
                // 一定要注意退出子进程,否则pcntl_fork() 会被子进程再fork,带来处理上的影响。
                exit;
            }
        }
        // 等待子进程执行结束
        while (pcntl_waitpid(0, $status) != -1) {
            $status = pcntl_wexitstatus($status);
            echo "子进程 $status 完成\n";
        }

看看是否满足你的需求

多进程比较好理解.

如果追求更高性能,可以用Swoole来写,不过还需要额外安装PHP扩展.

有其他疑问,请在评论区交流.

问题:加速消费
思路:

  1. 数据分批 -
  2. 消费能力提升 - 多进程/协程
  3. 分批和多进程/协程的拿任务问题
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题