共计 2171 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在 AI 视频生成网站的排行榜场景中,我们面临几个典型的技术挑战:

- 高并发查询压力 :热门榜单往往占据 80% 以上的流量,尤其在早晚高峰时段
- 实时性要求 :用户期望看到分钟级更新的播放量、点赞数等动态数据
- 数据一致性 :榜单更新期间要保证排名计算的原子性,避免出现跳变
- 多维排序 :需综合播放量、点赞率、时效性等动态权重因子
技术选型对比
1. 纯数据库方案
- 优点 :开发简单,直接利用 SQL 的 ORDER BY
- 缺点 :
- 大数据量表排序性能差(O(nlogn) 复杂度)
- 高并发时容易成为系统瓶颈
2. Redis SortedSet
- 优点 :
- O(logN) 的 zadd/zrange 时间复杂度
- 天然适合单维度排序场景
- 缺点 :
- 多维度组合排序实现复杂
- 数据持久化需要额外方案
3. Elasticsearch
- 优点 :
- 支持动态权重计算公式
- 分布式架构天然可扩展
- 内置聚合分析功能
- 缺点 :
- 资源消耗较大
- 需要维护索引映射
核心实现方案
1. 混合架构设计
flowchart TD
A[客户端] -->| 查询请求 | B[CDN]
B --> C{本地缓存命中?}
C -->|Yes| D[返回缓存数据]
C -->|No| E[Redis 集群]
E --> F{Redis 命中?}
F -->|Yes| G[返回并写入本地缓存]
F -->|No| H[Elasticsearch 集群]
H --> I[计算实时排名]
I --> J[写入 Redis+ 本地缓存]
2. 权重分计算模型
// 基于 Elasticsearch 的 function_score 实现
Map<String, Double> weights = Map.of(
"play_count", 0.5,
"like_rate", 0.3,
"time_decay", 0.2
);
FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery()
.add(ScoreFunctionBuilders.fieldValueFactorFunction("play_count")
.factor(weights.get("play_count"))
.modifier(FieldValueFactorFunction.Modifier.LOG1P))
.add(ScoreFunctionBuilders.gaussDecayFunction("create_time",
new DateTime().minusHours(24).toInstant(),
"3h")
.weight(weights.get("time_decay")));
3. 缓存策略实现
// 多级缓存加载逻辑
public List<VideoRank> getHotRank(int size) {
// 1. 检查本地缓存
List<VideoRank> localCache = caffeineCache.getIfPresent("hot_rank");
if (localCache != null) return localCache;
// 2. 检查 Redis 缓存
try (Jedis jedis = jedisPool.getResource()) {Set<String> cacheSet = jedis.zrevrange("hot_rank", 0, size-1);
if (!cacheSet.isEmpty()) {List<VideoRank> result = parseFromCache(cacheSet);
caffeineCache.put("hot_rank", result);
return result;
}
}
// 3. 回源 ES 查询
List<VideoRank> dbResult = loadFromElasticsearch(size);
// 4. 异步更新缓存
executorService.submit(() -> {updateRedisCache(dbResult);
caffeineCache.put("hot_rank", dbResult);
});
return dbResult;
}
生产环境建议
1. 冷热数据分离
- 热数据 :TOP 1000 视频保持 Redis 常驻
- 温数据 :TOP 10,000 使用 ES 实时计算
- 冷数据 :历史数据归档到 HBase
2. 监控指标设计
| 指标名称 | 采集方式 | 告警阈值 |
|---|---|---|
| 99 分位延迟 | Prometheus + Grafana | >500ms |
| 缓存命中率 | Redis INFO 命令 | <90% |
| ES 节点负载 | _cat/nodes API | CPU>70% |
3. 压测数据对比
| 方案 | QPS(单节点) | 99% 延迟 | 数据一致性 |
|---|---|---|---|
| MySQL ORDER BY | 1,200 | 450ms | 强一致 |
| Redis SortedSet | 35,000 | 12ms | 最终一致 |
| ES+Redis 混合 | 28,000 | 25ms | 最终一致 |
延伸思考
榜单公平性保障
-
时间衰减算法 :防止老视频长期霸榜
# 指数衰减公式示例 def time_decay(create_time, half_life=24): hours = (now - create_time) / 3600 return 0.5 ** (hours / half_life) -
反作弊策略 :
- 基于用户 IP/ 设备指纹的投票去重
-
异常流量检测(如突然暴增的播放量)
-
分区榜单设计 :
- 按视频时长分段(短视频 / 长视频)
- 按内容类别分榜(教学类 / 娱乐类)
实际落地时建议采用 A / B 测试验证不同算法效果,最终选择符合产品定位的排序策略。
正文完
发表至: 技术架构
五天前
