Advertisement

Redis的8种数据类型,什么场景使用?

阅读量:

Redis属于一种基于键值对的数据存储系统,并采用C语言作为底层编程语言实现这一特性。我们使用的键字段限定为字符串数据类型,并且每个键值对的键具有唯一性;相应的值字段包括以下几种数据类型

5种常用的

  • 字符串类型的标记为String
  • 列表类型的标记为List
  • 集合类型的标记为Set
  • 有序集合类的实现基于zset
  • 哈希类型的标记为Hash

2种不常用的

  • bitmap位图类型
  • geo地理位置类型

1种redis5.0新增的

  • stream类型

因为key被定义为字符串类型,所以它是否存在一些通行做法或建议呢?或是提供一些建议?

redis key如何设计?

  • 通常会通过冒号来进行分隔
  • 一般情况下,默认会以表名或其缩写作为key的前缀
    • 比如:在认证系统中,用户的个人资料表中的ID字段值为001时,默认对应的键名为auth:user:001
  • 命名需具备一定的识别性,在查看时即可立即了解其含义
  • 尽量使key简短一些,在大多数情况下简短的键通常比长键更具效率;后面我们会进行详细讲解

1、String字符串

Redis的string能存储3种值的类型:字符串,整数,浮点数

1.1、应用场景

key和value都是字符串类型的应用场景极为广泛

  • 常规的赋值操作
  • 所有kv存储均可表示为value类型为字符串的数据结构,在具体实现中可采用序列化方式将其转化为字符串形式或直接将非字符串类型数据转换为其对应的字符串形式;因此这种情况最为常见。
  • incr可以通过加入watch监听机制来实现乐观锁机制。

incr实现的是数字递增

  • setnx支持分布式锁的实现。
    • 当value不存在时,在使用分布式锁的时候。是否能够完成一次成功的设置?

1.2、String字符串类型命令

命令行罗列

命令 帮助 描述
set set key value 赋值
get get key 取值
getset getset key value 取值赋值
setnx setnx key value 当key不存在时才赋值成功,存在时赋值失败 set key value NX PX 3000 原子操作,可用于分布式锁,px 设置毫秒数
append append key value 向尾部追加值
strlen strlen key 获取字符串长度
incr incr key 递增数字
incrby incrby key increment 增加指定的整数
decr decr key 递减数字
decrby decrby key decrement 减少指定的整数

命令行实际操作

复制代码
 127.0.0.1:6379> set name zhangsan

    
 OK
    
 127.0.0.1:6379> get name
    
 "zhangsan"
    
 127.0.0.1:6379> getset age 20
    
 (nil)
    
 127.0.0.1:6379> get age
    
 "20"
    
 127.0.0.1:6379> setnx lock_01 1001
    
 (integer) 1
    
 127.0.0.1:6379> setnx lock_01 1001
    
 (integer) 0
    
 127.0.0.1:6379> setnx lock_01 1002
    
 (integer) 0
    
 127.0.0.1:6379> append name 1
    
 (integer) 9
    
 127.0.0.1:6379> get name
    
 "zhangsan1"
    
 127.0.0.1:6379> strlen name
    
 (integer) 9
    
 127.0.0.1:6379> incr myid
    
 (integer) 1
    
 127.0.0.1:6379> incrby myid 2
    
 (integer) 3
    
 127.0.0.1:6379> decr myid
    
 (integer) 2
    
 127.0.0.1:6379> decrby myid 2
    
 (integer) 0
    
 # 设置分布式锁后的值,有效期20s
    
 127.0.0.1:6379> set lock_02 1002 NX PX 30000  
    
 OK
    
 # 30s内重新设置值失败
    
 127.0.0.1:6379> set lock_02 1002 NX
    
 (nil)
    
 # 30s内获取值成功
    
 127.0.0.1:6379> get lock_02
    
 "1002"
    
 # 30s后获取值为空
    
 127.0.0.1:6379> get lock_02
    
 (nil)
    
 # 重新设置值成功
    
 127.0.0.1:6379> set lock_02 1003 NX PX 30000
    
 OK
    
 127.0.0.1:6379> get lock_02
    
 "1003"
    
 127.0.0.1:6379> 
    
    
    
    
    代码解释

2、list列表

2.1、应用场景

list列表可以存储有序并且可以重复的元素。

  • 获取头部或尾部的数据极快
  • 列表最多存储2^32 -1个元素,大概40亿

