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

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

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

项目现状

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

求

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

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 19

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

4年前 评论

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

4年前 评论

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

4年前 评论

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

4年前 评论

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

file

4年前 评论
ycstar 4年前

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

4年前 评论
Bryant001 4年前
chowjiawei

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

4年前 评论

一个敢问一个敢答

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

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

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

真够魔幻的~

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

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

4年前 评论

疑问:

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

参考方法:

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

一个比较靠谱的方案.
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 连接数上限, 你就随便整.)
4年前 评论
梦想星辰大海
  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扩展啥的,楼主自己测试一下。

4年前 评论

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