Redis的数据类型以及使用场景,看这一篇就够啦

发布时间 2023-12-10 15:22:30作者: 小小的编程员

Redis的数据类型以及使用场景,看这一篇就够啦

原创2021-06-20 18:02·猿视野

Redis 数据类型

  • string String
  • hash HashMap
  • list LinkedList
  • set HashSet
  • sorted_set TreeSet

redis 数据存储格式

redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形式存储

数据类型指的是存储的数据的类型,也就是 value 部分的类型,key 部分永远都是字符串

string 类型

string 操作

存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
存储数据的格式:一个存储空间保存一个数据
存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用

添加/修改数据
set key value
获取数据
get key
删除数据
del key

127.0.0.1:6379> set age 100
OK
127.0.0.1:6379> get age
"100"
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> del age
(integer) 0


添加/修改多个数据
mset key1 value1 key2 value2 …
获取多个数据
mget key1 key2 …
获取数据字符个数(字符串长度)
strlen key
追加信息到原始信息后部(如果原始信息存在就追加,否则新建)
append key value
127.0.0.1:6379> mset set a 1 b 2 c 3
(error) ERR wrong number of arguments for MSET
127.0.0.1:6379> mset a 1 b 2 c 3
OK
127.0.0.1:6379> mget a b c
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> strlen a
(integer) 1
127.0.0.1:6379> append a 23
(integer) 3
127.0.0.1:6379> get a
"123"


设置数值数据增加指定范围的值
incr key  # 增加1
incrby key increment
incrbyfloat key increment

127.0.0.1:6379> get a
"123"
127.0.0.1:6379> incr a
(integer) 124
127.0.0.1:6379> incrby a 26
(integer) 150
127.0.0.1:6379> incrbyfloat a 50
"200"


设置数值数据减少指定范围的值
decr key # 减少1
decrby key increment

127.0.0.1:6379> get a
"174"
127.0.0.1:6379> decr a
(integer) 173
127.0.0.1:6379> decrby a 25
(integer) 148



string 作为数值操作
string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算。
redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发
带来的数据影响。
注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围,将报错。

9223372036854775807(java中long型数据最大值,Long.MAX_VALUE)

Tips 1:
redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性
此方案适用于所有数据库,且支持数据库集群

设置数据具有指定的生命周期
setex key seconds value  # 秒为单位
psetex key milliseconds value   # 毫秒为单位

Tips 2:
redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作


127.0.0.1:6379> setex a 5 1
OK
127.0.0.1:6379> get a
"1"
127.0.0.1:6379> get a
(nil)

127.0.0.1:6379> psetex a 5000 2
OK
127.0.0.1:6379> get a
"2"
127.0.0.1:6379> get a
"2"
127.0.0.1:6379> get a
(nil)



string 类型数据操作的注意事项
数据操作不成功的反馈与数据正常操作之间的差异
① 表示运行结果是否成功
(integer) 0 → false 失败
(integer) 1 → true 成功
② 表示运行结果值
(integer) 3 → 3 3个
(integer) 1 → 1 1个
数据未获取到
(nil)等同于null
数据最大存储量
512MB
数值计算最大范围(java中的long的最大值)
9223372036854775807

string 类型应用场景

在redis中为大V用户设定用户信息,以用户主键和属性值作为key,后台设定定时刷新策略即可
eg: user:id:3506728370:fans → 12210947
eg: user:id:3506728370:blogs → 6164
eg: user:id:3506728370:focuss → 83

127.0.0.1:6379> set user:id:3506728370:fans 12210947
OK
127.0.0.1:6379> get user:id:3506728370:fans 
"12210947"
127.0.0.1:6379> set user:id:3506728370:blogs 6164
OK
get user:id:3506728370:blogs 
"6164"
127.0.0.1:6379> set user:id:3506728370:focuss 83
OK
127.0.0.1:6379> get user:id:3506728370:focuss 
"83"


在redis中以json格式存储大V用户信息,定时刷新(也可以使用hash类型)
eg: user:id:3506728370 →
{"id":3506728370,"name":"春晚","fans":12210862,"blogs":6164, "focus":83}

Tips 3:
redis应用于各种结构型和非结构型高热度数据访问加速

hash

hash操作

添加/修改数据
hset key field value
获取数据
hget key field
hgetall key
删除数据
hdel key field1 [field2]