通过查看以下命令我们可以明确这是一个双向列表即为一个双向列表左进右出的操作相当于依次取出元素可被视为队列结构而左进左出则相当于按顺序放入元素可被视为栈结构实际上这正是A First In First Out(FIFO)队列与A Last In First Out(LIFO)栈的基本原理

可以存储各种各样的列表数据。比如用户列表

2.2、list列表命令

命令罗列

命令 帮助 描述
lpush lpush key v1 v2 n3 ... vn 从左侧插入列表
lpop lpop key 从列表左侧取出
rpush rpush key v1 v2 n3 ... vn 从右侧插入列表
rpop rpop key 从列表右侧取出
lpushx lpushx key value 将值插入到列表头部
rpushx rpushx key value 将值插入到列表尾部
blpop blpop key timeout 从列表左侧取出,如果为空阻塞,timeout最大阻塞时间(s)
brpop brpop key timeout 从列表右侧取出,如果为空阻塞,timeout最大阻塞时间(s)
llen llen key 获得列表中元素个数
lindex lindex key index 获得列表中下标为index的元素 index从0开始
lrange lrange key start end 返回列表中指定区间的元素,区间通过start和end指定
lrem lrem key count value 删除列表中与value相等的元素 当count>0时, lrem会从列表左边开始删除;当count<0时, lrem会从列表后边开始删除;当count=0时, lrem删除所有值为value的元素
lset lset key index value 将列表index位置的元素设置成value的值
ltrim ltrim key start end 对列表进行修剪,只保留start到end区间
rpoplpush rpoplpush key1 key2 从key1列表右侧弹出并插入到key2列表左侧
brpoplpush brpoplpush key1 key2 从key1列表右侧弹出并插入到key2列表左侧,会阻塞
linsert linsert key BEFORE/AFTER pivot value 将value插入到列表,且位于值pivot之前或之后

命令执行

复制代码
 127.0.0.1:6379> lpush name2 zhangsan lisi wangwu

    
 (integer) 3
    
 127.0.0.1:6379> lpop name2
    
 "wangwu"
    
 127.0.0.1:6379> rpush name3 zhangsan lisi wangwu
    
 (integer) 3
    
 127.0.0.1:6379> rpop name3
    
 "wangwu"
    
 127.0.0.1:6379> lpushx name2 niuqi
    
 (integer) 3
    
 127.0.0.1:6379> lrange name2 0 5
    
 1) "niuqi"
    
 2) "lisi"
    
 3) "zhangsan"
    
 127.0.0.1:6379> rpushx name3 niuqi
    
 (integer) 3
    
 127.0.0.1:6379> lrange name3 0 5
    
 1) "zhangsan"
    
 2) "lisi"
    
 3) "niuqi"
    
 127.0.0.1:6379> blpop name2 1
    
 1) "name2"
    
 2) "niuqi"
    
 127.0.0.1:6379> brpop name3 1
    
 1) "name3"
    
 2) "niuqi"
    
 127.0.0.1:6379> llen name2
    
 (integer) 2
    
 127.0.0.1:6379> lindex name2 0
    
 "lisi"
    
 127.0.0.1:6379> lindex name2 1
    
 "zhangsan"
    
    
    
    
    代码解释

3、set集合

3.1、应用场景

Set集合,就是表示value唯一,并且无需的集合。

存储各种不需要顺序的数据集合。比如用户随机随机抽奖

3.2、Set集合命令

命令罗列

命令 帮助 描述
sadd sadd key v1 v2 n3 ... vn 为集合添加新成员
srem srem key mem1 mem2 ...memn 删除集合中指定成员
smembers rsmembers key 从获得集合中所有元素
spop spop key 返回集合中一个随机元素,并将该元素删除
srandmember srandmember key 将返回集合中一个随机元素,不会删除该元素
scard scard key 获得集合中元素的数量
sismember sismember key member 判断元素是否在集合内
sinter sinter key1 key2 key3 求多集合的交集
sdiff sdiffff key1 key2 key3 求多集合的差集
sunion sunion key1 key2 key3 求多集合的并集

命令操作

