在进入正题之前,我们先下载一个工具【redis desktop manager】用于可视化观察数据结构。
在redis中每一个唯一的key值对应一个value,这里的key就是数据的名字,而value就是用来存储的数据,它可以有不同的数据结构。在redis共提供了5中数据类型,接下来我们将逐一介绍每种数据类型的特性及使用方法。
类型
|
描述
|
string
|
字符串
|
list
|
列表
|
hash
|
字典
|
set
|
集合
|
zset
|
有序集合
|
1、string
string是redis最简单的数据结构,它就是一个字符数组。当存储的字符数据小于1MB的时候,每次扩容会翻倍现有空间,如果字
符数据大于
1MB,每次扩容会扩
1MB,当然string结构的value是有长度上限的,redis把它的上限设置为了
512MB。
命令
|
描述
|
set
|
新增值
|
get
|
获取值
|
del
|
删除值
|
mset
|
批量新增
|
mget
|
返回列表
|
incr
|
自增 1
|
incrby
|
增加指定数值
|
命令演示:
# 设置value
127.0.0.1:6379> set iphone-name ranen
OK
127.0.0.1:6379> set iphone2-name echo
OK
# 返回列表
127.0.0.1:6379> mget iphone-name iphone2-name
1) "ranen"
2) "echo"
# 批量设置
127.0.0.1:6379> mset ranen-name wangp echo-name qiujy
OK
# 返回列表
127.0.0.1:6379> mget ranen-name echo-name
1) "wangp"
2) "qiujy"
# 删除
127.0.0.1:6379> del ranen-name
(integer) 1
127.0.0.1:6379> mget ranen-name echo-name
1) (nil)
2) "qiujy"
# value 为 int 类型可以实现自增功能,通常自增范围在 signed long 的 [min,max] 之间
127.0.0.1:6379> set ranen-age 26
OK
127.0.0.1:6379> get ranen-age
"26"
# 自增 1
127.0.0.1:6379> incr ranen-age
(integer) 27
127.0.0.1:6379> get ranen-age
"27"
# 增加 10
127.0.0.1:6379> incrby ranen-age 10
(integer) 37
127.0.0.1:6379> get ranen-age
"37"
# 减 10
127.0.0.1:6379> incrby ranen-age -10
(integer) 27
127.0.0.1:6379> get ranen-age
"27"
使用场景:
-
缓存用户信息,将用户数据、权限数据、tocken转为json字符串,然后存储在redis。
-
生成token存放在redis。
2、list
list我们可以同向类比为java里面的LinkedList,意味着插入和删除都很快,但是索引定位会很慢。一般我们使用list实现队列、栈操作。
list的数据结构并非一个简单的链表,而是一个“快速列表”,快速列表每个节点又都为一个压缩列表。这样既保证了内存的使用效率,又便于数据的push和pop。
有兴趣的可以去看下redis 的ziplist.h、ziplist.c。这里可知的是ziplist使用的是一整块连续内存,存储效率较高。但是每次修改数据都会引发realloc。 若ziplist长度较长的时候,每次修改数据会引发大量的数据拷贝,效率会进一步低下。而“快速列表”就是为了优化数据存取、修改问题引入的。
命令
|
描述
|
rpush
|
右侧添加值
|
rpop
|
右侧弹出值
|
lpush
|
左侧添加值
|
lpop
|
左侧弹出值
|
llen
|
获取列表长度
|
命令演示:
# 队列:右进 左出
127.0.0.1:6379> rpush channel msg1 msg2 msg3 msg4
(integer) 4
127.0.0.1:6379> llen channel
(integer) 4
127.0.0.1:6379> lpop channel
"msg1"
127.0.0.1:6379> llen channel
(integer) 3
127.0.0.1:6379> lpop channel
"msg2"
127.0.0.1:6379> lpop channel
"msg3"
127.0.0.1:6379> lpop channel
"msg4"
127.0.0.1:6379> lpop channel
(nil)
# 栈:右进 右出
127.0.0.1:6379> rpush stack value1 value2 value3 value4
(integer) 4
127.0.0.1:6379> llen stack
(integer) 4
127.0.0.1:6379> rpop stack
"value4"
127.0.0.1:6379> rpop stack
"value3"
127.0.0.1:6379> rpop stack
"value2"
127.0.0.1:6379> rpop stack
"value1"
127.0.0.1:6379> rpop stack
(nil)
127.0.0.1:6379> rpush list value1 value2 value3 value4
(integer) 4
# 获取所有数据
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value2"
3) "value3"
4) “value4”
# 获取索引为 0 的数据
127.0.0.1:6379> lindex list 0
"value1"
127.0.0.1:6379> lindex list 1
“value2"
# 截取(保留)list 从索引1 到索引倒数第 1 个
127.0.0.1:6379> ltrim list 1 -1
OK
127.0.0.1:6379> lrange list 0 -1
1) "value2"
2) "value3"
3) “value4"
# 截取索引 1 到 索引 0 的数据,小于 0 则为清空列表
127.0.0.1:6379> ltrim list 1 0
OK
127.0.0.1:6379> lrange list 0 -1
(empty list or set)
127.0.0.1:6379> llen list
(integer) 0
使用场景:
-
异步队列,无ack机制的消息推送。
-
生产消费模型。