127.0.0.1:6379> hset a name xiaoming
(integer) 1
127.0.0.1:6379> hset a age 18
(integer) 1
127.0.0.1:6379> hget a name
"xiaoming"
127.0.0.1:6379> hgetall a
1) "name"
2) "xiaoming"
3) "age"
4) "18"
127.0.0.1:6379> hdel a name
(integer) 1
127.0.0.1:6379> hgetall a
1) "age"
2) "18"


添加/修改多个数据
hmset key field1 valuel field2 value2
获取多个数据
hmget key fieldl field2
获取哈希表中字段的数量
hlen key
获取哈希表中是否存在指定的字段
exists key field

127.0.0.1:6379> hmset a name xiaohong age 20
OK
127.0.0.1:6379> hmget a name age
1) "xiaohong"
2) "20"
127.0.0.1:6379> hlen a
(integer) 2
127.0.0.1:6379> exists a name
(integer) 1


获取哈希表中所有的字段名或字段值
keys key
hals key

127.0.0.1:6379> hkeys a
1) "age"
2) "name"
127.0.0.1:6379> hvals a
1) "20"
2) "xiaohong"


设置指定字段的数值数据増加指定范围的值
hincrby key field increment
hincrbyfloat key field increment


127.0.0.1:6379> hincrby a age 10
(integer) 30
127.0.0.1:6379> hgetall a
1) "age"
2) "30"
3) "name"
4) "xiaohong"
127.0.0.1:6379> hincrbyfloat a age 30.1
"60.1"
127.0.0.1:6379> hgetall a
1) "age"
2) "60.1"
3) "name"
4) "xiaohong"


hash类型数据操作的注意事项
hash类型下的 value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到,对应的值为(nil)
每个hash可以存储2^32-1个键值对
hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
hgetal操作可以获取全部属性,如果内部 field过多,遍历整体数据效率就会很低,有可能成为数据访问瓶颈

Hash 类型应用场景

电商网站购物车设计与实现

解决方案
以客户id作为key,每位客户创建一个hash存储结构存储对应的购物车信息
将商品编号作为field,购买数量作为value进行存储
添加商品:追加全新的field与value
浏览:遍历hash
更改数量:自增/自减,设置value值
删除商品:删除field
清空:删除key
此处仅讨论购物车中的模型设计
购物车与数据库间持久化同步、购物车与订单间关系、未登录用户购物车信息存储不进行讨论


127.0.0.1:6379> hmset 001 g01 100 g02 200
OK
127.0.0.1:6379> hmset 002 g02 1 g04 7 g05 100
OK
127.0.0.1:6379> hset 001 g03 5
(integer) 1
127.0.0.1:6379> hgetall 001
1) "g01"
2) "100"
3) "g02"
4) "200"
5) "g03"
6) "5"
127.0.0.1:6379> hdel 001 g01
(integer) 1
127.0.0.1:6379> hgetall 001
1) "g02"
2) "200"
3) "g03"
4) "5"
127.0.0.1:6379> hincrby 001 g03 1
(integer) 6
127.0.0.1:6379> hgetall 001
1) "g02"
2) "200"
3) "g03"
4) "6"

list

list操作

数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
list类型:保存多个数据,底层使用双向链表存储结构实现


添加/修改数据
lpush key value1 [value2] ……
rpush key value1 [value2] ……

获取数据
lrange key start stop
lindex key index
llen key 

获取并移除数据
lpop key
rpop key

127.0.0.1:6379> lpush list1 a b c
(integer) 3
127.0.0.1:6379> rpush list2 d e f
(integer) 3
127.0.0.1:6379> lrange list1 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> lrange list2 0 -1
1) "d"
2) "e"
3) "f"
127.0.0.1:6379> lindex list1 0
"c"
127.0.0.1:6379> lindex list1 -1
"a"
127.0.0.1:6379> lindex list1 -2
"b"
127.0.0.1:6379> llen list1
(integer) 3
127.0.0.1:6379> llen list2
(integer) 3
127.0.0.1:6379> lpop list1
"c"
127.0.0.1:6379> rpop list1
"a"
127.0.0.1:6379> llen list1
(integer) 1
127.0.0.1:6379> lpop list2 
"d"
127.0.0.1:6379> rpop list2
"f"
127.0.0.1:6379> llen list2
(integer) 1

规定时间内获取并移除数据
blpop key1 [key2] timeout
brpop key1 [key2] timeout

127.0.0.1:6379> keys *
1) "list2"
127.0.0.1:6379> lpush list1 aa
(integer) 1
127.0.0.1:6379> keys *
1) "list2"
127.0.0.1:6379> lpush list3 bb
(integer) 1
127.0.0.1:6379> 