复制代码
 127.0.0.1:6379> sadd name4 zhangsan lisi wangwu

    
 (integer) 3
    
 127.0.0.1:6379> srem zhangsan
    
 (error) ERR wrong number of arguments for 'srem' command
    
 127.0.0.1:6379> srem name4 zhangsan
    
 (integer) 1
    
 127.0.0.1:6379> smembers name4 
    
 1) "lisi"
    
 2) "wangwu"
    
 127.0.0.1:6379> spop name4
    
 "lisi"
    
 127.0.0.1:6379> srandmember name4
    
 "wangwu"
    
 127.0.0.1:6379> scard name4
    
 (integer) 1
    
 127.0.0.1:6379> sismember name4 wangwu
    
 (integer) 1
    
 127.0.0.1:6379> sismember name4 wangwu
    
 (integer) 1
    
 # 定义两个集合 求交集,差集,并集
    
 127.0.0.1:6379> sadd name5 zhangsan lisi
    
 (integer) 2
    
 127.0.0.1:6379> sadd name6 lisi wangwu
    
 (integer) 2
    
 127.0.0.1:6379> sinter name5 name6
    
 1) "lisi"
    
 127.0.0.1:6379> sdiff name5 name6
    
 1) "zhangsan"
    
 127.0.0.1:6379> sunion name5 name6
    
 1) "lisi"
    
 2) "wangwu"
    
 3) "zhangsan"
    
    
    
    
    代码解释

4、sortedset有序集合(zset)

4.1、应用场景

sortedset是一种顺序分明的数据结构,在其元素中与普通集合类似且保证每个元素唯一。每个元素都被赋予了一个得分值(score),这些得分值决定了排序方式。这些得分值允许存在相同的数值。

有序列表在多个排行榜业务中被广泛应用:例如销量排名、用户点击率排名等。

4.2、sortedset命令

命令罗列

命令 帮助 描述
zadd zadd key score1 v1 score2 v2 score1v3 ... scoren vn 为有序集合添加新成员
zrem zrem key mem1 mem2 ...memn 删除有序集合中指定成员
zcard zcard key 获得有序集合中的元素数量
zcount zcount key min max 返回集合中score值在[min,max]区间的元素数量
zincrby zincrby key increment member 在集合的member分值上加increment
zscore zscore key member 获得集合中member的分值
zrank zrank key member 获得集合中member的排名(按分值从小到大)
zrevrank zrevrank key member 获得集合中member的排名(按分值从大到小)
zrange zrange key start end 获得集合中指定区间成员,按分数递增排序
zrevrange zrevrange key start end 获得集合中指定区间成员,按分数递减排序

命令操作

复制代码
 127.0.0.1:6379> zadd test:001 20 zhangsan 50 lisi 30 wangwu 90 niuqi  
    
 (integer) 4
    
 127.0.0.1:6379> zcount test:001 0 2
    
 (integer) 0
    
 127.0.0.1:6379> zcount test:001 20 30
    
 (integer) 2
    
 127.0.0.1:6379> zcard test:001
    
 (integer) 4
    
 127.0.0.1:6379> zrem test:001 wangwu
    
 (integer) 1
    
 127.0.0.1:6379> zincrby test:001 10 zhangsan
    
 "30"
    
 127.0.0.1:6379> zscore test:001 zhangsan
    
 "30"
    
 127.0.0.1:6379> zrank test:001 zhangsan
    
 (integer) 0
    
 127.0.0.1:6379> zrank test:001 niuqi
    
 (integer) 2
    
 127.0.0.1:6379> zrevrank test:001 niuqi
    
 (integer) 0
    
 127.0.0.1:6379> zrevrank test:001 zhangsan
    
 (integer) 2
    
 127.0.0.1:6379> zrange test:001 0 5
    
 1) "zhangsan"
    
 2) "lisi"
    
 3) "niuqi"
    
 127.0.0.1:6379> zrevrange test:001 0 5
    
 1) "niuqi"
    
 2) "lisi"
    
 3) "zhangsan"
    
    
    
    
    代码解释

5、hash散列表

5.1、应用场景

哈希的作用是将一个键映射到多个值。例如,在实际应用中, 我们可以将用户的ID作为键(key), 而将用户的完整信息作为值(value)。这样的数据类型非常适合通过哈希表进行存储。

5.2、hash命令

命令罗列

命令 帮助 描述
hset hset key field value 赋值,不区别新增或修改
hmset hmset key field1 value1 field2 value2 批量赋值
hsetnx hsetnx key field value 获得有序集合中的元素数量
hexists hexists key filed 查看某个field是否存在
hget hget key field 获取一个字段值
hmget hmget key field1 field2 ... 获取所有
hgetall hgetall key 获得集合中member的排名(按分值从小到大)
hdel hdel key field1 field2 删除指定字段
hincrby hincrby key field increment 指定字段自增increment
hlen hlen key 获得字段数量

命令操作

