程序员小王
1/8/2025
嘿,大家好!👋
我最近在搞一个 Laravel 11 项目,使用 Redis 7 来处理数据流,结果在高峰期的时候,Redis 的流数据堆积得比处理速度还快,真是让人头大!😅
项目需要快速和高级的报告功能,我有个模型叫 StatisticAggregate
,它会随着一天的进展来聚合数据。每次有新的 session,就会更新或创建一行数据。为了高效,我用的是 MySQL 8 的 upsert
,因为有几百条数据需要更新或插入。
数据是通过 Redis 流来追加的,然后我用一个自定义的 artisan 命令(类似 Laravel Pulse)来无限循环地从流中拉取数据并 upsert 到数据库。问题是,随着一天的进展,流中的数据堆积得比处理速度还快。处理 1000 条数据大约需要 20-30 秒,也就是每分钟 2000 条,但高峰期每分钟有 5000 条以上的数据涌入。😩
我不认为是数据库的瓶颈,因为即使 Redis 中有大量积压,表中有 10 万行数据,系统负载下降时,积压的数据会在一夜之间处理完。如果是表慢的话,应该会在这里显现出来。
我是不是漏掉了什么关键的代码优化呢?求各位大佬指点!🙏
namespace App\Console\Commands\StatisticAggregates; use Illuminate\Console\Command; use Illuminate\Contracts\Console\Isolatable; use Illuminate\Support\Sleep; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; use App\Services\StatisticAggregateStream; use Carbon\CarbonImmutable; class StatisticAggregatesStreamWork extends Command implements Isolatable { // ... existing code ... public function handle(): int { // ... existing code ... while (true) { // ... existing code ... StatisticAggregateStream::digest(); // ... existing code ... } } }
digest
函数:namespace App\Services; use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\DB; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Database\QueryException; use App\Models\Reports\StatisticAggregate; use App\Models\Reports\StatisticAggregateRelation; use Throwable; class StatisticAggregateStream { // ... existing code ... public static function digest(): int { $total = 0; while (true) { $entries = collect(Redis::connection('stream')->xrange(self::ingestKey(), '-', '+', self::$chunk)); if ($entries->isEmpty()) { return $total; } $keys = $entries->keys(); self::store( $entries->map(fn (array $payload) => unserialize($payload['data'])) ); Redis::connection('stream')->xdel(self::ingestKey(), $keys->toArray()); if ($entries->count() < self::$chunk) { return $total + $entries->count(); } $total = $total + $entries->count(); } } }
我已经尝试过调整 Redis 的 chunk 大小和优化数据库索引,但效果不明显。有没有人遇到过类似的问题?或者有什么建议可以提高处理速度吗?非常感谢!🙏
PS: 我已经喝了三杯咖啡来保持清醒,希望能尽快解决这个问题!☕️
标签:MySQL, PHP, Laravel, Redis, 性能优化, 数据流处理
工程师Alex
1/8/2025
嘿,你好啊!👋
我太理解你遇到的 Redis 数据流处理瓶颈了,之前我也在类似的项目中遇到过这种情况,真是让人头疼!😅 但别担心,我们一起来看看怎么优化这个问题。
首先,确保你的 Redis 和 MySQL 都是最新的版本,并且配置是为高性能优化的。接下来,我们可以从以下几个方面来优化你的代码:
批量处理:你提到每次处理 1000 条数据,试着增加这个批量大小,看看是否能提高效率。Redis 和 MySQL 都能很好地处理批量操作。
并行处理:考虑使用 Laravel 的队列系统来并行处理数据流。这样可以充分利用多核 CPU 的优势。
异步处理:如果可以,尝试将一些非关键任务异步化,比如日志记录。
Redis 配置优化:确保 Redis 的 maxmemory-policy
设置为 allkeys-lru
或 volatile-lru
,以便在内存不足时能更好地管理数据。
数据库索引:虽然你已经优化过索引,但再检查一下是否有遗漏的地方,尤其是 upsert
操作涉及的字段。
以下是一些代码示例,展示如何实现并行处理:
namespace App\Console\Commands\StatisticAggregates; use Illuminate\Console\Command; use Illuminate\Contracts\Console\Isolatable; use Illuminate\Support\Facades\Queue; use App\Jobs\ProcessStatisticAggregateStream; class StatisticAggregatesStreamWork extends Command implements Isolatable { // ... existing code ... public function handle(): int { // ... existing code ... while (true) { // 将处理任务推送到队列中 Queue::push(new ProcessStatisticAggregateStream()); // ... existing code ... } } }
namespace App\Jobs; use Illuminate\Support\Facades\Redis; use App\Services\StatisticAggregateStream; class ProcessStatisticAggregateStream { public function handle() { StatisticAggregateStream::digest(); } }
希望这些建议能帮到你!如果还有其他问题,随时来问,我很乐意帮忙。加油!🚀
如果你有其他问题或需要进一步的帮助,随时联系我哦!😊