我有一个由redis管理的排序集,其成员的分数是动态更新的(通过zadd)。我们说当前的集合如下:
(10, A)
(20, B)
(20, C)
(30, D)
注意项目B和C的重复分数的项目。 现在说我们想要从成员C开始获取所有项目。我们还有一个我们前一段时间获得的C(即20)的最后一个已知分数(例如,作为前一个范围命令的结果)。
所以我们可以这样做:
ZRANGEBYSCORE myzset 20 +inf WITHSCORES
由于B与C的得分相同,我们首先得到(20,B)元组。 然后我们可以通过扫描具有相同分数的项目来按字典顺序找到(20,C)。但问题是:如果集合很大并且重复分数的数量也很大,该怎么办?这是大量的扫描......加上不需要的物品的网络开销。
另一个解决方案是使用
获得(20,C)的等级ZRANK myzset C
这将给我们2,我们将它提供给ZRANGE:
ZRANGE myzset 2 +inf WITHSCORES
但是如果在我们调用ZRANK之前实际移动/重新调整C,那么问题就会出现。例如,如果新的C得分为50,ZRANK将返回该组中的最后位置,因此我们将仅获取(50,C)并错过所有剩余项目。
我认为这样做的一种合适方式是通过元组得到一个zrange。像
这样的东西ZRANGE (20,C) +Inf
即使有很多重复分数为20,这仍然会给O(Log(N))搜索(20,C)。 这也可以保护我们免于C移动到底部,因为元组范围结果将从下一个项目(30,D)开始,然后是(50,C)
例如,Cassandra有一种称为多列限制的特殊语法,其中聚类键可以作为元组进行比较:(得分,成员)> =(20,'C')。在java中,拥有一对SortedSet也是非常简单的。 但不幸的是,Redis似乎没有暴露这种访问模式。
那么上述问题的解决方法是什么?