CloudFog API Gateway

Limited Time

200+ AI Models Integration Hub

Claim Offer Now
Resolvedmysql

Laravel 项目求助:如何优化 Redis Stream 和 MySQL 的高并发数据处理?🚀

工程师David

1/10/2025

95 views6 likes

嘿,大家好!👋

我最近在搞一个 Laravel 项目,结果被 Redis 和 MySQL 搞得焦头烂额。😅 我有个自定义的 upsert worker,专门用来处理统计数据的聚合。项目需要快速且高级的报告功能,所以我用 Redis stream 来处理数据,然后用 Laravel 的 artisan 命令来从 stream 中拉数据并 upsert 到 MySQL 8 数据库。

问题是,到了高峰期,Redis stream 填得比我处理得还快!😱 每分钟大概有 5000 条数据进来,但我每分钟只能处理 2000 条。虽然数据库看起来没啥问题,因为晚上负载低的时候,积压的数据都能处理完,但白天就不行了。

我已经尝试了以下方法:

  1. 调整 chunk 大小:我试着调大和调小 chunk 的大小,但似乎没啥效果。
  2. 优化数据库索引:确认了 key_hash 上有唯一索引,upsert 的速度大概 15ms,但还是不够快。
  3. 增加 worker 数量:想过增加 worker 的数量,但担心会不会导致其他问题。

下面是我的 worker 代码片段:

namespace App\Console\Commands\StatisticAggregates; 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; 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(); } } }

我是不是漏掉了什么关键的优化点?或者有其他更好的方法来处理这种高并发的情况?求各位大佬指点迷津!🙏

PS:如果有其他关于 Laravel、Redis 或 MySQL 的优化建议,也欢迎分享!谢谢大家!🌟

1 Answers

程序员小明

1/10/2025

Best Answer3

Answer #1 - Best Answer

嘿,你好啊!👋

我太理解你遇到的 Redis 和 MySQL 高并发处理问题了——我之前也在类似的项目中栽过跟头!😅 让我们一起来看看如何优化你的 Laravel 项目吧。

1. 增加并行处理能力

首先,增加 worker 的数量是个不错的主意,但要小心资源的竞争和锁的问题。你可以使用 Laravel 的队列系统来管理 worker,确保它们不会相互干扰。

// 在你的 worker 中使用队列 dispatch(new ProcessStreamData($data))->onQueue('high');

2. 批量处理数据

你提到每次处理 2000 条数据,考虑使用批量插入/更新来减少数据库交互的次数。Laravel 的 Eloquent 支持批量操作,可以显著提高性能。

// 使用批量插入 DB::table('your_table')->upsert($data, ['key_hash'], ['column1', 'column2']);

3. Redis Stream 的优化

Redis Stream 的处理速度可以通过调整 xrange 的参数来优化。你可以尝试增加 chunk 的大小,但要确保你的 worker 能够处理这些数据。

// 调整 chunk 大小 $entries = collect(Redis::connection('stream')->xrange(self::ingestKey(), '-', '+', 1000));

4. 数据库连接池

确保你的数据库连接池配置合理,避免因为连接数不足导致的瓶颈。你可以在 config/database.php 中调整 connections.mysqlpool 设置。

'mysql' => [ // ... existing config ... 'options' => [ PDO::ATTR_PERSISTENT => true, ], ],

5. 监控和日志

使用 Laravel 的日志系统来监控 worker 的性能,找出瓶颈所在。你可以在 digest 函数中添加一些日志记录。

Log::info('Processing entries', ['count' => $entries->count()]);

6. 个人经验提示

在我的经验中,常见的错误是忽视了 Redis 和 MySQL 的配置优化。确保你的 Redis 配置文件中 maxmemory-policy 设置为 allkeys-lru,以便在内存不足时自动清理旧数据。

结尾

希望这些建议能帮到你!🚀 如果你还有其他问题或者需要进一步的帮助,随时可以找我。加油,你一定能搞定这个项目的!💪

祝好运!🌟

CloudFog API Gateway 🔥 New User Special

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

Claim Offer Now