https://www.nowcoder.com/feed/main/detail/0be6e8fbbec845b392380c150c2f560b
正确答案:可以使用 Redis 的有序集合(Sorted Set,ZSet)数据结构,并结合分数(score)和时间戳(timestamp)构造复合排序键。具体实现方式是将 score 取负或乘以一个大数后加上插入时间戳,确保分数相同时按时间先后排序(先到者优先)。推荐做法是:score 为主排序维度,时间戳为次排序维度,通过 score * LARGE_NUMBER + timestamp 的方式合并为一个数值型 score 存入 ZSet。
解答思路:
深度知识讲解:
Redis ZSet 的底层实现:
分数相同如何处理?
如何设计复合 score?
时间戳精度选择:
实际命令示例:
ZADD leaderboard 85001712345678 user1
ZADD leaderboard 85001712345000 user2
ZREVRANGE leaderboard 0 -1 WITHSCORES
结果中 user2 会排在 user1 前面(因为时间更早)
查询排名与反查:
数据解析(从合并 score 提取原始信息):
边界问题:
扩展应用场景:
伪代码示例(插入与查询):
// 定义常量
LARGE = 1000000000000 // 1e12
// 插入用户分数
function add_user_score(user_id, raw_score):
timestamp = current_timestamp_milliseconds() // 如 1712345678901
final_score = raw_score * LARGE + timestamp
redis.zadd("leaderboard", final_score, user_id)
// 获取前 N 名
function get_top_n(n):
result = redis.zrevrange("leaderboard", 0, n-1, withscores=True)
parsed = []
for user_id, total_score in result:
raw_score = total_score // LARGE
time = total_score % LARGE
parsed.append({user_id: user_id, score: raw_score, timestamp: time})
return parsed
// 示例调用
add_user_score("user1", 85) // time=1712345678000 → score=85001712345678000
add_user_score("user2", 85) // time=1712345677000 → score=85001712345677000
get_top_n(10) // user2 排在 user1 前面
注意事项:
综上,Redis ZSet 结合复合 score 是解决“分数优先、时间次之”排序问题的最佳实践。