Redis 4.x系列(三):Redis 数据类型之String、List
Redis 与关系数据库不同,不是以表的模式来存储数据,无法使用 SQL 来操作 Redis 数据,而是直接使用 API 发送命令来操作目标数据。
Redis 支持的数据类型与不同与关系数据库, Redis 支持的数据类型有String, List, Set, Hash, Sorted set, Bitmap, HyperLogLog, 具体使用参考Redis 数据类型, 官网:介绍 Redis 数据类型和抽象。
String
String
字符串类型是 Redis 的基本数据类型,是二进制安全的,可以包含任何类型的数据,如媒体文件或序列化的对像数据。值最大可存 512 MB 数据。可以使用其它命令来对 String 数据做更复杂的操作。
- set/get:设置存储键值对,根据键获取值。
- strlen:根据键获取值的长度。
- append:末尾追加。
- setrange:从指定索引位开始覆盖。
- getrange:返回字符串子串,由偏移量(索引位) start 和 end 确定(两者都包括)
- setnx:键不存在时设置。
- mset:一次批量设置多个键值对。
- mget:根据多个键一次获取多个对应的值。
set/get
set/get 是 Redis 操作数据的最基本命令。 set
用于设置键值对, 存储键值对数据, 成功返回 OK;get
根据键获取值, 不存在返回**(nil)**。
set 语法:
set key value [EX seconds] [PX milliseconds] [NX|XX]
NX:键不存在时设置值;XX:键存在时设置值
1
2
3
4
5
6127.0.0.1:6379> set nickName HelloKitty ex 5
OK
127.0.0.1:6379> get nickName
"HelloKitty"
127.0.0.1:6379> get nickName
(nil)get 语法:
get key
1
2
3
4
5
6127.0.0.1:6379> get email
(nil)
127.0.0.1:6379> set email hello@163.com
OK
127.0.0.1:6379> get email
"hello@163.com"
strlen
strlen:返回字符串长度
语法:strlen key
示例:
1 | 127.0.0.1:6379> set name "Trump" |
append
append:字符串末尾追加字符串,返回新字符串长度
语法:append key value
示例:
1 | 127.0.0.1:6379> set address Shenzhen |
setrange
setrange:覆盖字符串的一部分,索引起始位是 0,从指定索引位开始,返回新字符串长度。
语法:setrange key index value
示例:
1 | 127.0.0.1:6379> set welcome "Hello World!" |
getrange
返回 key 处的字符串值的子字符串,由偏移量 start 和 end 确定(两者都包括在内)。 可以使用负偏移以便从字符串的末尾开始提供偏移。 所以**-1表示最后一个字符,-2**表示倒数第二个字符,依此类推。该API通过将结果范围限制为字符串的实际长度来处理超出范围的请求。
语法:GETRANGE key start end
示例:
1 | SET mykey "This is a string" |
setnx
setnx:仅在键不存在时设置,等同于 set命令的 NX选项
若键已存在,那么 set 命令会覆盖该键对应的值,若不希望已存在的键的值被覆盖,可以使用 setnx
命令(键不存在时 set),用于原子性、仅在键不存在时设置键的值。如果设置成功,返回 1,若键已存在,则返回 0,且不覆盖原来的值。
语法:setnx key value
示例:
1 | 127.0.0.1:6379> set age 23 |
键已存在返回 0;不存在则返回 1,值设置成功
setex
setex 相当于 set 包含过期时间的简写。
语法:setex key seconds value
示例:
1 | 127.0.0.1:6379> setex name 5 HelloKitty |
mset
mset:设置多个键值对,在一次通信中设置。
语法:mset key value [key value ...]
示例:
1 | 127.0.0.1:6379> mset key1 value1 key2 value2 key3 value3 |
mget
mget:一次获取多个值,在一次通信中设置。
语法:mget key [key ....]
示例:
1 | 127.0.0.1:6379> mget key1 key2 key3 |
使用mset 和 mget命令来一次性地设置和获取多个健的值,是在一次通信中执行,可以节省网强行开销。
incr
如果 set 的 value 值是个整数(integer),可使用 incr对该键进行自增操作。
语法:incr key
示例:
1 | 127.0.0.1:6379> set age 20 |
object encoding key
object encoding key:查看编码方式, Redis 使用了三种不同的编码方式来存储字符串对象,并会根据每个字符串的值自动决定所要使用的编码方式:
- int:用于能够使用 64 位有符号整数表示的字符串。
- embstr:用于长度小于或等于 44 字节的字符串;此编码在内存使用和性能方面更有效率。
- raw:用于长度大于 44 字节的字符串。
示例:
1 | 127.0.0.1:6379> set age 20 |
List
list 列表能够存储一组有序的字符串(元素),因此可用作栈或队列,在 Redis 中与键相关联的值可以是字符串组成的列表。一个列表最多可存储 2 的 32 次方减 1 个元素。可以对列表两端插入(push)和弹出(pop)。
两个特点:
- 列表中的元素是有序的。可以通过索引下标获取某个元素或某个索引范围的元素列表。
- 列表中的元素是可重复的。
使用场景:
- lpush + lpop = Stack(栈)
- lpush + rpop = Queue(队列)
- lpush + ltrim = Capped Collection(有限集合)
- lpush + brpop = Message Queue(消息队列)
List索引下标,从左到右分别是 0 到 N-1,但从右到左分别是 -1 到 -N。
Redis 中的列表更像 Java 中的 linkedlist,插入和删除操作非常快,时间复杂度是 O(1),但索引定位很慢,时间复杂度是 O(N)。
List 列表索引定义:从左到右,起始索引是 0,最后位索引是 (N个元素 - 1)。
- lpush:左插入,排在最左端。
- rpush:右插入,排在最右端。
- linsert:在指定元素的前后位置插入。
- lpop:删除最左端一个元素。
- rpop:删除最右端一个元素。
- ltrim:删除索引范围之外的元素。
- lset:设置指定索引元素的的值。
- lrange:获取列表元素,可根据索引位范围进行查询。
- lindex:获取索引位的值,根据指定的索引位查询。
- llen:获取列表长度。
- lrem:删除指定值的元素。
Redis 内部使用 quicklist 存储列表对像,有两个配置项可选:
- list-max-ziplist-size:一个列表条目中一个内部节点的最大大小,通常使用默认值。
- list-compress-depth:列表压缩策略。当列表很长时,最可能被访问的是位于列表两端的数据,可使用此参数进行调优,获得更好的压缩比。
插入元素
list 插入操作命令有 lpush,rpush,linsert,插入成功后返回列表的长度,如果向一个不存在的键插入元素, Redis 将首先创建空列表并将其与键关联,无需人工为一个键初始化一个空列表;Redis 也会自动值为空列表的键。
lpush:左插入,将元素添加到列表的左端, 最后插入的排在最前面。
语法:
lpush key value [value ...]
示例:1
2
3
4
5
6127.0.0.1:6379> lpush hot_product product1 product2 product3
(integer) 3
127.0.0.1:6379> lrange hot_product 0 -1
1) "product3"
2) "product2"
3) "product1"rpush:右插入,将元素添加到列表的右端, 最后插入的排在最后面。
语法:
rpush key value [value ...]
示例:1
2
3
4
5
6127.0.0.1:6379> rpush cold_product pro1 pro2 pro3
(integer) 3
127.0.0.1:6379> lrange cold_product 0 -1
1) "pro1"
2) "pro2"
3) "pro3"linsert:前后插入,将元素插入到表的支点/枢轴元素之前或之后。
语法:
linsert key BEFORE|AFTER pivot value
示例:1
2
3
4
5
6
7127.0.0.1:6379> linsert cold_product after pro2 pro2-1
(integer) 4
127.0.0.1:6379> lrange cold_product 0 -1
1) "pro1"
2) "pro2"
3) "pro2-1"
4) "pro3"
查看列表
- lrange
lrange:查看列表元素,可根据索引位范围进行查询,。
语法:lrange key start_index end_index //end_index 包含自身
示例:0 到 -1表示整个列表。
1 | 127.0.0.1:6379> lrange hot_product 0 -1 |
- lindex
lindex:查看索引位的值,根据指定的索引位查询。
语法:lindex key index
示例:
1 | 127.0.0.1:6379> lindex hot_product 0 |
删除元素
当删除的键不存在时,返回(nil)。
lpop:从左删除一个,从列表的左端删除第一个元素,返回删除的元素值。
语法:
lpop key
示例:1
2
3
4
5
6
7
8
9
10
11
12
13lpop 从左端开始删除
127.0.0.1:6379> lrange hot_product 0 -1
1) "product3"
2) "product2"
3) "product1"
127.0.0.1:6379> lpop hot_product
"product3"
127.0.0.1:6379> lpop hot_product
"product2"
127.0.0.1:6379> lpop hot_product
"product1"
127.0.0.1:6379> lpop hot_product
(nil)rpop:从右删除一个,从列表的右端删除第一个元素,返回删除的元素值。
语法:
rpop key
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16rpop 从右端开始删除
127.0.0.1:6379> lrange cold_product 0 -1
1) "pro1"
2) "pro2"
3) "pro2-1"
4) "pro3"
127.0.0.1:6379> rpop cold_product
"pro3"
127.0.0.1:6379> rpop cold_product
"pro2-1"
127.0.0.1:6379> rpop cold_product
"pro2"
127.0.0.1:6379> rpop cold_product
"pro1"
127.0.0.1:6379> rpop cold_product
(nil)ltrim:删除索引范围外,删除多个元素,只保留索引范围内的元素, 索引范围之外的元素删除。
语法:
ltrim key start_idx end_idx
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16ltrim 只保留索引范围内的元素
127.0.0.1:6379> rpush hot_products product1 product2 product3 product4 product5 product6
(integer) 6
127.0.0.1:6379> lrange hot_products 0 -1
1) "product1"
2) "product2"
3) "product3"
4) "product4"
5) "product5"
6) "product6"
127.0.0.1:6379> ltrim hot_products 2 4
OK
127.0.0.1:6379> lrange hot_products 0 -1
1) "product3"
2) "product4"
3) "product5"lrem:从列表中找到等于 value 的元素进行删除。
语法:
lrem key count value
count的值分三种情况,大于 0 表示从左到右删除 count 元素;等于 0 是删除所有;**小于 0 **表示从右到左删除 count 绝对值个元素。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20添加元素
127.0.0.1:6379> lrange user_list 0 -1
1) "user3"
2) "user4"
3) "user2"
4) "user2"
5) "user5"
6) "user4"
7) "user3"
8) "user2"
9) "user1"
127.0.0.1:6379> lrem user_list 0 user2
(integer) 3
127.0.0.1:6379> lrange user_list 0 -1
1) "user3"
2) "user4"
3) "user5"
4) "user4"
5) "user3"
6) "user1"lset:设置值,设置列表中指定索引位置元素的值。
语法:
lset key index value
示例:1
2
3
4
5
6
7
8
9
10
11lset 设置指定索引位元素的值
127.0.0.1:6379> lrange hot_products 0 -1
1) "product3"
2) "product4"
3) "product5"
127.0.0.1:6379> lset hot_products 1 product_apple
OK
127.0.0.1:6379> lrange hot_products 0 -1
1) "product3"
2) "product_apple"
3) "product5"
阻塞删除
LPOP和RPOP命令有对应的阻塞版本:BLPOP 和 BRPOP,也是从列表最左端或右端弹出元素;当列表为空时,阻塞命令将客户端阻塞。使用阻塞命令必须指定一个以秒为单位的超时时间,表示最长等待几秒。当超时时间为零时,表示永久等待。
阻塞特性在任务调度场景中非常有用,多个任务执行程序等待任务调度程序分配任务,任务执行程序只需对列表使用 BLPOP或BRPOP,每当调度程序把新任务插入到列表中,任务执行程序之一便会获取到该任务。
示例:
1 | worker-1:阻塞 |
相关参考
Redis 4.x系列(三):Redis 数据类型之String、List
http://blog.gxitsky.com/2018/09/24/Redis-3-datatype-1-string-list/