如何在Redis的ZRANK中获得相同分数的相同排名? [英] How to get same rank for same scores in Redis' ZRANK?

查看:32
本文介绍了如何在Redis的ZRANK中获得相同分数的相同排名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有 5 个成员的分数如下

If I have 5 members with scores as follows

a - 1
b - 2
c - 3
d - 3
e - 5

c 的 ZRANK 返回 2,d 的 ZRANK 返回 3

有没有办法获得相同分数的相同排名?
示例:ZRANK c = 2, d = 2, e = 3
如果是,那么如何在 spring-data-redis 中实现它?

ZRANK of c returns 2, ZRANK of d returns 3

Is there a way to get same rank for same scores?
Example: ZRANK c = 2, d = 2, e = 3
If yes, then how to implement that in spring-data-redis?

推荐答案

任何真正的解决方案都需要满足需求,而原始问题中缺少这些需求.我的第一个答案假设了一个小数据集,但这种方法至少不能像在 O(N) 中完成的密集排名(例如通过 Lua)那样扩展.

Any real solution needs to fit the requirements, which are kind of missing in the original question. My 1st answer had assumed a small dataset, but this approach does not scale as dense ranking is done (e.g. via Lua) in O(N) at least.

所以,假设有很多有分数的用户,for_stack建议的方向比较好,多个数据结构组合在一起.我相信这是他最后一句话的要点.

So, assuming that there are a lot of users with scores, the direction that for_stack suggested is better, in which multiple data structures are combined. I believe this is the gist of his last remark.

要存储用户的分数,您可以使用哈希.虽然从概念上讲,您可以使用单个键来存储所有用户分数的 Hash,但在实践中,您希望对 Hash 进行散列以使其可扩展.为了让这个例子简单,我将忽略哈希缩放.

To store users' scores you can use a Hash. While conceptually you can use a single key to store a Hash of all users scores, in practice you'd want to hash the Hash so it will scale. To keep this example simple, I'll ignore Hash scaling.

这是您在 Lua 中添加(更新)用户分数的方式:

This is how you'd add (update) a user's score in Lua:

local hscores_key = KEYS[1]
local user = ARGV[1]
local increment = ARGV[2]
local new_score = redis.call('HINCRBY', hscores_key, user, increment)

接下来,我们要跟踪每个离散分值的当前用户数,因此我们为此保留另一个散列:

Next, we want to track the current count of users per discrete score value so we keep another hash for that:

local old_score = new_score - increment
local hcounts_key = KEYS[2]
local old_count = redis.call('HINCRBY', hcounts_key, old_score, -1)
local new_count = redis.call('HINCRBY', hcounts_key, new_score, 1)

现在,我们需要维护的最后一件事是每个分数排名,有一个排序的集合.每一个新的分数都被添加为 zset 中的一个成员,并删除没有更多用户的分数:

Now, the last thing we need to maintain is the per score rank, with a sorted set. Every new score is added as a member in the zset, and scores that have no more users are removed:

local zdranks_key = KEYS[3]
if new_count == 1 then
  redis.call('ZADD', zdranks_key, new_score, new_score)
end
if old_count == 0 then
  redis.call('ZREM', zdranks_key, old_score)
end

由于使用了 Sorted Set,这个 3-piece-script 的复杂度是 O(logN),但请注意,N 是离散分数值的数量,而不是系统中的用户.获取用户的密集排名是通过另一个更短更简单的脚本完成的:

This 3-piece-script's complexity is O(logN) due to the use of the Sorted Set, but note that N is the number of discrete score values, not the users in the system. Getting a user's dense ranking is done via another, shorter and simpler script:

local hscores_key = KEYS[1]
local zdranks_key = KEYS[2]
local user = ARGV[1]

local score = redis.call('HGET', hscores_key, user)
return redis.call('ZRANK', zdranks_key, score)

这篇关于如何在Redis的ZRANK中获得相同分数的相同排名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