You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP处理16k+用户大数组:如何用延迟任务优化推送性能

处理大规模推送通知的延迟任务方案

一、用消息队列异步拆分任务

把每个用户的推送请求拆成独立任务扔进消息队列(比如Redis List、RabbitMQ),再启动多个消费者进程/线程分批处理,既能控制并发量,又不会一次性占满服务器资源。

示例代码(PHP+Redis):
生产者(拆分任务入队):

foreach ($users as $user) {
    $task = json_encode([
        'user_id' => $user['id'],
        'token' => $user['push_token'],
        'content' => '你的推送内容'
    ]);
    // 推入Redis队列
    $redis->lPush('push_tasks', $task);
}

消费者(后台持续处理任务):

while (true) {
    // 阻塞式取任务,避免空轮询浪费资源
    $task = $redis->brPop('push_tasks', 0);
    if ($task) {
        $data = json_decode($task[1], true);
        // 调用推送接口
        send_push($data['user_id'], $data['token'], $data['content']);
        // 每次处理后休眠100毫秒,降低CPU占用
        usleep(100000);
    }
}

二、定时任务分批+延迟续跑

不用一次性拆分所有任务,而是通过定时任务每次处理一小批(比如100条),处理完自动触发下一批,或者固定间隔执行。

示例(Cron+PHP):

  1. 数据库存一个last_processed_id记录已处理的最后一个用户ID
  2. 定时脚本逻辑:
$batch_size = 100;
$last_id = get_last_processed_id();
// 取未处理的100条用户
$users = $db->query("SELECT * FROM users WHERE id > $last_id LIMIT $batch_size")->fetchAll();

foreach ($users as $user) {
    send_push($user['id'], $user['push_token'], '推送内容');
    update_last_processed_id($user['id']);
}

// 如果当前批次满100条,说明还有未处理用户,1分钟后自动续跑
if (count($users) == $batch_size) {
    exec('sleep 60 && php /path/to/push_script.php > /dev/null 2>&1 &');
}

三、异步任务+批次延迟调度

用语言自带的异步能力,分批次处理并设置延迟,给服务器留足喘息时间。

示例(Node.js):

const users = require('./user_list.json');
const batch_size = 50;
let current_index = 0;

function process_batch() {
    const batch = users.slice(current_index, current_index + batch_size);
    if (batch.length === 0) return;

    // 并行处理当前批次推送
    Promise.all(batch.map(user => send_push(user.id, user.token, '推送内容')))
        .then(() => {
            current_index += batch_size;
            // 延迟2秒处理下一批
            setTimeout(process_batch, 2000);
        })
        .catch(err => console.log('推送失败:', err));
}

// 启动任务
process_batch();

四、优先用服务商批量推送接口

绝大多数推送服务商(FCM、APNs、个推等)都支持批量推送,把多个用户打包成一个请求发送,能大幅减少HTTP请求次数,降低服务器负载。

示例(FCM批量推送):

// 提取所有用户的推送令牌
$tokens = array_column($users, 'fcm_token');
// 按服务商限制拆分批次(FCM一次最多500个令牌)
$token_batches = array_chunk($tokens, 500);

foreach ($token_batches as $batch) {
    $payload = [
        'registration_ids' => $batch,
        'notification' => [
            'title' => '通知标题',
            'body' => '通知内容'
        ]
    ];

    $ch = curl_init('https://fcm.googleapis.com/fcm/send');
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: key=你的FCM密钥',
        'Content-Type: application/json'
    ]);
    curl_exec($ch);
    curl_close($ch);

    // 延迟1秒避免触发接口限流
    sleep(1);
}

内容的提问来源于stack exchange,提问作者Aman Kamboj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 19:06:21