PHP十万级用户排行榜查询用户排名性能优化问题咨询
性能优化方案
代码层即时优化(无需改架构,直接替换原有逻辑)
原有逻辑的核心问题是PHP用户态手写循环遍历10万级数据,执行效率极低,同时存在两处可优化的冗余逻辑:
- 循环条件中每次都调用
count($table['users']),存在重复函数调用开销 - 纯PHP实现的遍历匹配逻辑,性能远低于PHP内置的C语言实现的数组操作函数
直接替换原有逻辑的最优代码如下,性能可提升30~50倍:
<?php $res = []; // 提取Top10用内置array_slice(C实现)比PHP手写循环效率高 $top10Raw = array_slice($table['users'], 0, 10); foreach ($top10Raw as $user) { if ($user['value'] === null) { break; } $res['users'][] = [ 'value' => $user['value'], 'user_id' => $user['user_id'], 'name' => $user['name'] ]; } // 用内置函数查排名,完全避免PHP用户态循环 $allUserId = array_column($table['users'], 'user_id'); $matchIndex = array_search($user_id, $allUserId); // 初始化默认值避免未定义变量报错 $res['currentTop'] = $matchIndex === false ? 0 : $matchIndex + 1; echo json_encode($res, JSON_UNESCAPED_UNICODE);
架构层高并发优化(适合线上生产环境)
如果榜单不需要秒级实时更新,可通过缓存方案进一步把性能提升100倍以上:
- 榜单更新时预生成两份缓存数据:Top10列表、
user_id=>排名的哈希映射表,缓存时间根据业务对实时性的要求设置为1~10分钟 - 每次请求直接从缓存读取数据,O(1)复杂度即可拿到结果,完全不需要处理10万级数组
- 长期方案推荐直接用Redis的ZSet结构存储榜单:取Top10用
zRange、查用户排名用zRank,都是O(logN)复杂度,10万级数据查询延迟稳定在毫秒级,高并发下无性能压力
缓存方案的示例代码如下:
<?php // 假设已实例化Redis对象$redis,缓存key根据业务场景自定义 $top10CacheKey = 'game_rank_top10'; $rankMapCacheKey = 'game_rank_user_rank_map'; // 优先读缓存 $top10 = $redis->get($top10CacheKey); $rankMap = $redis->get($rankMapCacheKey); if (!$top10 || !$rankMap) { // 缓存失效时才重新生成榜单数据 $top10 = []; $rankMap = []; foreach ($table['users'] as $index => $user) { $rankMap[$user['user_id']] = $index + 1; if ($index < 10 && $user['value'] !== null) { $top10[] = $user; } } // 缓存1分钟,可根据需求调整 $redis->setex($top10CacheKey, 60, json_encode($top10, JSON_UNESCAPED_UNICODE)); $redis->setex($rankMapCacheKey, 60, serialize($rankMap)); } else { $top10 = json_decode($top10, true); $rankMap = unserialize($rankMap); } $res['users'] = $top10; $res['currentTop'] = $rankMap[$user_id] ?? 0; echo json_encode($res, JSON_UNESCAPED_UNICODE);
内容的提问来源于stack exchange,提问作者antoshka
相关产品推荐
相关产品推荐