127.0.0.1:6379> blpop list1 10
1) "list1"
2) "aa"
127.0.0.1:6379> blpop list3 10
1) "list3"
2) "bb"(3.78s)

List 类型应用场景

list 类型数据扩展操作
移除指定数据
lrem key count value  # count表示移除的个数


Tips 6:
redis 应用于具有操作先后顺序的数据控制


127.0.0.1:6379> lpush list1 a b c d a
(integer) 5
127.0.0.1:6379> lrange list1 0 -1
1) "a"
2) "d"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379> lrem list1 2 a
(integer) 2
127.0.0.1:6379> llen list1
(integer) 3
127.0.0.1:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"

set类型

set操作

新的存储需求:存储大量的数据,在查询方面提供更高的效率
需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的

set 类型数据的基本操作
添加数据
sadd key member1 [member2]
获取全部数据
smembers key 
删除数据
srem key member1 [member2]
获取集合数据总量
scard key
判断集合中是否包含指定数据
sismember key member

127.0.0.1:6379> sadd users zs
(integer) 1
127.0.0.1:6379> sadd users ls
(integer) 1
127.0.0.1:6379> sadd users ww
(integer) 1
127.0.0.1:6379> smembers users
1) "zs"
2) "ww"
3) "ls"
127.0.0.1:6379> srem users ww
(integer) 1
127.0.0.1:6379> smembers users
1) "zs"
2) "ls"
127.0.0.1:6379> scard users
(integer) 2
127.0.0.1:6379> sismember users zs
(integer) 1
127.0.0.1:6379> sismember users ww
(integer) 0

set 类型数据操作的注意事项
set 类型不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份
set 虽然与hash的存储结构相同,但是无法启用hash中存储值的空间

127.0.0.1:6379> sadd a a
(integer) 1
127.0.0.1:6379> sadd a a
(integer) 0
127.0.0.1:6379> hset a a 1
(error) WRONGTYPE Operation against a key holding the wrong kind of value

set 类型数据的扩展操作
随机获取集合中指定数量的数据
srandmember key [count]

随机获取集合中的某个数据并将该数据移出集合
spop key [count]

Tips 8:
redis 应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐,
大V推荐等

Tips 9:
redis 应用于同类信息的关联搜索,二度关联搜索,深度关联搜索
显示共同关注(一度)
显示共同好友(一度)
由用户A出发,获取到好友用户B的好友信息列表(一度)
由用户A出发,获取到好友用户B的购物清单列表(二度)
由用户A出发,获取到好友用户B的游戏充值列表(二度)

127.0.0.1:6379> sadd news n1
(integer) 1
127.0.0.1:6379> sadd news n2
(integer) 1
127.0.0.1:6379> sadd news n3
(integer) 1
127.0.0.1:6379> sadd news n4
(integer) 1
127.0.0.1:6379> srandmember news 1
1) "n1"
127.0.0.1:6379> srandmember news 1
1) "n1"
127.0.0.1:6379> srandmember news 1
1) "n1"
127.0.0.1:6379> srandmember news 1
1) "n3"
127.0.0.1:6379> scard news
(integer) 4
127.0.0.1:6379> spop news 1
1) "n1"
127.0.0.1:6379> smembers news
1) "n4"
2) "n2"
3) "n3"
127.0.0.1:6379> spop news 2
1) "n4"
2) "n3"
127.0.0.1:6379> smembers news
1) "n2"

求两个集合的交、并、差集
sinter key1 [key2]
sunion key1 [key2]
sdiff key1 [key2]


求两个集合的交、并、差集并存储到指定集合中
sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2] 

将指定数据从原始集合中移动到目标集合中
smove source destination member 

127.0.0.1:6379> sadd u1 a1
(integer) 1
127.0.0.1:6379> sadd u1 s1
(integer) 1
127.0.0.1:6379> sadd u1 b1
(integer) 1
127.0.0.1:6379> sadd u2 s1
(integer) 1
127.0.0.1:6379> sadd u2 w1
(integer) 1
127.0.0.1:6379> sinter u1 u2
1) "s1"
127.0.0.1:6379> sunion u1 u2
1) "a1"
2) "s1"
3) "w1"
4) "b1"
127.0.0.1:6379> sdiff u1 u2
1) "a1"
2) "b1"
127.0.0.1:6379> sdiff u2 u1
1) "w1"
127.0.0.1:6379> sdiffstore u3 u1 u2
(integer) 2
127.0.0.1:6379> smembers u3
1) "a1"
2) "b1"
127.0.0.1:6379> smove u2 u1 w1
(integer) 1
127.0.0.1:6379> smembers u1
1) "a1"
2) "s1"
3) "w1"
4) "b1"
127.0.0.1:6379> smembers u2
1) "s1"

