doc: 阅读sorted set文档
This commit is contained in:
@@ -71,6 +71,17 @@
|
||||
- [Field Expiration](#field-expiration)
|
||||
- [Common field expiration use cases](#common-field-expiration-use-cases)
|
||||
- [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
|
||||
@@ -1073,3 +1084,180 @@ print(expire_time)
|
||||
# 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