doc: 阅读redis lists文档
This commit is contained in:
@@ -50,6 +50,12 @@
|
||||
- [Redis List Impl](#redis-list-impl)
|
||||
- [`LPUSH, RPUSH`](#lpush-rpush)
|
||||
- [`LRANGE`](#lrange)
|
||||
- [`LPOP, RPOP`](#lpop-rpop)
|
||||
- [Common use cases for lists](#common-use-cases-for-lists)
|
||||
- [Capped lists - `latest n`](#capped-lists---latest-n)
|
||||
- [Blocking operations on lists](#blocking-operations-on-lists)
|
||||
- [BRPOP](#brpop)
|
||||
- [Automatic Creation and removal of keys](#automatic-creation-and-removal-of-keys)
|
||||
|
||||
|
||||
# redis
|
||||
@@ -700,3 +706,148 @@ LPUSH和RPUSH接收的参数都是可变的,在单次调用中可以向list中
|
||||
2) "bike:1"
|
||||
3) "bike:2"
|
||||
```
|
||||
#### `LPOP, RPOP`
|
||||
lists支持pop元素,从list中移除元素,并且获取元素的值。lists支持从list的左端和右端pop元素,使用示例如下所示:
|
||||
```redis-cli
|
||||
> RPUSH bikes:repairs bike:1 bike:2 bike:3
|
||||
(integer) 3
|
||||
> RPOP bikes:repairs
|
||||
"bike:3"
|
||||
> LPOP bikes:repairs
|
||||
"bike:1"
|
||||
> RPOP bikes:repairs
|
||||
"bike:2"
|
||||
> RPOP bikes:repairs
|
||||
(nil)
|
||||
```
|
||||
|
||||
#### Common use cases for lists
|
||||
redis lists拥有如下有代表性的用例场景:
|
||||
- 记录用户最新上传的推文
|
||||
- 用于进程间的通信,使用consumer-producer pattern,其中生产者向lists中推送内容,而消费者消费lists中的内容
|
||||
|
||||
#### Capped lists - `latest n`
|
||||
在许多用例场景下,会使用lists来存储latest items,例如`social network updates, logs`等。
|
||||
|
||||
redis允许将lists作为`拥有容量上限的集合使用`,可以通过`LTRIM`命令来实现`only remembering the latest N items and discarding all the oldest items`。
|
||||
|
||||
`LTRIM`命令和`LRANGE`类似,但是`LRANGE`用于获取获取list中指定范围内的元素,`LTRIM`会将选中的范围作为`new list value`,所有位于选中范围之外的元素都会从list中被移除。
|
||||
|
||||
`LTRIM`的使用示例如下所示:
|
||||
```redis-cli
|
||||
> RPUSH bikes:repairs bike:1 bike:2 bike:3 bike:4 bike:5
|
||||
(integer) 5
|
||||
> LTRIM bikes:repairs 0 2
|
||||
OK
|
||||
> LRANGE bikes:repairs 0 -1
|
||||
1) "bike:1"
|
||||
2) "bike:2"
|
||||
3) "bike:3"
|
||||
```
|
||||
`LTRIM 0 2`会令redis保留index位于`[0, 2]`范围内的3个元素,并且移除其他的元素。将`push操作`和`LTRIM`操作组合,可以实现`add a new element and discard elements exceeding a limt`的操作。
|
||||
|
||||
例如,使用`LRANGE -3 -1`可用于实现`仅保留最近添加的三个元素`的场景
|
||||
|
||||
```redis-cli
|
||||
> RPUSH bikes:repairs bike:1 bike:2 bike:3 bike:4 bike:5
|
||||
(integer) 5
|
||||
> LTRIM bikes:repairs -3 -1
|
||||
OK
|
||||
> LRANGE bikes:repairs 0 -1
|
||||
1) "bike:3"
|
||||
2) "bike:4"
|
||||
3) "bike:5"
|
||||
```
|
||||
|
||||
#### Blocking operations on lists
|
||||
lists的`blocking operation`特性令其适合用于实现queues,并广泛用于进程间通信系统。
|
||||
|
||||
在通过redis lists实现进程间通信系统时,如果某些时刻list为空,并不存在任何元素,那么此时消费者client在调用`pop`操作时只会返回为空。通常来讲,consumer会等待一定的时间并且重新尝试调用pop,该操作被称为`polling`,其通常被认为是一种不好的实现:
|
||||
- 其会强制redis/client来处理无用的命令(`当list为空时,pop请求只会返回为空而不会任何的实际处理`)
|
||||
- 会增加`delay to processing of items`,因为worker在接收到redis server返回的null时,其会等待一定的时间。为了令delay更小,可以在调用POP操作之间等待更短的时间,但是其可能方法前一个问题(`当pop调用之间的时间间隔更小时,redis server可能会处理更多的无用命令`)
|
||||
|
||||
故而,redis实现支持`BRPOP`和`BLPOP`命令,其命令在list为空时会阻塞:`上述命令造成的阻塞会在list中被添加新元素时返回,如果直到设置的超时到达后,该操作也会返回`。
|
||||
|
||||
`BRPOP`的使用示例如下所示:
|
||||
```redis-cli
|
||||
> RPUSH bikes:repairs bike:1 bike:2
|
||||
(integer) 2
|
||||
> BRPOP bikes:repairs 1
|
||||
1) "bikes:repairs"
|
||||
2) "bike:2"
|
||||
> BRPOP bikes:repairs 1
|
||||
1) "bikes:repairs"
|
||||
2) "bike:1"
|
||||
> BRPOP bikes:repairs 1
|
||||
(nil)
|
||||
(2.01s)
|
||||
````
|
||||
上述示例中,`BRPOP bikes:repairs 1`代表`wait for elements in the list bikes:repairs`,但是`当list中元素为空时,最多等待1s。`
|
||||
|
||||
当为`BRPOP`指定timeout为0时,代表会永久等待elements。并且,`可以为BRPOP`命令指定多个lists,其会`等待所有的list,并且当任何一个list中接收到元素时,当前BRPOP命令会立刻返回`。
|
||||
|
||||
示例如下:
|
||||
```redis-client
|
||||
# client 1 等待 event-queue:1, event-queue:2, event-queue:3三个list
|
||||
client 1> brpop event-queue:1 event-queue:2 event-queue:3 1000
|
||||
|
||||
# client 2 向event-queue:2 中追加元素
|
||||
client 2> rpush event-queue:2 baka
|
||||
(integer) 1
|
||||
|
||||
# client 1 立刻返回,返回结果如下
|
||||
1) "event-queue:2"
|
||||
2) "baka"
|
||||
(19.55s)
|
||||
```
|
||||
##### BRPOP
|
||||
- 对于`BRPOP`命令造成的阻塞,其处理是按照顺序的:`the first client that blocked waiting for a list, is served first when an element is pushed by some other client, and so forth`
|
||||
- `BRPOP`命令的返回结果其结构和`RPOP`命令不同:`BRPOP`返回的是一个包含两个元素的array,`arrary[0]`为list对应的key,`array[1]`为弹出的元素(因为BRPOP可以等待多个list)
|
||||
- 如果超时后list中仍然没有可获取的元素,那么将会返回null
|
||||
|
||||
#### Automatic Creation and removal of keys
|
||||
在先前示例中,向list中添加元素时,并没有预先创建空的list,或是在list中没有元素时将list手动移除。
|
||||
|
||||
在redis中,`list的创建和删除都是redis的职责`:
|
||||
- 当list中不再包含元素时,redis会自动删除list对应的key
|
||||
- 当想要对不存在的key中添加元素时,redis会自动创建一个empty list
|
||||
|
||||
故而,可以整理除如下准则:
|
||||
- 当将元素添加到一个聚合数据类型时,如果target key不存在,那么在添加元素前一个empty aggregate data type将会被自动创建
|
||||
- 当从aggregate data type中移除元素时,如果移除后该aggregate data type中为空,那么key将会被自动销毁(`stream data type`除外)
|
||||
- 调用一个read-only command(例如`LLEN`)或write command(用于移除元素)对一个`empty key`做操作时,其返回结果和针对`an key holding an empty aggregate type of type the command expects to find`的操作一直
|
||||
|
||||
上述三个准则的示例如下:
|
||||
|
||||
准则1示例如下所示,当new_bikes不存在时,通过`LPUSH`命令向其中添加元素,一个empty list在添加前会自动创建
|
||||
```redis-cli
|
||||
> DEL new_bikes
|
||||
(integer) 0
|
||||
> LPUSH new_bikes bike:1 bike:2 bike:3
|
||||
(integer) 3
|
||||
```
|
||||
|
||||
准则2示例如下所示,当pop出所有的元素后,key将会被自动销毁,通过`EXISTS`命令返回的结果为0:
|
||||
```redis-cli
|
||||
> LPUSH bikes:repairs bike:1 bike:2 bike:3
|
||||
(integer) 3
|
||||
> EXISTS bikes:repairs
|
||||
(integer) 1
|
||||
> LPOP bikes:repairs
|
||||
"bike:3"
|
||||
> LPOP bikes:repairs
|
||||
"bike:2"
|
||||
> LPOP bikes:repairs
|
||||
"bike:1"
|
||||
> EXISTS bikes:repairs
|
||||
(integer) 0
|
||||
```
|
||||
准则3的示例如下所示,当key不存在时,对该key进行`read-only`操作和`remove element`操作所返回的结果,和对`empty aggregated data type`操作所返回的结果一致:
|
||||
```redis-cli
|
||||
> DEL bikes:repairs
|
||||
(integer) 0
|
||||
> LLEN bikes:repairs
|
||||
(integer) 0
|
||||
> LPOP bikes:repairs
|
||||
(nil)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user