Set 类型应用场景

权限校验

集团公司共具有12000名员工,内部OA系统中具有700多个角色,3000多个业务操作,23000多种数据,每位员工具有一个或多个角色,可以快速进行业务操作的权限校验

127.0.0.1:6379> sadd rid:001 getall
(integer) 1
127.0.0.1:6379> sadd rid:001 getById
(integer) 1
127.0.0.1:6379> sadd rid:002 getall
(integer) 1
127.0.0.1:6379> sadd rid:002 getCount 
(integer) 1
127.0.0.1:6379> sadd rid:002 insert
(integer) 1
127.0.0.1:6379> sunionstore uid:007  rid:001 rid:002
(integer) 4
127.0.0.1:6379> smembers uid:007
1) "insert"
2) "getById"
3) "getCount"
4) "getall"
127.0.0.1:6379> sismember uid:007 insert
(integer) 1

sorted_set

sorted_set操作

新的存储需求:数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式

需要的存储结构:新的存储模型,可以保存可排序的数据

sorted_set类型:在set的存储结构基础上添加可排序字段

sorted_set 类型数据的基本操作
添加数据
zadd key score1 member1 [score2 member2]
获取全部数据
zrange key start stop [WITHSCORES]
zrevrange key start stop [WITHSCORES]
删除数据
zrem key member [member ...]
按条件获取数据
zrangebyscore key min max [WITHSCORES] [LIMIT]
zrevrangebyscore key max min [WITHSCORES]
条件删除数据
zremrangebyrank key start stop
zremrangebyscore key min max
注意:
min与max用于限定搜索查询的条件
start与stop用于限定查询范围,作用于索引,表示开始和结束索引
offset与count用于限定查询范围,作用于查询结果,表示开始位置和数据总量
 获取集合数据总量
 zcard key
zcount key min max
集合交、并操作
zinterstore destination numkeys key [key ...]
zunionstore destination numkeys key [key ...]

127.0.0.1:6379> zadd scores 94 zs
(integer) 1
127.0.0.1:6379> zadd scores 100 ls
(integer) 1
127.0.0.1:6379> zadd scores 60 ww
(integer) 1
127.0.0.1:6379> zadd scores 47 zl
(integer) 1
127.0.0.1:6379> zrange scores 0 -1
1) "zl"
2) "ww"
3) "zs"
4) "ls"
127.0.0.1:6379> zrange scores 0 -1 withscores
1) "zl"
2) "47"
3) "ww"
4) "60"
5) "zs"
6) "94"
7) "ls"
8) "100"
127.0.0.1:6379> zrevrange scores 0 -1 withscores
1) "ls"
2) "100"
3) "zs"
4) "94"
5) "ww"
6) "60"
7) "zl"
8) "47"
127.0.0.1:6379> zrem scores ls
(integer) 1
127.0.0.1:6379> zrevrange scores 0 -1 withscores
1) "zs"
2) "94"
3) "ww"
4) "60"
5) "zl"
6) "47"

127.0.0.1:6379> zrange scores 0 -1 withscores
 1) "wangwu"
 2) "45"
 3) "zhangsan"
 4) "67"
 5) "zhouqi"
 6) "71"
 7) "qianba"
 8) "92"
 9) "lisi"
10) "99"
11) "zhangliu"
12) "100"
127.0.0.1:6379> zrangebyscore scores 50 80 withscores
1) "zhangsan"
2) "67"
3) "zhouqi"
4) "71"
127.0.0.1:6379> zrevrangebyscore scores 80 50 withscores
1) "zhouqi"
2) "71"
3) "zhangsan"
4) "67"
127.0.0.1:6379> zrangebyscore scores 50 99 withscores
1) "zhangsan"
2) "67"
3) "zhouqi"
4) "71"
5) "qianba"
6) "92"
7) "lisi"
8) "99"
127.0.0.1:6379> zrangebyscore scores 50 99 withscores limit 0 3
1) "zhangsan"
2) "67"
3) "zhouqi"
4) "71"
5) "qianba"
6) "92"
127.0.0.1:6379> zrangebyscore scores 50 99 withscores limit 0 1
1) "zhangsan"
2) "67"
127.0.0.1:6379> zremrangebyscore scores 50 70
(integer) 1
127.0.0.1:6379> zrange scores 0 -1 withscores
 1) "wangwu"
 2) "45"
 3) "zhouqi"
 4) "71"
 5) "qianba"
 6) "92"
 7) "lisi"
 8) "99"
 9) "zhangliu"
