ZSKIPLIST_MAXLEVEL(64) 够2^64个元素吗?

Is ZSKIPLIST_MAXLEVEL(64) enough for 2^64 elements?

我最近从跳表:平衡树的概率替代中了解了跳表。我认为 p=0.25 的 64 个级别应该有 4^64 个元素(如果 p = 1/2,使用 MaxLevel = 16 适用于最多包含 2^16 个元素的数据结构。--引用自平衡树的概率替代方案) .但是当我检查 Redis server.h 时,我看到

define ZSKIPLIST_MAXLEVEL 64 /* 应该足够 2^64 个元素 */

define ZSKIPLIST_P 0.25 /* 跳表 P = 1/4 */.

是我错了还是配置错了?

You are right. It is fair to say that server.h defines a MAXLEVEL higher than necessary.

The probability that a particular element reaches a level at least k is p^k, and the probability that any of the n elements reaches a level at least k is n·p^k.

Redis uses the skip list for sorted sets, and it uses it in conjunction with a hash map. The hash map (dict) has a capacity of 2^64-1 elements (ready for, not ever tested in practice). Hence the comment on ZSKIPLIST_MAXLEVEL.

It follows that if we use N = 2^64 as an upper bound on the number of elements in the skip list, Redis could have used ZSKIPLIST_MAXLEVEL = 32.

The nodes allocate memory up the level they actually got when rolling the dice. Only the first, null node uses the ZSKIPLIST_MAXLEVEL. The impact: 512 bytes of extra memory per sorted list (of 129 entries or more - before, it uses a ziplist, see zset-max-ziplist-entries config setting).

The other side effect is the chance a node would get an unnecessarily high level, but the odds get really low really fast as we go up beyond the 32nds level.

I think it is worth fixing IMO, for those 512 bytes.