V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
colordog
V2EX  ›  PHP

来个 PHP shell 自动执行的思路

  •  
  •   colordog · 2017-05-30 22:08:19 +08:00 · 4102 次点击
    这是一个创建于 2762 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景是这样的,有一个商城,预估用户数为 10w+,客户要求每月 1 日,计算每个用户上个月的消费总额和消费笔数,然后根据这 2 个数值,自动给用户升降级,同时需要写入升降级记录以便用户查询;

    问题,写一个 php 程序,如果一次 foreach 出来 10w 个数据,再循环查询、插入,效率感觉很低,服务器基本要垮掉,而浏览器我记得可以一次处理一部分,然后跳转再执行下一部分,跟分页似的,可是用 shell 行么?不行吧,使用 sleep 让 php 等待不知道是不是可以,希望大家给个思路。

    26 条回复    2017-07-06 13:53:23 +08:00
    shmilyin
        1
    shmilyin  
       2017-05-30 22:13:42 +08:00 via iPhone
    php cli
    cnlongxi
        2
    cnlongxi  
       2017-05-30 22:21:29 +08:00 via iPhone
    PHP 一次执行 100 条,没计算完就用 PHP 执行 exec 继续
    shoaly
        3
    shoaly  
       2017-05-30 22:26:18 +08:00
    放到 crond 里面去执行: 执行思路:
    1 每次取 100 个用户, 计算积分, 并且缓存该积分, 然后记录本次计算的时间戳
    2 注意取的时候要 where 出 当前时间减去上一次更新时间>阈值的数据

    基于上面 2 个点, 就可以无限去运行 crond 了, 既不会重复计算, 也不会因为某一次计算量太大而卡住, 即便是卡住了, 也可以"断点续传"的接着上次 bug 掉的地方继续处理
    colordog
        4
    colordog  
    OP
       2017-05-30 22:32:00 +08:00
    @shmilyin 以前稍微弄过一点,不太熟悉,还是不太了解一次性处理大量数据的方法。
    colordog
        5
    colordog  
    OP
       2017-05-30 22:32:17 +08:00
    @cnlongxi 这个方法好像可以诶,谢谢
    colordog
        6
    colordog  
    OP
       2017-05-30 22:32:31 +08:00
    @shoaly 看着好复杂的样子,不过看起来貌似可以
    sagaxu
        7
    sagaxu  
       2017-05-30 22:35:59 +08:00
    10 万是很小的量,放心 foreach 吧
    rekulas
        8
    rekulas  
       2017-05-30 22:38:22 +08:00
    10w+的数据量 PHP 的性能完全能胜任,如果慢很可能是卡在数据库相关操作上,检查你的语句即可
    hiboshi
        9
    hiboshi  
       2017-05-30 22:45:02 +08:00
    既然是写脚本不需要考虑浏览器,超时。直接 php-cli 即可。
    hiboshi
        10
    hiboshi  
       2017-05-30 22:45:26 +08:00
    @hiboshi > php run.php
    doctorlai
        11
    doctorlai  
       2017-05-30 23:00:43 +08:00
    每次从数据库里取 1000 条,执行,结束。
    加入 crontab 每几分钟执行一次
    coolyujiyu
        12
    coolyujiyu  
       2017-05-30 23:02:49 +08:00
    任务分片、多线程处理。
    dangyuluo
        13
    dangyuluo  
       2017-05-30 23:04:26 +08:00
    同时从数据库内取 10000 条,然后处理完成后,组成一条长 MySQL update 语句,这样执行很快。
    Fishdrowned
        14
    Fishdrowned  
       2017-05-30 23:34:14 +08:00 via Android
    我来说三个点
    1、如果你要遍历所有用户,你可以写成两层循环,外层 while(读 1000 条),内层 foreach (刚才读到的 1000 条);
    2、在 sql 里就可以筛选掉大部分记录。升级比较容易处理,降级再加一个条件,因为最低级别是不会再降级的,所以不用处理最低级的用户;
    3、每月 1 号执行配置一下 crontab 就可以了,具体怎么配置,搜索一下。
    cxbig
        15
    cxbig  
       2017-05-31 07:26:39 +08:00 via Android
    用户总有自增 ID 的吧?怕读多了锁表或吃太多内存,每次取 100 个来计算不就好了? SQL 不是有 LIMIT 分页么。
    azh7138m
        16
    azh7138m  
       2017-05-31 07:56:03 +08:00 via Android
    @Fishdrowned 最低级用户可以升级的吧
    zhs227
        17
    zhs227  
       2017-05-31 08:26:46 +08:00
    如果数据不会因为后续的更新而导致 sql 变化,可以把要执行的 sql 都统一生成到一个文件里,前后加上事务执行开始和结束。然后使用 mysqladmin 导进去。
    Fishdrowned
        18
    Fishdrowned  
       2017-05-31 08:57:19 +08:00 via Android
    @azh7138m 升级和降级是分开处理的
    klgd
        19
    klgd  
       2017-05-31 08:57:28 +08:00
    没有消费的用户也要处理吗? 如果不处理的话,就反过来,先查出上月消费数据,根据这些数据来处理用户升降级,这样要处理的数据会少很多(每月不可能 10W 用户都有消费的)
    sarices
        20
    sarices  
       2017-05-31 09:07:11 +08:00
    分开取出或者一次性取出,10W 不多,但是看你取出会不会有慢查询了,然后放到队列跑
    harborM
        21
    harborM  
       2017-05-31 09:42:04 +08:00
    想必计算用户的上月总额和笔数不会在每月一日执行,每月一日前的工作是取出已经叠加的聚合数值执行升降级工作,那么可以用一条语句直接 update,担心性能的话可以用 crontab + limit 分段工作;
    gouchaoer
        22
    gouchaoer  
       2017-05-31 17:01:45 +08:00
    php-cli 部署很麻烦的,10w 的数据量就用 php-fpm 就 ok 了,至于怕 cron 超时的话超过一定时间之后可以自己触发新的 php 请求。。。。
    mengdodo
        23
    mengdodo  
       2017-05-31 17:37:49 +08:00
    phpredis
    mingyun
        24
    mingyun  
       2017-05-31 22:11:13 +08:00
    cli 每次取 1000 获取最后一个 id 然后第二次从 这个 id 开始,依次循环
    baoguok
        25
    baoguok  
       2017-06-02 11:55:29 +08:00
    php xx.php

    用多线程处理,10 万,也就几分钟的事情
    zhengwenk
        26
    zhengwenk  
       2017-07-06 13:53:23 +08:00
    才 10w 用户 你开一个 php 脚本 放后台跑,一伙都跑完了吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2623 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 06:57 · PVG 14:57 · LAX 22:57 · JFK 01:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.