10) "100"
127.0.0.1:6379> zremrangebyrank scores 0 1
(integer) 2
127.0.0.1:6379> zrange scores 0 -1 withscores
1) "qianba"
2) "92"
3) "lisi"
4) "99"
5) "zhangliu"
6) "100"
127.0.0.1:6379> zcard scores
(integer) 3
127.0.0.1:6379> zcount scores 99 200
(integer) 2
127.0.0.1:6379> zadd s1 50 aa 60 bb 70 cc
(integer) 3
127.0.0.1:6379> zadd s2 60 aa 40 bb 90 aa
(integer) 2
127.0.0.1:6379> zadd s3 70 aa 20 bb 100 dd
(integer) 3
127.0.0.1:6379> zinterstore sss 3 s1 s2 s3   # 求和
(integer) 2
127.0.0.1:6379> zrange sss 0 -1 withscores
1) "bb"
2) "120"
3) "aa"
4) "210"
127.0.0.1:6379> zinterstore ssss 3 s1 s2 s3 aggregate max  # 求最大值
(integer) 2
127.0.0.1:6379> zrange ssss 0 -1 withscores
1) "bb"
2) "60"
3) "aa"
4) "90"
127.0.0.1:6379> help zunionstore

  ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
  summary: Add multiple sorted sets and store the resulting sorted set in a new key
  since: 2.0.0
  group: sorted_set

127.0.0.1:6379> help zinterstore

  ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
  summary: Intersect multiple sorted sets and store the resulting sorted set in a new key
  since: 2.0.0
  group: sorted_set


sorted_set 类型数据的扩展操作
获取数据对应的索引(排名)
zrank key member
zrevrank key member
score值获取与修改
zscore key member
zincrby key increment member
Tips 11:
redis 应用于计数器组合排序功能对应的排名

127.0.0.1:6379> zadd movies 143 aa 97 bb 201 cc
(integer) 3
127.0.0.1:6379> zrank movies bb
(integer) 0
127.0.0.1:6379> zrevrank movies bb
(integer) 2
127.0.0.1:6379> zscore movies aa
"143"
127.0.0.1:6379> zincrby movies 1 aa
"144"
127.0.0.1:6379> zscore movies aa
"144"

sorted_set 类型数据操作的注意事项
score保存的数据存储空间是64位,如果是整数范围是-9007199254740992~9007199254740992
score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时
候要慎重
sorted_set 底层存储还是基于set结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反
复覆盖,保留最后一次修改的结果

sorted_set 类型应用场景

微信接受消息顺序控制

使用微信的过程中,当微信接收消息后,会默认将最近接收的消息置顶,当多个好友及关注的订阅号同时发
送消息时,该排序会不停的进行交替。同时还可以将重要的会话设置为置顶。一旦用户离线后,再次打开微
信时,消息该按照什么样的顺序显示?

依赖list的数据具有顺序的特征对消息进行管理,将list结构作为栈使用
对置顶与普通会话分别创建独立的list分别管理
当某个list中接收到用户消息后,将消息发送方的id从list的一侧加入list(此处设定左侧)
多个相同id发出的消息反复入栈会出现问题,在入栈之前无论是否具有当前id对应的消息,先删除对应id
推送消息时先推送置顶会话list,再推送普通会话list,推送完成的list清除所有数据
消息的数量,也就是微信用户对话数量采用计数器的思想另行记录,伴随list操作同步更新

Tips 15:
redis 应用于基于时间顺序的数据操作,而不关注具体时间

127.0.0.1:6379> lrem 100 1 200
(integer) 0
127.0.0.1:6379> lpush 100 200
(integer) 1
127.0.0.1:6379> lrem 100 1 300
(integer) 0
127.0.0.1:6379> lpush 100 300
(integer) 2
127.0.0.1:6379> lrem 100 1 400
(integer) 0
127.0.0.1:6379> lpush 100 400
(integer) 3
127.0.0.1:6379> lrem 100 1 200
(integer) 1
127.0.0.1:6379> lpush 100 200
(integer) 3
127.0.0.1:6379> lrem 100 1 300
(integer) 1
127.0.0.1:6379> lpush 100 300
(integer) 3
127.0.0.1:6379> lrange 100 0 -1
1) "300"
2) "200"
3) "400"