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

基于Redis存储集合计算排行榜排名的优化方案咨询

Redis排行榜密集排名(含同分场景)解决方案

一、可替代Redis集合的数据结构

如果不想依赖Redis Sorted Set的默认排序逻辑,可考虑以下存储方案:

  • Hash + Sorted Set 组合存储
    • 用Sorted Set存储唯一分数值并排序,保证分数的先后顺序
    • 用Hash表存储每个分数对应的条目ID列表,键为分数,值为条目ID数组
      查询时先从Sorted Set获取排序后的分数序列,再遍历每个分数对应的条目列表,按顺序分配排名,天然适配连续排名(含同分按条目顺序排序的场景)。
  • RedisJSON 结构化存储
    将排序后的整个排行榜以JSON数组形式存储,每次更新时重新计算排序并覆盖写入。适合数据量不大的场景,读取时直接遍历数组,索引+1即为排名,无需额外计算。

二、保留Redis Sorted Set的算法优化

你的现有算法使用find()和findIndex()导致时间复杂度为O(n²),数据量大时效率极低。以下是优化后的O(n)时间复杂度方案:

场景1:同分条目按顺序获连续排名(如示例期望效果)

Redis Sorted Set在分数相同时,会自动按member的字典序排序,返回的列表已经是最终的排名顺序,直接遍历分配排名即可:

// 假设从Redis通过ZREVRANGE(降序)或ZRANGE(升序)获取的排序后数据
const scoring = [
  { entryId: 15, score: 2211500 },
  { entryId: 6, score: 2211000 },
  { entryId: 11, score: 2211000 },
  { entryId: 4, score: 2196000 },
  { entryId: 5, score: 2196000 },
  { entryId: 7, score: 2196000 },
  { entryId: 9, score: 2196000 }
];

// 一次遍历完成排名计算
const rankings = scoring.map(({ entryId }, index) => ({
  entryId,
  rank: index + 1
}));

console.log(rankings);

场景2:同分条目共享同一排名(标准密集排名)

如果需要同分条目获得相同排名,后续排名连续不空缺,可通过一次遍历维护当前排名:

const scoring = [
  { entryId: 15, score: 2211500 },
  { entryId: 6, score: 2211000 },
  { entryId: 11, score: 2211000 },
  { entryId: 4, score: 2196000 },
  { entryId: 5, score: 2196000 },
  { entryId: 7, score: 2196000 },
  { entryId: 9, score: 2196000 }
];

const rankings = [];
let currentRank = 1;
let prevScore = scoring[0]?.score;

for (let i = 0; i < scoring.length; i++) {
  const { entryId, score } = scoring[i];
  // 分数变化时更新当前排名为当前索引+1
  if (score !== prevScore) {
    currentRank = i + 1;
    prevScore = score;
  }
  rankings.push({ entryId, rank: currentRank });
}

console.log(rankings);

内容的提问来源于stack exchange,提问作者Vladimir Štus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:35:23