复制代码
 # 其实直接使用hset多个key value也是可以的

    
 127.0.0.1:6379> hset user:001 id 001 name zhangsan
    
 (integer) 2
    
 127.0.0.1:6379> hget user:001 id
    
 "001"
    
 127.0.0.1:6379> hget user:001 name
    
 "zhangsan"
    
 127.0.0.1:6379> hmset user:001 age 20 sex 1
    
 OK
    
 127.0.0.1:6379> hsetnx user:001 age 30
    
 (integer) 0
    
 127.0.0.1:6379> hexists user:001 age
    
 (integer) 1
    
 127.0.0.1:6379> hget user:001 age
    
 "20"
    
 # 使用hget多个就会报错
    
 127.0.0.1:6379> hget user:001 age name
    
 (error) ERR wrong number of arguments for 'hget' command
    
 127.0.0.1:6379> hmget user:001 age name
    
 1) "20"
    
 2) "zhangsan"
    
 127.0.0.1:6379> hgetall user
    
 (empty list or set)
    
 127.0.0.1:6379> hgetall user:001
    
 1) "id"
    
 2) "001"
    
 3) "name"
    
 4) "zhangsan"
    
 5) "age"
    
 6) "20"
    
 7) "sex"
    
 8) "1"
    
    
    
    
    代码解释

6、bitmap位图

bitmap用于执行按位运算能够极大地减少所需的空间在内存中使用少量内存时适合存储大量数据仅需1bit即可存储这些数据

比如:用户每月签到,客户以用户id为key, 日期作为偏移量,1 表示签到

命令罗列

命令 帮助 描述
setbit setbit key offffset value 设置key在offffset处的bit值(只能是0或者1)。
getbit getbit key offffset 获得key在offffset处的bit值
bitcount bitcount key 获得key的bit位为1的个数
bitpos bitpos key value 返回第一个被设置为bit值的索引值
bitop bitop and[or/xor/not] destkey key [key …] 对多个key 进行逻辑运算后存入destkey中

命令操作

复制代码
 # 本月用户签到了四天

    
 127.0.0.1:6379> setbit user:sign:001 20220801 1
    
 (integer) 0
    
 127.0.0.1:6379> setbit user:sign:001 20220803 1
    
 (integer) 0
    
 127.0.0.1:6379> setbit user:sign:001 20220809 1
    
 (integer) 0
    
 127.0.0.1:6379> setbit user:sign:001 20220820 1
    
 (integer) 0
    
 # 查看20220801是否签到了 1表示签到了 0表示没有签到
    
 127.0.0.1:6379> getbit user:sign:001 20220801
    
 (integer) 1
    
 127.0.0.1:6379> getbit user:sign:001 20220802
    
 (integer) 0
    
 # 统计用户签到的次数
    
 127.0.0.1:6379> bitcount user:sign:001 
    
 (integer) 4
    
 # 查看第一次签到的时间
    
 127.0.0.1:6379> bitpos user:sign:001 1
    
 (integer) 20220801
    
    
    
    
    代码解释

7、geo地理位置类型

7.1、应用场景

geo是Redis用来处理位置信息的。在Redis3.2中正式使用。

应用场景:

  • 记录地理位置

  • 计算距离

  • 查找"附近的人"

7.2、geo地理位置命令

命令罗列

命令 帮助 描述
geoadd geoadd key 经度 纬度 成员名称1 经度1 纬度1 成员名称2 添加地理坐标
geohash geohash key 成员名称1 成员名称2 返回标准的geohash串
geopos geopos key 成员名称1 成员名称2 返回成员经纬度
geodist geodist key 成员1 成员2 单位 计算成员间距离
georadiusbymember georadiusbymember key 成员 值单位 count 数asc[desc] 根据成员查找附近的成员

复制代码
 # 添加坐标

    
 127.0.0.1:6379> geoadd user:addr 116.21 40.00 zhangsan 116.23 49.9 lisi
    
 (integer) 2
    
 # 获取坐标的hash
    
 127.0.0.1:6379> geohash user:addr zhangsan lisi
    
 1) "wx4es3v8ck0"
    
 2) "y8feuuh0e60"
    
 # 获取坐标的经纬度
    
 127.0.0.1:6379> geopos user:addr zhangsan
    
 1) 1) "116.21000200510025024"
    
    2) "39.99999991084916218"
    
 # 计算两个用户的距离 单位米
    
 127.0.0.1:6379> geodist user:addr zhangsan lisi
    
 "1101141.4665"
    
 # 计算两个用户的距离 单位千米
    
 127.0.0.1:6379> geodist user:addr zhangsan lisi km
    
 "1101.1415"
    
 # 计算张三1200km之内的人的经纬度,距离,由近到远排出顺序
    
 127.0.0.1:6379> georadiusbymember user:addr zhangsan 1200 km withcoord withdist count 3 asc
    
 1) 1) "zhangsan"
    
    2) "0.0000"
    
    3) 1) "116.21000200510025024"
    
       2) "39.99999991084916218"
    
 2) 1) "lisi"
    
    2) "1101.1415"
    
    3) 1) "116.23000055551528931"
    
       2) "49.89999975254306719"
    
    
    
    
    代码解释

