我们知道redis中的过期时间只能作用于key上。对于string数据结构来说,因为它是key/value的形式,只有一个value与key对应,所以当过期时间到了,整个key/value被移除,符合心理预期,皆大欢喜。但好多时候我们用到的是其他数据结构,比如:一个拥有多个元素的集合。由于过期时间只能作用于key(集合数据结构可以理解为集合ID)上,当过期时间到了,整个集合被移除。一般使用集合的场景都不希望各个元素在同一时间过期,有时也希望进行与时间相关的查询,这该怎么办呢?
redis有一种数据结构是Sorted Set,有序集合,它的实现是hash table(element->score, 用于实现zscore及判断element是否在集合内)和skiplist(score->element,按score排序)的混合体。 skiplist有点像平衡二叉树那样,不同范围的score被分成一层一层,每层是一个按score排序的链表。其中zadd/zrem是O(log(N)),zrangebyscore/zremrangebyscore是O(log(N)+M),N是Set大小,M是结果/操作元素的个数。可见,原本可能很大的N被很关键的Log了一下,1000万大小的Set,复杂度也只是几十不到。当然,如果一次命中很多元素M很大那谁也没办法了。
这里我们用到了它如下特性:
1. 元素唯一
2. 每个元素拥有一个score
3. 所有元素依据score进行有序排列
4. 可通过score来进行查询
我们可以借助这些特性来让集合中的元素拥有时间维度。每当add一个元素时,把当前时间的unix