CloudFog API Gateway

Limited Time

200+ AI Models Integration Hub

Claim Offer Now
Resolvedmysql

Laravel 11 项目性能优化:如何加速 Redis 7 数据流处理?🚀

程序员小王

1/8/2025

108 views6 likes

嘿,大家好!👋

我最近在搞一个 Laravel 11 项目,使用 Redis 7 来处理数据流,结果在高峰期的时候,Redis 的流数据堆积得比处理速度还快,真是让人头大!😅

项目需要快速和高级的报告功能,我有个模型叫 StatisticAggregate,它会随着一天的进展来聚合数据。每次有新的 session,就会更新或创建一行数据。为了高效,我用的是 MySQL 8 的 upsert,因为有几百条数据需要更新或插入。

数据是通过 Redis 流来追加的,然后我用一个自定义的 artisan 命令(类似 Laravel Pulse)来无限循环地从流中拉取数据并 upsert 到数据库。问题是,随着一天的进展,流中的数据堆积得比处理速度还快。处理 1000 条数据大约需要 20-30 秒,也就是每分钟 2000 条,但高峰期每分钟有 5000 条以上的数据涌入。😩

我不认为是数据库的瓶颈,因为即使 Redis 中有大量积压,表中有 10 万行数据,系统负载下降时,积压的数据会在一夜之间处理完。如果是表慢的话,应该会在这里显现出来。

我是不是漏掉了什么关键的代码优化呢?求各位大佬指点!🙏

这是我的 worker 代码:

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, 性能优化, 数据流处理

1 Answers

工程师Alex

1/8/2025

Best Answer10

Answer #1 - Best Answer

嘿,你好啊!👋

我太理解你遇到的 Redis 数据流处理瓶颈了,之前我也在类似的项目中遇到过这种情况,真是让人头疼!😅 但别担心,我们一起来看看怎么优化这个问题。

解决方案

首先,确保你的 Redis 和 MySQL 都是最新的版本,并且配置是为高性能优化的。接下来,我们可以从以下几个方面来优化你的代码:

  1. 批量处理:你提到每次处理 1000 条数据,试着增加这个批量大小,看看是否能提高效率。Redis 和 MySQL 都能很好地处理批量操作。

  2. 并行处理:考虑使用 Laravel 的队列系统来并行处理数据流。这样可以充分利用多核 CPU 的优势。

  3. 异步处理:如果可以,尝试将一些非关键任务异步化,比如日志记录。

  4. Redis 配置优化:确保 Redis 的 maxmemory-policy 设置为 allkeys-lruvolatile-lru,以便在内存不足时能更好地管理数据。

  5. 数据库索引:虽然你已经优化过索引,但再检查一下是否有遗漏的地方,尤其是 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(); } }

个人经验提示

  • 监控工具:使用 Redis 和 MySQL 的监控工具来观察性能瓶颈。
  • 日志分析:分析日志以识别可能的瓶颈或错误。
  • 定期重启:在高负载情况下,定期重启 Redis 可能会有帮助。

常见错误

  • 忘记设置 Redis 的持久化选项,导致数据丢失。
  • 没有正确配置 Laravel 队列的连接,导致任务无法并行处理。

希望这些建议能帮到你!如果还有其他问题,随时来问,我很乐意帮忙。加油!🚀

如果你有其他问题或需要进一步的帮助,随时联系我哦!😊

CloudFog API Gateway 🔥 New User Special

💥 New User Offer: Get $1 Credit for ¥0.5

Claim Offer Now