哈希算法题目:设计一个基于哈希的分布式实时排行榜系统(支持分数更新和Top K查询)
字数 1272 2025-11-04 11:59:17
哈希算法题目:设计一个基于哈希的分布式实时排行榜系统(支持分数更新和Top K查询)
题目描述:设计一个分布式实时排行榜系统,支持以下操作:
addScore(playerId, score)- 为玩家添加分数(可正可负)top(k)- 返回前k名最高分的玩家IDreset(playerId)- 重置玩家的分数为0
系统需要支持高并发访问,并且要保证在大数据量下的查询效率。
解题过程:
第一步:分析需求和数据特点
- 玩家数量可能达到百万级别
- 分数会频繁更新,需要支持高并发写入
- Top K查询需要快速响应
- 需要支持分布式部署
第二步:设计基本数据结构
我们需要两个核心数据结构:
-
哈希表:存储玩家ID到当前分数的映射
- 键:playerId(字符串或整数)
- 值:当前分数(整数)
- 作用:支持O(1)时间查询和更新单个玩家的分数
-
有序集合:按分数排序的玩家集合
- 使用跳表(Skip List)或平衡树实现
- 支持按分数范围快速查询
- 支持O(log n)时间的插入、删除和更新
第三步:详细设计操作流程
addScore操作:
- 在哈希表中查找玩家当前分数
- 如果玩家不存在,初始化分数为0
- 计算新分数 = 旧分数 + 输入分数
- 从有序集合中删除旧的分数记录(如果存在)
- 将新分数插入有序集合
- 更新哈希表中的分数值
示例代码逻辑:
def addScore(playerId, score):
# 1. 从哈希表获取当前分数
old_score = hash_map.get(playerId, 0)
# 2. 计算新分数
new_score = old_score + score
# 3. 如果之前有分数,从有序集合删除旧记录
if old_score != 0:
sorted_set.remove((old_score, playerId))
# 4. 插入新记录到有序集合
sorted_set.add((new_score, playerId))
# 5. 更新哈希表
hash_map[playerId] = new_score
top(k)操作:
- 从有序集合的尾部(分数最高端)开始遍历
- 取前k个元素
- 返回对应的玩家ID列表
def top(k):
results = []
# 从分数最高端开始遍历(降序排列)
for i in range(min(k, len(sorted_set))):
# 获取第i高的分数和玩家ID
score, playerId = sorted_set[-1-i]
results.append(playerId)
return results
reset操作:
def reset(playerId):
if playerId in hash_map:
old_score = hash_map[playerId]
# 从有序集合中删除
sorted_set.remove((old_score, playerId))
# 从哈希表中删除或设为0
hash_map[playerId] = 0
# 插入0分记录(如果需要显示在排行榜中)
sorted_set.add((0, playerId))
第四步:处理分布式场景
在分布式环境中,我们需要考虑数据分片:
数据分片策略:
-
按玩家ID分片:将玩家哈希到不同的服务器节点
- 优点:单个玩家的操作都在同一节点完成
- 挑战:Top K查询需要合并所有节点的数据
-
全局有序集合的维护:
- 每个节点维护自己分片内的局部排行榜
- 定期合并局部排行榜生成全局排行榜
- 使用缓存机制存储最近的Top K结果
分布式Top K查询优化:
-
阈值算法(TA算法):
- 并行查询所有分片,按分数降序获取记录
- 维护一个最小堆来合并结果
- 当已经收集到k个分数不低于其他分片当前最高分的记录时停止
-
缓存策略:
- 缓存最近的Top K查询结果
- 设置合适的缓存过期时间
- 当分数更新时,使受影响的缓存失效
第五步:处理并发和一致性
并发控制:
- 使用细粒度锁:对每个玩家ID使用独立的锁
- 乐观锁:使用版本号或CAS操作
- 读写分离:读操作访问副本,写操作访问主节点
一致性保证:
- 最终一致性:允许短暂的数据不一致
- 使用事务保证哈希表和有序集合的原子更新
- 写入日志进行故障恢复
第六步:性能优化
内存优化:
- 使用压缩数据结构存储分数
- 对玩家ID使用字符串驻留(string interning)
- 定期清理分数为0的不活跃玩家
查询优化:
- 使用布隆过滤器快速判断玩家是否存在
- 对频繁查询的Top K结果进行预计算
- 使用多级缓存减少数据库访问
这个设计结合了哈希表的快速查找和有序集合的高效排序,通过分布式架构支持水平扩展,能够满足大规模实时排行榜的需求。