【问题标题】:why redis zrank's complexity is O(log(N))为什么redis zrank的复杂度是O(log(N))
【发布时间】:2016-05-18 09:11:45
【问题描述】:

Redis zrank.

返回存储在 key 的有序集合中成员的排名,分数从低到高排序。排名(或索引)是从 0 开始的,这意味着得分最低的成员排名为 0。

为什么复杂度是 O(log(N))?成员是按分数排序的,而zrank是按成员查询的。

更新

我找到了可能是答案的东西。

A.当zset被ziplist实现时

  1. 大小小于128
  2. 每个成员的大小小于 64 字节。

所以,ziplist的大小很小,所以不是我讨论的问题。

B.当zset由skiplist实现时 zset的实现是:

typedef struct zset {

    zskiplist *zsl;

    dict *dict;

} zset;

zset同时保存一个dict和一个skiplist。

  1. dict 保持成员与分数的映射。
  2. zsl 是按分数排序的对象的排序列表。该对象同时包含成员和分数。

所以,zrank 是这样的:

  1. 使用 O(1) 时间查找成员的分数。如果没有找到,返回nil

  2. 用找到的分数在zsl中搜索,花费O(log(N))时间。

【问题讨论】:

  • 你说使用从zsl找到的分数搜索,花费O(log(N))时间。,但你只能找到你想要的成员,但你可以'不知道它的等级是什么。
  • @JasonLaw 在 skiplist 的节点中,每个级别都有一个跨度(int)。它将在搜索处理过程中累积。详见:zslGetRank in github.com/antirez/redis/blob/unstable/src/t_zset.c

标签: algorithm redis


【解决方案1】:

成员键很可能存储在某种搜索树中(增加了分支大小,例如this)。

所以元素搜索和排名计算都在 O(logN) 中执行。上面的链接显示了这些操作的示例实现。

【讨论】:

    【解决方案2】:

    Redis 对排序集使用两种编码之一:ziplists 和跳过列表。

    较小的集合是 ziplists,它们的排名复杂度实际上是 O(N)。但是,这被认为是 O(1),因为 ziplist 阈值是恒定的。

    使用跳过列表编码时,排名为 O(LogN),因为搜索的复杂性 - 有关详细信息,请参阅 Wikipedia article about skiplists

    【讨论】:

    • 为什么使用跳过列表编码时排名 O(LogN)?跳过列表是按分数排序的,你可以使用O(LogN)按分数找到成员,但是你怎么知道那个成员的排名呢?
    猜你喜欢
    • 2017-01-25
    • 2022-10-24
    • 2021-11-11
    • 2011-07-09
    • 2012-06-29
    • 2018-11-26
    • 2018-03-19
    • 2021-08-13
    • 1970-01-01
    相关资源
    最近更新 更多