[redis]基础数据类型

3 篇文章 0 订阅
3 篇文章 0 订阅
    在进入正题之前,我们先下载一个工具【redis desktop manager】用于可视化观察数据结构。
    
    在redis中每一个唯一的key值对应一个value,这里的key就是数据的名字,而value就是用来存储的数据,它可以有不同的数据结构。在redis共提供了5中数据类型,接下来我们将逐一介绍每种数据类型的特性及使用方法。
前言:使用range系列命令的时候,0代表第一位,负数代表倒数位数,如-1代表倒数第一个-2代表倒数第二个,以此类推
 
类型
描述
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机制的消息推送。
  • 生产消费模型。
 
3、hash
    hash类型也就是字典类型,可以类比java中的hashmap。hash是无序的,存储的都是键值对。数据结构也和HashMap的一致为二维结构,通过数组和链表共同实现。当增加数据的时候会根据key优先计算数组位置,找到位置后将数据串接在当前数组对应的链表中。与java HashMap的不同是,redis的值只能为字符串。

 

 
命令
描述
hset
添加值
hgetall
获取所有值,key、value依次列出
hlen
记录行数
hget
获取记录值
hmset
批量设置
hmget
批量获取
命令演示:
# 设置hash 数据 people的name 为 wangp
127.0.0.1:6379> hset people name wangp
(integer) 1
127.0.0.1:6379> hset people age 26
(integer) 1
127.0.0.1:6379> hset people sex 男
(integer) 1
# 获取hash全量数据,key和value间隔打印
127.0.0.1:6379> hgetall people
1) "name"
2) "wangp"
3) "age"
4) "26"
5) "sex"
6) "\xe7\x94\xb7"
127.0.0.1:6379> hlen people
(integer) 3
# 更新年龄
127.0.0.1:6379> hset people age 27
(integer) 0      # 更新成功
127.0.0.1:6379> hgetall people
1) "name"
2) "wangp"
3) "age"
4) "27"
5) "sex"
6) "\xe7\x94\xb7”
# 批量获取属性列表
127.0.0.1:6379> hmget people name age sex
1) "wangp"
2) "27"
3) "\xe7\x94\xb7”
# 批量设置hash 属性
127.0.0.1:6379> hmset people email 616444@qq.com address 浙江杭州萧山区
OK
127.0.0.1:6379> hgetall people
1) "name"
2) "wangp"
3) "age"
4) "27"
5) "sex"
6) "\xe7\x94\xb7"
7) "email"
8) "616444@qq.com"
9) "address"
10) "\xe6\xb5\x99\xe6\xb1\x9f\xe6\x9d\xad\xe5\xb7\x9e\xe8\x90\xa7\xe5\xb1\xb1\xe5\x8c\xba”
# hash针对整形属性同样支持 自增
127.0.0.1:6379> hincrby people age 1
(integer) 28

 

使用场景:
  • 存储用户数据,与string不同,可以按属性存储、提取数据,而非像string一样全部取出,序列化重新存入。在网络环境中可以节省不小的流量开支。
4、set
    Set类型相当于java中的HashSet,其中存储的数据是无序且唯一的。也可以理解为是一个value为空只有key的Hash。
命令演示:
# set中添加一个值
127.0.0.1:6379> sadd car BMW
(integer) 1
# 重复添加,添加失败
127.0.0.1:6379> sadd car BMW
(integer) 0
# 添加小写,证明大小写敏感
127.0.0.1:6379> sadd car bmw
(integer) 1
# 批量添加 直接空格分隔
127.0.0.1:6379> sadd car audi benz MAYBACH
(integer) 3
# 显示所有值列表
127.0.0.1:6379> smembers car
1) "bmw"
2) "audi"
3) "benz"
4) "BMW"
5) “MAYBACH"
# 判断一个值是否存在
127.0.0.1:6379> sismember car bmw
(integer) 1
127.0.0.1:6379> sismember car shuangzuan
(integer) 0
# 从car 中弹出一个值
127.0.0.1:6379> spop car
"benz"
127.0.0.1:6379> spop car
"MAYBACH"
127.0.0.1:6379> smembers car
1) "bmw"
2) "audi"
3) "BMW"

 

使用场景:
  • 利用Set的唯一性可实现对业务主键去重处理。
