From 20578b535e31fac21d8099c2ba01f5c4d9739b23 Mon Sep 17 00:00:00 2001 From: asahi Date: Fri, 5 Sep 2025 17:22:26 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20=E9=98=85=E8=AF=BBredis=20list=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 中间件/redis/redis.md | 111 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/中间件/redis/redis.md b/中间件/redis/redis.md index dbe2d91..fb80f7d 100644 --- a/中间件/redis/redis.md +++ b/中间件/redis/redis.md @@ -40,6 +40,16 @@ - [json object操作](#json-object操作) - [format output](#format-output) - [Limitation](#limitation) + - [Redis lists](#redis-lists) + - [Blocking commands](#blocking-commands) + - [Queue(first in, first out)](#queuefirst-in-first-out) + - [Stack(first in, last out)](#stackfirst-in-last-out) + - [check length of list](#check-length-of-list) + - [Atomically pop one element from one list and push to another](#atomically-pop-one-element-from-one-list-and-push-to-another) + - [trim the list](#trim-the-list) + - [Redis List Impl](#redis-list-impl) + - [`LPUSH, RPUSH`](#lpush-rpush) + - [`LRANGE`](#lrange) # redis @@ -589,3 +599,104 @@ $ redis-cli --raw #### Limitation 传递给command的json值最大深度只能为128,如果嵌套深度大于128,那么command将返回错误。 +### Redis lists +Redis lists为string values的链表,redis list通常用于如下场景: +- 实现stack和queue +- 用于backgroup worker system的队列管理 + +#### Blocking commands +redis lists中支持阻塞命令 +- `BLPOP`: 从`head of a list`移除并且返回一个element,如果list为空,该command会阻塞,直至list被填充元素或发生超时 +- `BLMOVE`: 从source list中pop一个element,并且将其push到target list中。如果source list为空,那么command将会被阻塞,直到source list中出现new element + +> 在上述文档描述中,`阻塞`实际指的是针对客户端的阻塞。该`Blocking Command`命令的调用会实际的阻塞客户端,直到redis server返回结果。 +> +> 但是,`server并不会被blocking command所阻塞`。redis server为单线程模型,当用户发送blocking command给server,并且该command无法立即被执行而导致客户端阻塞时,`server会挂起该客户端的连接`,并且转而处理其他请求,直至该客户端的阻塞命令满足执行条件时,才会将挂起的连接唤醒重新执行。 +> +> 故而,`Blocking Command`并不会对server造成阻塞,而是会阻塞客户端的调用。 + +#### Queue(first in, first out) +依次调用`LPUSH`后再依次调用`RPOP`,可模拟队列行为,元素的弹出顺序和元素的添加顺序相同: +```redis-cli +> LPUSH bikes:repairs bike:1 +(integer) 1 +> LPUSH bikes:repairs bike:2 +(integer) 2 +> RPOP bikes:repairs +"bike:1" +> RPOP bikes:repairs +"bike:2" +``` +#### Stack(first in, last out) +依次调用`LPUSH`后再依次调用`LPOP`,可模拟栈的行为,元素的移除顺序和添加顺序相反: +```redis-cli +> LPUSH bikes:repairs bike:1 +(integer) 1 +> LPUSH bikes:repairs bike:2 +(integer) 2 +> LPOP bikes:repairs +"bike:2" +> LPOP bikes:repairs +"bike:1" +``` +#### check length of list +可通过`LLEN`命令来检查list的长度 +```redis-cli +> LLEN bikes:repairs +(integer) 0 +``` +#### Atomically pop one element from one list and push to another +通过`lmove`命令能够实现原子的`从srclist移除并添加到dstlist`的操作 +```redis-cli +> LPUSH bikes:repairs bike:1 +(integer) 1 +> LPUSH bikes:repairs bike:2 +(integer) 2 +> LMOVE bikes:repairs bikes:finished LEFT LEFT +"bike:2" +> LRANGE bikes:repairs 0 -1 +1) "bike:1" +> LRANGE bikes:finished 0 -1 +1) "bike:2" +``` +#### trim the list +可以通过`LTRIM`命令来完成对list的裁剪操作: +```redis-cli +> LPUSH bikes:repairs bike:1 +(integer) 1 +> LPUSH bikes:repairs bike:2 +(integer) 2 +> LMOVE bikes:repairs bikes:finished LEFT LEFT +"bike:2" +> LRANGE bikes:repairs 0 -1 +1) "bike:1" +> LRANGE bikes:finished 0 -1 +1) "bike:2" +``` +#### Redis List Impl +redis lists是通过Linked List来实现的,其元素的添加操作并开销永远是常量的,并不会和Array一样因扩容而可能导致内存的复制。 + +#### `LPUSH, RPUSH` +`LPUSH`会将元素添加到list的最左端(头部),而`RPUSH`则会将新元素添加奥list的最右端(尾部)。 + +LPUSH和RPUSH接收的参数都是可变的,在单次调用中可以向list中添加多个元素。 + +例如,向空list中调用`lpush 1 2 3`时,其等价于`lpush 1; lpush 2; lpush3`,即调用后list中元素为`3,2,1` + +#### `LRANGE` +`LRANGE`命令能够从list中解析范围内的数据,其接收两个indexes,为range中开始和结束元素的位置。index可以是负的,负数代表从尾端开始计数: +- `-1`代表最后的元素 +- `-2`代表倒数第二个元素 + +```redis-cli +> RPUSH bikes:repairs bike:1 +(integer) 1 +> RPUSH bikes:repairs bike:2 +(integer) 2 +> LPUSH bikes:repairs bike:important_bike +(integer) 3 +> LRANGE bikes:repairs 0 -1 +1) "bike:important_bike" +2) "bike:1" +3) "bike:2" +```