如何处理一亿条数据请求api, 求一个思路或者流程?

项目想实现的效果是这样的

1.)前端提交一个txt文件, 文件内有一亿条数据,一行一条数据
2.)后端接受txt文件,取出一条数据,拼接api, 生成新的url链接
3.)后端curl发起请求,获取返回数据,保存数据
4.)前端此时,可以实时显示一亿条数据跑了多少条了

项目现状

前端用js模拟多线程,不停的向后端发起请求,后端laravel不停的接收数据并返回数据
效果并不理想,速度特别慢,前端页面还会卡死不动!

1.)希望一亿条数据在后端循环处理,目前是前端发起一亿次请求,后端只是处理一条数据,相当于一亿条数据在前端处理
2.)前端显示实时跑到了第几条数据!
3.)希望速度快一些,最好一天跑完!提供最快的方式就行!
4.)求这个的解题思路,要用到laravel的那些插件框架或者技术名词?
5.)是否用Guzzle合适?

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 19

队列,websocket
数据不要只一条,几百条一起也是没问题的

2年前 评论

直接录入后端,前端不用操作什么。然后队列。

2年前 评论

感觉思路和搜索引擎站长提交sitemap差不多的道理,sitemap有api方式提交和文本提交两种,api提交偏重于实时,每次提交数量较少一般几百条,但处理较快;文本提交偏于数量较大的数据,每个文件包含大概小于5W条。
可以模仿这种方式,前端单次提交包含N万条的文本作为一个数据单元,提取文本中的数据和条数,插入表中待处理。比如有10个进程,每个进程负责处理一个数据单元,或者放进队列多个进程消费。重点是前端和后端是异步的,且既不一条一条提交(太慢)又不能单次提交过大,其他都没什么难度了。

2年前 评论

你这个每条还要 curl 获取数据保存,这个动作注定快不了吧!大概只能多放几个服务器一起跑了。。。

2年前 评论

上传txt文件到后端,循环读取,队列处理,内存够用的话,horizon多开点进程

file

2年前 评论
ycstar 2年前

一亿条保存在一个txt?好奇那个txt文件有多大

2年前 评论
arvin-hermit 2年前
chowjiawei

获取到这个txt文件 判断有几行 按1000个或者多少来循环 循环体内增加redis缓存 缓存该次请求的状态
提供状态api给前端 前端可以实时看到数据处理的情况 1亿数据 分为100块 每块100万数据进度 即可

2年前 评论

一个敢问一个敢答

算你一行10个字节,一亿行数据就是 953 个 G,恕我我见识短没见过这么大的文件;

  • C 端能打开这个文件吗?
  • 浏览器有能力处理这个文件吗?
  • 磁盘会转晕吗?
  • 上传的时候能带宽够用吗?
  • ……

有哥们又来说了我分片上传呀,服务端内存够用吗?磁盘会转晕吗?……

真够魔幻的~

2年前 评论
hello-bug 2年前
myhui0926 2年前
lidongyoo (作者) 2年前
lidongyoo (作者) 2年前
two_steps

后端接收到文件之后,调用shell脚本执行后面的逻辑,又快占用内存又小

2年前 评论

疑问:

  1. 拼接的api能承受吗
  2. 返回数据要保存 (这步考虑带宽和存储IO,会花掉很多性能)
  3. 有带宽交互和存储的往往快不了 理论1天还挺难 除非高核(多台)服务器+高带宽(金钱换时间)

参考方法:

  1. 将大文件拆分为1万行每个(linux命令能搞定 文件名使用数字形式存储 例如1.txt 2.txt)
  2. 读取这些拆分的全部文件 (开多线程 利用文件名取余或者其他分辨方式处理)
  3. 1个小文件处理完成后利用socket通知前端现在已经到(10000/1000000000) (感觉没必要搞到前端实时显示进度 可以在处理完小文件后记录小文件名称...)
2年前 评论

一个比较靠谱的方案.
100000000 个 URL 的 TXT 文件,

  1. 前端 js 有一个计数器变量 count
  2. 前端分片读取, 不要上传到服务器, 每次读取 1000 个 URL,
  3. 把这 1000 个 URL 提交给 PHP, PHP 使用MultiCurl并发请求, 假如设置 3s 时间,理论 3s 内能处理好 1000 个 URL (后端并发), 然后 js 计数 count += 1000 显示

file

  1. 想要更快吗? 当然还有, 既然后端能并发发出请求, 那前端也可以
  2. 第 2 步 js 并发去读, 或者不等待后端处理完成直接发起下一个请求. 自己处理好前端并发数, 然后多个 ajax 同时发出. (理论上只要你的服务器够牛, 在没有达到 tcp 连接数上限, 你就随便整.)
2年前 评论
梦想星辰大海
  1. 前端看效果,可以轮询redis,后端每处理成功一次,就自增一次redis数据。
  2. 后端处理速度这块,可以考虑上协程来处理,如果是一次性代码,可以考虑用swow处理,这个扩展windows也能跑。

下面是test.php的代码:

<?php

use Swow\Channel;
use Swow\Coroutine;
use Swow\Sync\WaitGroup;

$consumer = 2;
$quit = new Channel($consumer);
for ($i = 0; $i < $consumer; $i++) {
    $quit->push(1);
}
$channel = new Channel(5);
$wg = new WaitGroup();

$wg->add(1);
Coroutine::run(function () use ($channel, $wg, $quit, $consumer) {
    try {
        $file = fopen(__DIR__ . '/data.txt', 'r');
        while (!feof($file)) {
            $row = trim(fgets($file));
            if (strlen($row) > 0) {
                $channel->push($row);
            }
        }
        fclose($file);
        for ($i = 0; $i < $consumer; $i++) {
            $quit->pop();
        }
    } catch (Throwable $throwable) {
        echo '生产异常:' . $throwable->getMessage() . PHP_EOL;
    } finally {
        $wg->done();
    }
});

for ($i = 0; $i < $consumer; $i++) {
    $wg->add(1);
    Coroutine::run(function () use ($channel, $wg, $quit, $i, $consumer) {
        try {
            while (!$quit->isEmpty()) {
                $row = $channel->pop();
                sleep(1);
                echo '协程 ' . $i . ' 正在消费 --> ' . $row . PHP_EOL;
            }
            if ($i + 1 == $consumer) {
                while (!$channel->isEmpty()) {
                    $row = $channel->pop();
                    sleep(1);
                    echo '协程 ' . $i . ' 正在消费剩余 --> ' . $row . PHP_EOL;
                }
            }
        } catch (Throwable $throwable) {
            if ($throwable instanceof Swow\Channel\Exception && !$channel->isWritable()) {
                return;
            }
            echo '消费异常:' . $throwable->getMessage() . PHP_EOL;
        } finally {
            $wg->done();
            echo '协程 ' . $i . ' 退出' . PHP_EOL;;
        }
    });
}

$wg->wait();
$channel->close();
$quit->close();

执行:php -d extension=swow test.php
至于能不能使用curl扩展啥的,楼主自己测试一下。

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!