colordog
V2EX  ›  PHP

来个 PHP shell 自动执行的思路

  •  
  •   colordog · May 30, 2017 · 5533 views
    This topic created in 3452 days ago, the information mentioned may be changed or developed.

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

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

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

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

    用多线程处理,10 万,也就几分钟的事情
    zhengwenk
    zhengwenk
    Jul 6, 2017
    26
    才 10w 用户 你开一个 php 脚本 放后台跑,一伙都跑完了吧
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4032 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 58ms · UTC 05:45 · PVG 13:45 · LAX 21:45 · JFK 00:45
    ♥ Do have faith in what you're doing.