8、stream数据流类型

8.1、应用场景

stream是Redis5.0后新增的数据结构,用于可持久化的消息队列。

在应用环境中未采用第三方消息队列的方式进行设计与实现,而是采用了Redis来模拟一个类似的消息队列功能,但这一功能体系尚未成熟,因此在这种情况下需要谨慎选择.学习起来虽然有效但存在一定的风险.

8.2、stream类型命令

命令罗列

命令 帮助 描述
xadd xadd key id <*> field1 value1 将指定消息数据追加到指定队列(key)中,*表示最新生成的id(当前时间+序列号)
xread xread [COUNT count] [BLOCKmilliseconds] STREAMS key[key ...] ID [ID ...] 从消息队列中读取,COUNT:读取条数,BLOCK:阻塞读(默认不阻塞)key:队列名称 id:消息id
xrange xrange key start end [COUNT] 读取队列中给定ID范围的消息 COUNT:返回消息条数(消息id从小到大)
xrevrange xrevrange key start end [COUNT] 读取队列中给定ID范围的消息 COUNT:返回消息条数(消息id从大小到大)
xdel xdel key id 删除队列的消息
xgroup xgroup create key groupname id 创建一个新的消费组
xgroup xgroup destory key groupname 删除指定消费组
xgroup xgroup delconsumer key groupname cname 删除指定消费组中的某个消费者
xgroup xgroup setid key id 修改指定消息的最大id
xreadgroup xreadgroup group groupname consumer COUNT streams key 从队列中的消费组中创建消费者并消费数据(consumer不存在则创建)

命令操作

复制代码
 # 创建消息

    
 127.0.0.1:6379> xadd topic:001 * name zhangsan age 20
    
 "1661008860267-0"
    
 127.0.0.1:6379> xadd topic:001 * name wangwu age 24 name lisi age 35
    
 "1661008909085-0"
    
 # 查看消息
    
 127.0.0.1:6379> xrange topic:001 - + 
    
 1) 1) "1661008860267-0"
    
    2) 1) "name"
    
       2) "zhangsan"
    
       3) "age"
    
       4) "20"
    
 2) 1) "1661008909085-0"
    
    2) 1) "name"
    
       2) "wangwu"
    
       3) "age"
    
       4) "24"
    
       5) "name"
    
       6) "lisi"
    
       7) "age"
    
       8) "35"
    
 # 读取一个消息
    
 127.0.0.1:6379> xread count 1 streams topic:001 0
    
 1) 1) "topic:001"
    
    2) 1) 1) "1661008860267-0"
    
      2) 1) "name"
    
         2) "zhangsan"
    
         3) "age"
    
         4) "20"
    
 # 创建一个消费组
    
 127.0.0.1:6379> xgroup create topic:001 group1 0
    
 OK
    
 # 使用消费组消费数据
    
 127.0.0.1:6379> xreadgroup group group1 user1 count 1 streams topic:001 >
    
 1) 1) "topic:001"
    
    2) 1) 1) "1661008860267-0"
    
      2) 1) "name"
    
         2) "zhangsan"
    
         3) "age"
    
         4) "20"
    
 # 使用消费组消费数据 继续消费 总共两条
    
 127.0.0.1:6379> xreadgroup group group1 user1 count 1 streams topic:001 >
    
 1) 1) "topic:001"
    
    2) 1) 1) "1661008909085-0"
    
      2) 1) "name"
    
         2) "wangwu"
    
         3) "age"
    
         4) "24"
    
         5) "name"
    
         6) "lisi"
    
         7) "age"
    
         8) "35"
    
 # 消费完了,没有啦
    
 127.0.0.1:6379> xreadgroup group group1 user1 count 1 streams topic:001 >
    
 (nil)
    
    
    
    
    代码解释

9、小结

Redis功能之所以非常强大, 也与其丰富多样的数据类型息息相关; 在不同业务场景下, 可以选择最适合的数据类型; 这样便能够更加高效地实现所需功能.

全部评论 (0)

还没有任何评论哟~