doc: 阅读sorted set文档
This commit is contained in:
@@ -71,6 +71,17 @@
|
|||||||
- [Field Expiration](#field-expiration)
|
- [Field Expiration](#field-expiration)
|
||||||
- [Common field expiration use cases](#common-field-expiration-use-cases)
|
- [Common field expiration use cases](#common-field-expiration-use-cases)
|
||||||
- [Field Expiration examples](#field-expiration-examples)
|
- [Field Expiration examples](#field-expiration-examples)
|
||||||
|
- [Sorted sets](#sorted-sets)
|
||||||
|
- [ZRANGEBYSCORE](#zrangebyscore)
|
||||||
|
- [ZREMRANGEBYSCORE / ZREM](#zremrangebyscore--zrem)
|
||||||
|
- [Inclusive and exclusive](#inclusive-and-exclusive)
|
||||||
|
- [ZRANK / ZREVRANK](#zrank--zrevrank)
|
||||||
|
- [`Lexicographical scores`](#lexicographical-scores)
|
||||||
|
- [ZRANGEBYLEX](#zrangebylex)
|
||||||
|
- [Updating the score: leaderboards](#updating-the-score-leaderboards)
|
||||||
|
- [Leaderboard Example](#leaderboard-example)
|
||||||
|
- [ZADD](#zadd)
|
||||||
|
- [ZINCRBY](#zincrby)
|
||||||
|
|
||||||
|
|
||||||
# redis
|
# redis
|
||||||
@@ -1073,3 +1084,180 @@ print(expire_time)
|
|||||||
# prints [1717668041] # your actual value may vary
|
# prints [1717668041] # your actual value may vary
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sorted sets
|
||||||
|
redis sorted set是一个包含unique strings的集合,其中unique strings会关联一个score,并且strings会按照score进行排序。`如果多个string存在相同的score,那么拥有相同score的strings将会按照字典序进行排序`。
|
||||||
|
|
||||||
|
sorted sets的用例场景包括如下:
|
||||||
|
- `Leaderboards`: 可以通过sorted sets维护一个ordered list,其可被用于实现排行榜
|
||||||
|
- `RateLimiter`: 通过sorted list,可以构建一个`sliding-window rate limiter`,从而避免过多的api调用
|
||||||
|
- 在实现`sliding-window rate limiter`时,可以将时间戳作为score,因为可以快速获取一个时间范围内的调用数量
|
||||||
|
|
||||||
|
可以将sorted sets看作是set和hash的混合,
|
||||||
|
- 和set一样,sorted sets由unique strings组成
|
||||||
|
- 和hash一样,sorted sets中元素由一个关联的floating point value,被称为score
|
||||||
|
|
||||||
|
sorted set的使用示例如下:
|
||||||
|
```redis-cli
|
||||||
|
> ZADD racer_scores 10 "Norem"
|
||||||
|
(integer) 1
|
||||||
|
> ZADD racer_scores 12 "Castilla"
|
||||||
|
(integer) 1
|
||||||
|
> ZADD racer_scores 8 "Sam-Bodden" 10 "Royce" 6 "Ford" 14 "Prickett"
|
||||||
|
(integer) 4
|
||||||
|
```
|
||||||
|
|
||||||
|
`ZADD`和`SADD`类似,但是其接收一个用于表示`score`的额外参数。和`SADD`类似,可以使用`ZADD`来添加多个`score-value pairs`。
|
||||||
|
|
||||||
|
> #### Implementation
|
||||||
|
> sorted sets实现的数据结构中,同时使用了`skip list`和`hash table`两种数据结构,故而每次向zset中添加元素时,其操作的复杂度为o(log(n))`。
|
||||||
|
>
|
||||||
|
> 并且,在获取元素时,由于元素已经被排序,获取操作无需其他的额外开销。
|
||||||
|
|
||||||
|
`ZRANGE`的顺序为从小到大,`ZREVRANGE`的顺序则是从大到小
|
||||||
|
```redis-cli
|
||||||
|
> ZRANGE racer_scores 0 -1
|
||||||
|
1) "Ford"
|
||||||
|
2) "Sam-Bodden"
|
||||||
|
3) "Norem"
|
||||||
|
4) "Royce"
|
||||||
|
5) "Castilla"
|
||||||
|
6) "Prickett"
|
||||||
|
> ZREVRANGE racer_scores 0 -1
|
||||||
|
1) "Prickett"
|
||||||
|
2) "Castilla"
|
||||||
|
3) "Royce"
|
||||||
|
4) "Norem"
|
||||||
|
5) "Sam-Bodden"
|
||||||
|
6) "Ford"
|
||||||
|
```
|
||||||
|
在上述示例中,0和-1代表index位于`[0, len-1]`范围内的元素。(负数代表的含义和`LRANGE`命令中相同)
|
||||||
|
|
||||||
|
在`ZRANGE`命令中指定`withscores`,也能够在返回zset中value时同时返回score:
|
||||||
|
```redis-cli
|
||||||
|
> ZRANGE racer_scores 0 -1 withscores
|
||||||
|
1) "Ford"
|
||||||
|
2) "6"
|
||||||
|
3) "Sam-Bodden"
|
||||||
|
4) "8"
|
||||||
|
5) "Norem"
|
||||||
|
6) "10"
|
||||||
|
7) "Royce"
|
||||||
|
8) "10"
|
||||||
|
9) "Castilla"
|
||||||
|
10) "12"
|
||||||
|
11) "Prickett"
|
||||||
|
12) "14"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ZRANGEBYSCORE
|
||||||
|
除了上述操作外,sorted sets还支持对`operate on ranges`。可以通过`ZRANGEBYSCORE`来实现`get all racers with 10 or fewer points`的操作:
|
||||||
|
```redis-cli
|
||||||
|
> ZRANGEBYSCORE racer_scores -inf 10
|
||||||
|
1) "Ford"
|
||||||
|
2) "Sam-Bodden"
|
||||||
|
3) "Norem"
|
||||||
|
4) "Royce"
|
||||||
|
```
|
||||||
|
上述示例中,`ZRANGEBYSCORE racer_score -inf 10`向redis请求`返回score位于negative infinity和10之间(both included)的元素`。
|
||||||
|
|
||||||
|
#### ZREMRANGEBYSCORE / ZREM
|
||||||
|
如果想要丛zset中移除元素,可以调用`ZREM`命令。同样的,sorted sets也支持`remove ranges of elements`的操作,可通过`ZREMRANGEBYSCORE`命令来实现。
|
||||||
|
```redis-cli
|
||||||
|
> ZREM racer_scores "Castilla"
|
||||||
|
(integer) 1
|
||||||
|
> ZREMRANGEBYSCORE racer_scores -inf 9
|
||||||
|
(integer) 2
|
||||||
|
> ZRANGE racer_scores 0 -1
|
||||||
|
1) "Norem"
|
||||||
|
2) "Royce"
|
||||||
|
3) "Prickett"
|
||||||
|
```
|
||||||
|
上述示例中,通过`ZREMRANGEBYSCORE racer_scores -inf 9`命令实现了`remove all the racers with strictly fewer than 10 points`的操作。
|
||||||
|
|
||||||
|
`ZREMRANGEBYSCORE`会返回其移除的元素个数。
|
||||||
|
|
||||||
|
##### Inclusive and exclusive
|
||||||
|
在使用`ZRANGEBYSCORE`指定`min`和`max`时,可以分别将其指定为`-inf`和`+inf`。故而,在获取zset中比`xx`大或比`xx`小的所有元素时,可以使用`-inf`和`+inf`,此时无需知道当前zset中的最大/最小元素。
|
||||||
|
|
||||||
|
默认情况下,`interval specified by min and max is closed`(inclusive)。但是,可以将其指定为`open interval`(exclusive),只需要在score前添加`(`符号即可,示例如下:
|
||||||
|
```redis-cli
|
||||||
|
ZRANGEBYSCORE zset (1 5
|
||||||
|
```
|
||||||
|
上述示例中,会返回位于`(1, 5]`区间内的元素。
|
||||||
|
|
||||||
|
而`ZRANGEBYSCORE zset (5 (10`命令则是会返回`(5, 10)`区间内的元素。
|
||||||
|
|
||||||
|
#### ZRANK / ZREVRANK
|
||||||
|
sorted sets还支持`get-rank operation`,通过`ZRANK`可以返回`position of an element in the set of ordered elements`。
|
||||||
|
|
||||||
|
`ZREVRANK`命令的作用和`ZRANK`类似,但是`ZREVRANK`返回的值为`从大到小的降序ranking`。
|
||||||
|
|
||||||
|
使用示例如下所示:
|
||||||
|
```redis-cli
|
||||||
|
> ZRANK racer_scores "Norem"
|
||||||
|
(integer) 0
|
||||||
|
> ZREVRANK racer_scores "Norem"
|
||||||
|
(integer) 2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `Lexicographical scores`
|
||||||
|
自redis 2.8其,引入了`getting ranges lexicograhpically`的新特性,其假设sorted set中的所有元素都拥有相同的score。
|
||||||
|
|
||||||
|
与`lexicographical ranges`进行交互的主要命令如下:
|
||||||
|
- ZRANGEBYLEX
|
||||||
|
- ZREVRANGEBYLEX
|
||||||
|
- ZREMRANGEBYLEX
|
||||||
|
- ZLEXCOUNT
|
||||||
|
|
||||||
|
使用示例如下所示:
|
||||||
|
```redis-cli
|
||||||
|
> ZADD racer_scores 0 "Norem" 0 "Sam-Bodden" 0 "Royce" 0 "Castilla" 0 "Prickett" 0 "Ford"
|
||||||
|
(integer) 3
|
||||||
|
> ZRANGE racer_scores 0 -1
|
||||||
|
1) "Castilla"
|
||||||
|
2) "Ford"
|
||||||
|
3) "Norem"
|
||||||
|
4) "Prickett"
|
||||||
|
5) "Royce"
|
||||||
|
6) "Sam-Bodden"
|
||||||
|
> ZRANGEBYLEX racer_scores [A [L
|
||||||
|
1) "Castilla"
|
||||||
|
2) "Ford"
|
||||||
|
```
|
||||||
|
在上述示例中,可以通过`ZRANGEBYLEX`按照字典序对range进行请求。
|
||||||
|
|
||||||
|
##### ZRANGEBYLEX
|
||||||
|
ZRANGEBYLEX的语法如下:
|
||||||
|
```
|
||||||
|
ZRANGEBYLEX key min max [limit offset count]
|
||||||
|
```
|
||||||
|
和`ZRANGEBYSCORE`命令不同的是,`ZRANGEBYSCORE`在指定范围时,默认是`included`的;而`ZRANGEBYLEX`必须通过`[`和`(`来显式指定inclusive或exclusive。
|
||||||
|
|
||||||
|
而在指定min和max时,`-`和`+`分别则代表negatively infinite和positive infinite。故而,`ZRANGEBYLEX myzset - +`命令代表返回zset中所有的元素。
|
||||||
|
|
||||||
|
#### Updating the score: leaderboards
|
||||||
|
支持对sorted set中元素的score进行更新。在更新sorted set中元素的score时,只需要`再次调用ZADD命令即可`,sorted set会更新score,更新操作的时间复杂度为`O(log(N))`。
|
||||||
|
|
||||||
|
#### Leaderboard Example
|
||||||
|
在通过zset实现leaderboard时,由如下两种方式对user score进行更新:
|
||||||
|
- 在得知user当前score的情况下,可以直接通过`ZADD`命令来进行覆盖
|
||||||
|
- 如果想要针对当前的score进行`增加`操作时,可以使用`ZINCRBY`命令
|
||||||
|
|
||||||
|
```redis-cli
|
||||||
|
> ZADD racer_scores 100 "Wood"
|
||||||
|
(integer) 1
|
||||||
|
> ZADD racer_scores 100 "Henshaw"
|
||||||
|
(integer) 1
|
||||||
|
> ZADD racer_scores 150 "Henshaw"
|
||||||
|
(integer) 0
|
||||||
|
> ZINCRBY racer_scores 50 "Wood"
|
||||||
|
"150"
|
||||||
|
> ZINCRBY racer_scores 50 "Henshaw"
|
||||||
|
"200"
|
||||||
|
```
|
||||||
|
##### ZADD
|
||||||
|
当当前添加的元素已经在sorted set中存在时,`ZADD`命令会返回`0`,否则`ZADD`命令会返回`1`。
|
||||||
|
|
||||||
|
##### ZINCRBY
|
||||||
|
而`ZINCRBY`命令则是会返回更新后的new score。
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user