5、zset
    对于zset我们可以理解为是一个按权重排序的SortedSet,它和set的差别就是对每一个key都有一个对应的score值,这个值便是zset数据的排序依据。
    zset为有序集合,那么普通链表就肯定不能支持 频繁的插入特定位置逻辑,因而redis采用了跳跃列表的数据结构,跳跃列表为一个有层级的集合,通过找到最近层级,可以快速的跳跃切换指针位置从而插入特定数值。具体结构可参考下图。要知道随着元素的增加,层级也同样会增加。数据越多,那么到达顶层的概率就会越大。
命令演示:
# 以下为关注列表示例
# 20200101 wangsicong关注了我
127.0.0.1:6379> zadd myfollower 20200101 wangsicong@weibo.com
(integer) 1
127.0.0.1:6379> zadd myfollower 20200102 zhaobanshan@weibo.com
(integer) 1
127.0.0.1:6379> zadd myfollower 20190102 panweibo@weibo.com
(integer) 1
127.0.0.1:6379> zadd myfollower 20161202 yiyangqianxi@weibo.com
(integer) 1
127.0.0.1:6379> zadd myfollower 20211202 wangyuan@weibo.com
(integer) 1
# 显示全部关注列表
127.0.0.1:6379> zrange myfollower 0 -1
1) "yiyangqianxi@weibo.com"
2) "panweibo@weibo.com"
3) "wangsicong@weibo.com"
4) "zhaobanshan@weibo.com"
5) "wangyuan@weibo.com”
# 逆序打印
127.0.0.1:6379> zrevrange myfollower 0 -1
1) "wangyuan@weibo.com"
2) "zhaobanshan@weibo.com"
3) "wangsicong@weibo.com"
4) "panweibo@weibo.com"
5) "yiyangqianxi@weibo.com”
# 统计共有多少数据
127.0.0.1:6379> zcard myfollower
(integer) 5
# 获取 wangyuan@weibo.com 的 关注时间
127.0.0.1:6379> zscore myfollower wangyuan@weibo.com
“20211202"
# 获取 wangyuan@weibo.com 的排序
127.0.0.1:6379> zrank myfollower wangyuan@weibo.com
(integer) 4
# 找到19990101到20201230之间关注的人的ID
127.0.0.1:6379> zrangebyscore myfollower 19990101 20201230
1) "yiyangqianxi@weibo.com"
2) "panweibo@weibo.com"
3) "wangsicong@weibo.com"
4) "zhaobanshan@weibo.com”
# 找到 负无穷到 20201230 之间的关注者,也就是 20201230之前关注我的人
127.0.0.1:6379> zrangebyscore myfollower -inf 20201230
1) "yiyangqianxi@weibo.com"
2) "panweibo@weibo.com"
3) "wangsicong@weibo.com"
4) "zhaobanshan@weibo.com”
# 赵本山老师取消了关注我
127.0.0.1:6379> zrem myfollower zhaobanshan@weibo.com
(integer) 1
127.0.0.1:6379> zrangebyscore myfollower -inf 20201230
1) "yiyangqianxi@weibo.com"
2) "panweibo@weibo.com"
3) "wangsicong@weibo.com"
127.0.0.1:6379> zrange myfollower 0 -1
1) "yiyangqianxi@weibo.com"
2) "panweibo@weibo.com"
3) "wangsicong@weibo.com"
4) "wangyuan@weibo.com"

 

使用场景:
  • 学生按成绩排序,其中value就是学生名字,score便是学生的分数。
  • 微博关注列表,value为微博id,score为微博的关注时间。
 
二、过期时间
    Redis所有数据结构都可以设置过期时间,时间到了就会自动删除对象,这里删除的是整个redis的对象,而不是hash里面的一个key。
    
# 新建一个计时器
127.0.0.1:6379> set timer ranen
OK
# 计时器 500s 过期
127.0.0.1:6379> expire timer 500
(integer) 1
# 查看剩余长时间过期
127.0.0.1:6379> ttl timer
(integer) 494
# 覆盖新的timer
127.0.0.1:6379> set timer ranen
OK
# 原有超期时间自动作废
127.0.0.1:6379> ttl timer
(integer) -1
# 设置500s超期,如果timer不存在则创建
127.0.0.1:6379> set timer ranen ex 500 nx
(nil)
127.0.0.1:6379> ttl timer
(integer) -1
# 设置500s超期,如果timer1不存在则创建
127.0.0.1:6379> set timer1 ranen ex 500 nx
OK
# 未被覆盖
127.0.0.1:6379> ttl timer
(integer) -1
# 500s计时器创建成功
127.0.0.1:6379> ttl timer1
(integer) 451

 


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值