作者:痴者工良
Redis 基本数据类型
Redis 中,常用的数据类型有以下几种:
- String:字符串类型, 二进制安全字符串;
- Hash:哈希表;
- List 列表:链表结构,按照插入顺序排序的字符串元素的集合;
- Set:集合,元素具有唯一性,未排序的字符串元素集合;
- Sorted Set:有序集合;
- Bit arrays:二进制数据;
Redis 的 Key
Redis 的键是二进制安全的,意味着无论 Key 中的内容是什么,在 Redis 都可以正常使用,例如 Key 中可以包含空格、 \r\n
、 ¥
、 $
等特殊字符,因为它们都会被转为二进制存储,它们不再是具有意义的字符串,而是一堆 01 组成的内容。你可以使用普通字符串做 Key ,也可以使用一张图片做 Key,只要 Key 小于 512MB 即可。
Redis Key 命名
Redis Key 的命名一般都是小写,命名主要以便于阅读为主,同时考虑缩短 Key,减少内存占用,例如 user:1000:followers
便于阅读,而 u1000flw
很短可以减少内存占用,但可读性不高。
Key 可以如果要表达有层次结构,则可以使用 :
组合 ,如要表达 租户(id1)=>技术部(id5)=>后端(id1)=>工号006
,每层对象在数据库中都有一个表存储,且每个对象都有一个 Id,则可以使用 tenant:01:department:05:group:01:user:006
做 Key,在某些工具下,Key 会被以树的形式显示,便于查找,其显示如下图所示:
如果 Key 某一个部分是多词字段,则可以使用 .
或 -
连接,如 comment:1234:reply.to
和 comment:1234:reply-to
,表示 Id 为 1234 的评论被回复的信息列表。
由于 Redis 的 Key 是很宽松的,因此命名规则不必限定,可以根据团队内部讨论觉得使用何种分隔符分割层次、使用长命名还是缩短命名习惯等。
一般更加建议是使用 {对象名称}:{对象标识/id}:{对象属性}
表示,如 用户1
的消息列表表示为 user:1:messages
,如果是租户隔离,还可以表示用户相关信息为 tenant:1:user:1:messages
、 tenant:1:user:1.messages
。
设置 Key 过期时间
Redis 的过期时间设置有四种形式:
- EXPIRE 秒——设置指定的过期时间(秒),表示的是时间间隔。
- PEXPIRE 毫秒——设置指定的过期时间,以毫秒为单位,表示的是时间间隔。
- EXPIREAT 时间戳-秒——设置指定的 Key 过期的 Unix 时间,单位为秒,表示的是时间/时刻。
- PEXPIREAT 时间戳-毫秒——设置指定的 Key 到期的 Unix 时间,以毫秒为单位,表示的是时间/时刻。
如设置一个 Key 在 5s 后过期:
127.0.0.1:6379> expire value 5
(integer) 1
设置 Key 在 2021年11月26日22时过期:
2021-11-26 22:00:00
127.0.0.1:6379> expireat value 1637935200
(integer) 1
有些类型本身或类型的元素的命令参数可以设置过期时间,如 string 类型,可以不使用 expire 等相关命令。
使用 ttl 命令,可以查看一个 Key 的过期时间,返回剩余存活秒数。
2021-11-26 22:00:00
127.0.0.1:6379> expireat value 1637935200
(integer) 1
127.0.0.1:6379> ttl value
(integer) 4760
Redis 7.0 后 expire 命令有以下参数可用:
- NX ——只有当密钥没有过期时才设置过期
- XX — 仅当键具有现有的过期时才设置过期
- GT 仅当新的有效期大于当前有效期时才设置有效期
- LT ——只有当新的有效期小于当前有效期时才设置有效期
笔者在编写这篇文章时,使用的 redis:latest
镜像,其版本是 6.2.6,因此暂未使用这些参数,你可以使用 info
命令查看 Redis 信息:
127.0.0.1:6379> info
Server
redis_version:6.2.6
... ...
Redis 使用 expires 字典存储了所有 Key 的过期时间。
判断键是否存在
exist 命令可以判断一个 Key 是否存在,如果存在则返回 1,否则返回 0 。
redis> exist key1
(integer) 1
redis> exist nosuchkey
(integer) 0
搜索 Key
keys 命令可以搜索符合条件的 Key,如 keys *
则返回全部 key。
搜索以 t 开头的所有 key
keys t*
搜索包含 test 的 key
keys *test*
使用 dbsize 命令可以知道 Key 的数量:
127.0.0.1:6379> dbsize
(integer) 5
scan 则可以指定搜索多少条符合条件的 key:
返回一条以 t 开头的 key
scan 0 match t* count 1
可参考: https://redis.io/commands/scan
can 命令格式入下
scan cursor [MATCH pattern] [COUNT count] [TYPE type]
cursor 是一个游标值,scan 每次结果的是在上一次迭代,表示开始位置,如果不注意,可能会导致查找结果与需要的不一样。如 Redis 中有三个 user:{id}
Key,我想搜索符合条件的这三个值:
127.0.0.1:6379> scan 0 match "user:*" count 5
1) "10"
2) 1) "user:3"
2) "user:1"
搜索结果一直很奇怪。
这是因为是当前游标是 1) "10"
在 10;而且scan 只会返回部分数量的 Key,不会返回所有数量。所以如果要使用 scan 命令,我们要注意以下步骤。
笔者的完整 Key 如下:
1) "test"
2) "user:1"
3) "key"
4) "user:3"
5) "Sicily"
6) "test1"
7) "zset"
8) "deck"
9) "h"
10) "year"
11) "user:2"
注意 user:{id}
的位置。
重置游标:
127.0.0.1:6379> scan 0
1) "7"
2) 1) "Sicily"
2) "user:3"
3) "deck"
4) "test"
5) "user:1"
6) "year"
7) "h"
8) "key"
9) "test1"
10) "zset"
注意,此时游标位置在 7,这个是 Redis 分配的, 具有不确定性。
搜索:
127.0.0.1:6379> scan 0 match "user:*" count 100
1) "0"
2) 1) "user:3"
2) "user:1"
3) "user:2"
首先,当我们使用 scan 0
时,游标重新在 0 开始,因为没有设置值,因此 Redis 分配到了 7。另外游标的意思并不是下次从 7 开始搜索,而是指当前游标识别了 0-7 中的 Key,你下次搜索的结果将会在 0-7 中搜索!因此笔者给其设置了 count 100
,这样游标会一直往下走,直至找到符合数量的 Key 或 Key 已经检索完毕。
要注意, SCAN 命令并不保证每次执行都返回某个给定数量的元素。
如下所示,重置游标后,它自动检索到 7,默认最大 10,此时我们的关键字在 0-7中搜索,不加 count
默认只会找到两个 Key,那么我将 count 数量改成 3,那他不就可以找到三个元素了?这里我们直接设置为 5 试试:
127.0.0.1:6379> scan 0
1) "7"
2) 1) "Sicily"
2) "user:3"
3) "deck"
4) "test"
5) "user:1"
6) "year"
7) "h"
8) "key"
9) "test1"
10) "zset"
127.0.0.1:6379> scan 0 match "user:*" count 5
1) "10"
2) 1) "user:3"
2) "user:1"
结果事与愿违,游标只走到 10 ,并且结果只有两个,而不是 3 个。
如果你把 count 设置大一点,可能便可以搜索到需要的 3 个 Key 了:
127.0.0.1:6379> scan 0 match "user:*" count 11
1) "0"
2) 1) "user:3"
2) "user:1"
3) "user:2"
注意, scan cursor
跟 scan cursor match ...
命令不一样,前者是重置游标检索位置,将范围内的 Key 当搜索结果搜集起来;而 scan cursor match ...
指从哪个位置开始搜索。
在 Redis 的很多类型中,如列表、集合,都支持搜索,它们的命令格式中有个 pattern 字段,其支持 glob 风格的通配符区配格式,也使用这种风格区配 Key。其规则或说明如下:
符号 说明 ? 表示一个任意字符,如 tes?
test
符合结果; * 区配任意数量的字符,如 *
表示所有; t*
表示以 t 开头; [] 区配方括号间的任一个字符,可以使用 -
表示一个范围,与正则表达式类似;如 t[a-d]*
,以 t 开头,第二个字符是 a,b,cd
中的一个; \x x 表示一个字符;用于将前面三个符号转义,使其失去特殊意义,如 \?
\*
另外 Redis 的命令关键字不区分大小写。
判断键类型
type
命令可以获取一个 Key 的 Value 的类型:
127.0.0.1:6379> set value 123455
OK
127.0.0.1:6379> type value
string
127.0.0.1:6379> rpush value2 abc
(integer) 1
127.0.0.1:6379> type value2
list
删除键
del
命令可以删除一个 Key:
127.0.0.1:6379> del value2
(integer) 1
127.0.0.1:6379> del value2 value
(integer) 1
返回删除的 Key 数量;如果 Key 不存在,del 命令不会报错,只会返回受影响的数量;
前面提到, Redis 支持模糊搜索 Key,可以很容易查找符合条件的 Key,但是 Redis 不支持模糊删除 Key。
RESP 协议
RESP 协议用于编写 Redis 客户端,它定义了 Redis 请求和响应的格式内容,当我们使用 redis-cli 工具连接 Redis 并执行命令时,返回的数据格式跟 RESP 有关系,这里简单说一下,Redis 响应的格式主要有:
- 对于 简单字符串,回复的第一个字节是”+”
- 对于 错误,回复的第一个字节是”-“
- 对于 整数,回复的第一个字节是”:”
- 对于 批量字符串,回复的第一个字节是”$”
- 对于 数组,回复的第一个字节是”
*
“
在 redis-cli 或别的工具中,第一个符号可能不会显示,例如 "+ok"
,在工具中只给用户显示 "ok"
;响应包含 ok
则说明命令执行成功;nil 表示 Null Bulk String,也 nil 可以表达为 ok 的反义,即失败,但不代表发生错误,不同的编程语言客户端应将 nil 表示为其语言的相关空类型,例如 go 语言返回 nil,C# 返回 null,C 语言返回 NULL 等,在 redis-cli 中显示为 (nil)。
以上符号只是对响应内容进行初步解析,具体含义要根据发送的命令以及编程语言特点做二次处理。如 del bar
命令,删除一个 Key,响应内容:
127.0.0.1:6379> del bar
(integer) 0
redis-cli 工具中看到的不是原始的消息内容,如果直接接收 TCP 消息,其内容应该是 :0
,客户端可以通过前面的 :
符号了解到后面的是数字,于是吧 0
截取处理,转为数字;但是这个数字结合 del 命令才有意义,这部分则要看编程语言的特点做处理。
这里不必深入了解 RESP 协议,只需要大概了解使用 redis-cli 等工具执行 Redis 命令时,响应结果代表什么意义即可。
字符串类型
Redis 的字符串类型也是二进制安全的,二进制安全并不是指线程安全,而是指无论你存储什么内容都可以,Redis string 最大可以存储 512 MB,可以往里面塞一些小姐姐视频、图片、网页、文件等都没问题。
面试题:Redis 相比 memcached 有哪些优势
- memcached 只支持简单的字符串类型,而 Redis 支持多种类型;
- Redis 速度更加快;
- Redis 的数据可以持久化;
下面介绍一些 string 常用的指令。
使用 set
、 get
对单个 Key 进行写或读,使用 mset
、 mget
对多个 Key 批量写或读。
> set mykey somevalue
OK
> get mykey
"somevalue"
> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"
默认情况下,当 Key 已存在时, set
、 mset
会替换其值;当 Key 不存在时, set
、 mset
会创建新的 Key,而 Redis 提供了 NX、XX 两个参数,可以改变这种替换或新创建行为。如果一个 Key 存在并具有过期时间等属性时,如果使用 set 等命令替换 Key 时,过期时间等属性会自动消除。
NX:当 Key 不存在时才生效。
127.0.0.1:6379> set key1 666 nx
"OK"
127.0.0.1:6379> set key1 666 nx
(nil)
Key 不存在时,set 命令正常;当 Key 不存在时,set 命令报 nil。
如果响应的信息以-
开头,则表示一个错误。
XX:当 Key 存在时才生效。
127.0.0.1:6379> set key1 666 xx
OK
127.0.0.1:6379> del key1 # 删除键
(integer) 1
127.0.0.1:6379> set key1 666 xx
(nil)
Key 存在时,set 命令正常;当 Key 不存在时,set 命令报 nil。
完整的 set 命令定义如下:
set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
下面介绍一下这些参数:
- EX 秒——设置指定的过期时间(秒),表示的是时间间隔。
- PX 毫秒——设置指定的过期时间,以毫秒为单位,表示的是时间间隔。
- EXAT 时间戳-秒——设置指定的 Key 过期的 Unix 时间,单位为秒,表示的是时间/时刻。
- PXAT 时间戳-毫秒——设置指定的 Key 到期的 Unix 时间,以毫秒为单位,表示的是时间/时刻。
- NX ——当 Key 不存在时才设置值。
- XX ——当 Key 存在时才设置值。
- KEEPTTL ——保留设置前指定键的生存时间,即替换 Key 时,保留 Key 的过期时间设置。
- GET ——如果 Key 已存在,使用 set 命令会替换 Key,加上 get 可以取得替换之前的值;如果 Key 不存在,则返回 nil。
EX、PX、EXAT、PXAT 都是设置时间的,其中 EX、PX 都是表示时间间隔,即自设置起还有多久此 Key 过期;而 EXAT 、PXAT 都是表示过期时刻,即什么时候过期,EXAT 是 10 位时间戳,如设置 2021-11-25 22:33:48
此 Key 过期,则时间戳为 1637850828;而 PXAT 是十三位的时间戳。
KEEPTTL 参数可以让 Key 继承旧 Key 的过期时间,如果一个 Key 设置了 100 秒后过期,那么当 set 命令替换 Key 前还有 90 秒过期,当替换后,新的 Key 会在 90 秒后过期。
示例:
127.0.0.1:6379> set key1 666 EX 10 get
"666"
127.0.0.1:6379> set key1 666 KEEPTTL get
"666"
string 类型也可以使用原子操作,相当于 C# 的 Interlocked.Increment、Java 的 AtomicInteger、Go 的 atomic,在 Redis 中称为 atomic increment(原子增量)。
原子操作主要有 INCR、INCRBY、DECR、DECRBY 四种,前两种是增量,后两种是减量。
127.0.0.1:6379> set value 100
OK
127.0.0.1:6379> incr value # 自加 1
(integer) 101
127.0.0.1:6379> incrby value 5 # 指定加量
(integer) 106
INCR 可以用作统计访问量、注册账号递增的 ID 等。Redis 的原子操作对所有客户端生效,避免此客户端操作时,值被另一个客户端操作覆盖。
原子增量是双精确度类型,你可以使用 incrby value 5.0
甚至 incrby value 5E+4
加值。
string 类型具有以下列出的命令,有部分命令可能已经失效或在将来的版本中去除,本文只列举部分常用的命令,读者可参考官网文档说明。
Redis 命令有上百个,即使是常用的 Linux 命令也没有这么多,没必要强硬记住这些命令。
- APPEND :追加字符串;
- DECR:原子操作,减 1;
- DECRBY:原子操作,减指定值;
- GET:获取字符串值;
- GETDEL:获取字符串值后删除 Key;
- GETEX:获取字符串并设置过期时间,单位秒;
- GETRANGE:获取字符串中的一部分字符;
- GETSET:设置字符串值并返回旧字符串值;
- INCR:原子操作,加 1;
- INCRBY:原子操作,加指定值;
- INCRBYFLOAT:原子操作,浮点数加指定值;
- MGET:获取多个字符串 key;
- MSET:同时设置多个字符串 ;
- MSETNX:对多个字符串进行原子级别的设置值,这些 key 同时改变值;
- PSETEX:获取字符串并设置过期时间,单位毫秒;
- SET:设置字符串值;
- SETEX:设置字符串并设置过期时间,单位秒;
- SETNX:字符串不存在时才设置值;
- SETRANGE:覆盖字符串的部分值,从偏移量 offset 设定的位置开始替换为新的字符串;
- STRALGO:STRALGO LCS,不知道是什么东西;
- STRLEN:获取字符串的字符数量;
位操作
位图不是实际的数据类型,而是在 String 类型上定义的一组面向位的操作,当然,从逻辑上也可以说 Bit 类型,前面提到过字符串是二进制安全的,它们的最大长度为 512 MB,使用二进制存储,因此有,因此它们适合设置为232个不同的位。
Redis 的字符串实现叫 简单动态字符串(Simple dynamic string),简称 SDS,按照存储空间的大小拆分成为了 sdshdr5
、 sdshdr8
、 sdshdr16
、 sdshdr32
、 sdshdr64
,其中 5、8、16、32、64 表示位数,例如 32 位,最大可以表示为 4GB。但是 Redis 中 Key 字符串值默认最大为 512MB,因此 sdshdr64 并没有实际使用到,sdshdr32 也是 “残血” 状态。
位操作主要有以下五个命令:
所述SETBIT命令采用作为第一个参数的比特数,和作为第二个参数的值以设置所述位,其为1或0的命令自动放大字符串,如果寻址位是当前字符串长度之外。
1,SETBIT:设置指定位的值;
2,GETBIT:仅返回指定索引处的位值,超出范围的位不会报错,会显示 0;
3,BITOP:在不同的字符串之间执行按位运算,提供的操作是 AND、OR、XOR 和 NOT。
4,BITCOUNT: 统计字符串的二进制位中 1 的个数;
5,BITPOS:返回字符串中设置为 1 或 0 的第一位的位置。
要注意,Redis 使用 C 语言编写,使用 char*
类型存储字符串,而在 C 语言中,char 是一个字节,而其他语言可能是两个字节;字符串存储的数字是字符串,以 ASCII 表示,因此,每位字符使用一个 char 表示,每个 char 8 位程度;但是中文等字符,不能按照此规则,例如 Unicode 使用4字节表示,UTF-8 使用3字节表示,那么中文的 帅
字,使用 UTF8 表示,其二进制为 11100101 10111000 10000101
。
Redis 的字符串是二进制安全的,当我们使用 C# 或 Go 语言编写时,需将字符串转为二进制数据,此时由编程语言编写的客户端决定了 Redis 中要存储的二进制数据,然后通过 TCP 发送二进制数据到 Redis 中,读者可参考 教你写个简单的 Redis Client 框架 。
首先,在字符串中,存储 1
这个字符串:
127.0.0.1:6379> set a1 1
OK
在工具中查看 a1 的 16 进制表示,在 ASCII 中使用 31 表示 "1"
,二进制表示为 0011 0001
。
所以,使用 BITCOUNT 命令时,返回结果是 3:
127.0.0.1:6379> bitcount a1
127.0.0.1:6379> bitcount a1 0 -1
(integer) 3
获取 1,3,7 位的值:
127.0.0.1:6379> getbit a1 0
(integer) 1
127.0.0.1:6379> getbit a1 1
(integer) 1
127.0.0.1:6379> getbit a1 2
(integer) 1
127.0.0.1:6379> getbit a1 7
(integer) 1
BITOP 可以让多个值之间进行位运算,即 与(&)
、 或(|)
、 异或(^)
、 非(~)
四个基本操作,多个字符串值的二进制位数可以不相等。
BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP NOT destkey srckey
示例:
127.0.0.1:6379> set a1 1
OK
127.0.0.1:6379> set a2 2
OK
127.0.0.1:6379> set a2 帅
OK
127.0.0.1:6379> bitop and a1 a2
(integer) 3
127.0.0.1:6379> get a1
"\xe5\xb8\x85"
11100101 10111000 10000101 帅
AND
00110001 1(ASCII 31)
00100001 00000000 00000000 !
11100101 10111000 10000101 帅
XOR
00110001 1(ASCII 31)
11010100 10111000 10000101 (无对于中文)
BITFIELD 也是一个很有用的命令,可以指定在某些位置填充字符。
BITFIELD 命令格式如下:
BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
在 Redis 中,整型可以使用 i8、i16 等表示,其中 i8 表示 8 位二进制组成的数字,值在 0-127 之间;而无符号使用 u8、u16 等表示。使用 BITFIELD 命令时,会返回上一次的值。
127.0.0.1:6379> BITFIELD mystring SET i8 #0 100 SET i8 #1 200
1) (integer) 0
2) (integer) 0
127.0.0.1:6379> BITFIELD mystring SET i8 #0 100 SET i8 #1 200
1) (integer) 100
2) (integer) -56
#
后面的数字表示字节偏移量,SET i8 #0 100
表示将第一个字节设置为值为 i8 表示的 100。由于 i8 范围在 0-127,因此 200 使用 u8 表示,发生溢出,结果为 -56。但是不代表有问题,因为存储的时候 i8 和 u8 表示 200 都是 11001000(0xc8),存储二进制时不会区分正负,但是当你设置了i8
,则它在返回旧值的时候,按照给定的数据类型转换,因此 11001000 会显示 -56,但是 正负不影响存入结果。
如果值过大,则会发生溢出。如:
... ...
127.0.0.1:6379> BITFIELD mystring SET i8 #0 100 SET i8 #1 257
1) (integer) 100
2) (integer) 1
BITFIELD 还有个好玩的地方是可以在某一位上使用原子增量,格式示例 incrby i8 0 1
。
127.0.0.1:6379> BITFIELD mystring SET i8 #0 1 SET i8 #1 2
1) (integer) 1
2) (integer) 2
127.0.0.1:6379> BITFIELD mystring incrby i8 0 1
1) (integer) 2
incrby 参数后面可以带上溢出控制,避免自增后的数溢出,有 WRAP、SAT、FAIL,默认是 WRAP 模式,溢出了也没问题。
而 WRAP 会从负数到正数范围内取值,如 i8 则为 -127~+128;而 SAT 模式在递增时,如果即将发生溢出,那么他不会执行此操作,将值一直保持为 127。
WRAP
127.0.0.1:6379> BITFIELD mystring SET i8 #0 127
1) (integer) 127
127.0.0.1:6379> BITFIELD mystring incrby i8 0 1
1) (integer) -128
127.0.0.1:6379> BITFIELD mystring incrby i8 0 257
1) (integer) -127
SAT
127.0.0.1:6379> BITFIELD mystring SET i8 #0 127
1) (integer) 127
127.0.0.1:6379> BITFIELD mystring overflow sat incrby i8 #0 1
1) (integer) 127
127.0.0.1:6379> BITFIELD mystring overflow sat incrby i8 #0 1
1) (integer) 127
如果溢出控制模式为 FAIL,会对检测到的上溢或下溢执行任何操作。相应的返回值设置为 NULL 以向调用者发出条件信号:
127.0.0.1:6379> BITFIELD mystring overflow fail incrby i8 #0 128
1) (nil)
列表类型
Redis 的 list 类型是 链表,区别与一些语言的 List 类型,例如 C# 的 List 、Go 的切片类型内部使用数组实现。因为 Redis list 是链表,所以 list 类型最平常的操作是头部或尾部添加/移除元素,头部或尾部的操作速度和时间跟元素数量不相关,1百万个元素和1千万个元素的操作速度是相同的。当然 list 的查找速度比数组慢。一个 list 最多可以包含 232- 1 个元素(4294967295)。
list 使用 lpush 和 rpush 命令在头部或尾部插入元素,使用 lpop 和 rpop 命令在头部或尾部移除元素:
127.0.0.1:6379> lpush list a b c d
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> rpush list 1 2 3 4
(integer) 8
127.0.0.1:6379> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"
8) "4"
lpop 和 rpop 移除元素时,可以指定弹出的元素数量,如果不指定,默认数量是 1:
127.0.0.1:6379> lpop list 2
1) "d"
2) "c"
要注意,
lpush list 1 2 3
,结果是3 2 1
,而不是1 2 3
,因为每一个元素都会从左边插入,相当于跑过第一,就是你第一。
插入过程:
1
3
2
1
除了 LPOP、RPOP,还有其它弹出头部和尾部的命令。
BLPOP、BRPOP:从多个键的头部或尾部弹出一个元素;
LMPOP(Redis 7.0 后可用):在多个键中弹出多个元素,示例: LMPOP 2 mylist mylist2 right count 3
;
BLMPOP:阻塞版本的 LMPOP;
lrange 表示从 list 的头部取一定范围的元素,其格式是 lrange {key} start stop
, start stop
表示元素下标范围,如取下标为 0-5 的六个元素:
127.0.0.1:6379> lrange list 0 5
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
如果要获取全部元素,stop 取值为 -1:
127.0.0.1:6379> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"
8) "4"
lset 可以通过指定索引设置元素的值:
127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "1"
127.0.0.1:6379> lset list 0 b
OK
127.0.0.1:6379> lrange list 0 -1
1) "b"
2) "1"
可以使用 llen 获取 list 的元素数量:
127.0.0.1:6379> llen list
(integer) 8
lindex 可以获取指定索引下标的元素的值:
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"
8) "4"
127.0.0.1:6379> lindex list 0
"d"
lrem 命令可以从 list 的左边或右边开始扫描,移除 N 个值为 value 的元素:
127.0.0.1:6379> lrem list 2 b
(integer) 1
lrem 的命令格式为 lrem {key} [count] {value}
,如果 count 为 0 ,则表示移除全部值 {value}
的元素;如果 count > 0
,则从左边开始扫描,移除对应数量的元素;如果 count < 0
,则从右边开始扫描,移除 |count|
个对应的元素。
linsert
可以在指定元素值前或后插入一个新的值,其命令格式如下:
linsert key BEFORE|AFTER pivot element
privot 元素值
127.0.0.1:6379> lpush list 3 2 1 1 2 3 3 2 2 1 1
(integer) 11
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "1"
3) "2"
4) "2"
5) "3"
6) "3"
7) "2"
8) "1"
9) "1"
10) "2"
11) "3"
127.0.0.1:6379> linsert list before 1 a
(integer) 12
127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "1"
3) "1"
4) "2"
5) "2"
6) "3"
7) "3"
8) "2"
9) "1"
10) "1"
11) "2"
12) "3"
lmove
命令可以从一个 list 中弹出头部或尾部,然后压入另一个 list 中,其格式: LMOVE source destination LEFT|RIGHT LEFT|RIGHT
。
127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> lrange test 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> lmove list test right right
"d"
127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> lrange test 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "d"
示例中,由于两个位置参数都是 right,因此只处理 “list” 中的尾部元素,并压入到 “testt” 中。
`
list: a b c d
test: 1 2 3 4
Original: https://www.cnblogs.com/whuanle/p/15708800.html
Author: 痴者工良
Title: 万字长文入门 Redis 命令、事务、锁、订阅、性能测试
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529162/
转载文章受原作者版权保护。转载请注明原作者出处!