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

Laravel服务端事件(SSE)中$lastrec变量无法更新的问题排查

Laravel SSE 重复获取旧数据问题解决

问题本质

你用控制器私有变量$lastrec记录最后处理的ID,但每次SSE连接请求都会创建新的控制器实例,之前的$lastrec值会被重置为0,根本没法跨循环/跨请求保存状态。

解决思路:用持久化存储存lastrec

把$lastrec从控制器私有变量换成缓存、Redis或者数据库这类持久化存储,就能跨请求保持状态了,下面给具体实现:

方案1:用Laravel缓存(最简单)

直接替换变量读写为缓存操作:

public function streamUpdates()
{
    // 从缓存取上次的记录ID,默认0
    $lastrec = Cache::get('sse_last_record_id', 0);

    return response()->stream(function () use (&$lastrec) {
        while (true) {
            // 只查ID大于lastrec的新记录
            $newzRecords = Newz::where('id', '>', $lastrec)->orderBy('id')->get();

            if ($newzRecords->isNotEmpty()) {
                foreach ($newzRecords as $record) {
                    // 关联业务表取数据
                    $fullData = match($record->type) {
                        'TODOS' => TODOS::find($record->business_id),
                        'MEMOS' => MEMOS::find($record->business_id),
                        default => null
                    };

                    // 发送SSE事件
                    echo "event: new-data\n";
                    echo "data: " . json_encode($fullData) . "\n\n";
                    ob_flush();
                    flush();

                    // 更新缓存和本地变量
                    Cache::put('sse_last_record_id', $record->id, now()->addDay());
                    $lastrec = $record->id;
                }
            }

            // 每秒查一次,避免占满CPU
            sleep(1);
        }
    }, 200, [
        'Content-Type' => 'text/event-stream',
        'Cache-Control' => 'no-cache',
        'Connection' => 'keep-alive',
    ]);
}

方案2:用Redis(高并发场景)

如果项目已经用Redis,用法和缓存类似,只是指定驱动:

// 初始化
$lastrec = Redis::get('sse_last_record_id') ?? 0;

// 更新时
Redis::set('sse_last_record_id', $record->id);

方案3:用数据库存储(需要持久化到磁盘)

建个简单的配置表sse_configs(字段key、value),专门存这个ID:

// 初始化,没有就创建默认值0
$config = SseConfig::firstOrCreate(['key' => 'last_record_id'], ['value' => 0]);
$lastrec = (int)$config->value;

// 更新时
$config->update(['value' => $record->id]);

额外提醒

  • 一定要设置正确的SSE响应头,不然浏览器可能会缓存数据或者断开连接
  • 休眠时间可以根据业务调整,比如数据更新不频繁就设成5秒
  • 多服务器部署的话,别用本地缓存,必须用Redis这类分布式存储,不然不同节点的记录ID会不一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:25:10